From 7c246a09972c0c32c1f2a50c1767aca6d4c49cc1 Mon Sep 17 00:00:00 2001 From: Andy Theuninck Date: Fri, 29 Jul 2016 14:45:38 -0500 Subject: [PATCH 0001/1148] Include import line in Java application --- docs/installation.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/installation.md b/docs/installation.md index 3c3f18255..09d7bc7e8 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -54,6 +54,8 @@ For React Native v0.29.0 or above: 2. in your application object, add: ```java +import com.airbnb.android.react.maps.MapsPackage; + public class MyApplication extends Application implements ReactApplication { private final ReactNativeHost reactNativeHost = new ReactNativeHost(this) { @Override protected List getPackages() { From c2081739c70496fc51fa574c415cf35ffce43317 Mon Sep 17 00:00:00 2001 From: Nick Sarafa Date: Mon, 15 Aug 2016 14:38:52 -0400 Subject: [PATCH 0002/1148] update installation guide with alternative Android meta tag (#465) --- docs/installation.md | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/docs/installation.md b/docs/installation.md index 3c3f18255..ae5448d95 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -95,7 +95,7 @@ For older versions of React Native: 4. Specify your Google Maps API Key: > To develop is recommended a ***Browser Key*** without refeer restriction. Go to https://console.developers.google.com/apis/credentials to check your credentials. -Add your API key to your manifest file: +Add your **Browser** API key to your manifest file: ```xml @@ -104,6 +104,18 @@ Add your API key to your manifest file: android:name="com.google.android.geo.API_KEY" android:value="{{Your Google maps API Key Here}}"/> +``` + > If that doesn't work try using an ***Android Key*** without refeer restriction. Go to https://console.developers.google.com/apis/credentials to check your credentials. + +Add your **Android** API key to your manifest file: + +```xml + + + + ``` 5. ensure that you have Google Play Services installed: From ed0b5099f5b9ed333b285ee1ae7334e2847ca6ce Mon Sep 17 00:00:00 2001 From: Mark Florisson Date: Mon, 15 Aug 2016 19:39:04 +0100 Subject: [PATCH 0003/1148] Clarify which build.gradle to modify in Installation.md (#460) --- docs/installation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/installation.md b/docs/installation.md index ae5448d95..f1a6f9539 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -40,7 +40,7 @@ To install using Cocoapods, simply insert the following line into your `Podfile` ## Android -1. in your `build.gradle` add: +1. in your `android/app/build.gradle` add: ```groovy ... dependencies { From 2407b71e50aec3fb5f73c28f544be5d025624c53 Mon Sep 17 00:00:00 2001 From: Fidan Hakaj Date: Mon, 15 Aug 2016 20:40:20 +0200 Subject: [PATCH 0004/1148] Update mapview.md (#440) Added a note explaining that followsUserLocation property is iOS specific (cf. https://github.com/lelandrichardson/react-native-maps/blob/master/components/MapView.js#L67). PS: It could be great to have for each component API table, an extra column showing if features are platform specific. What do you think ? --- docs/mapview.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/mapview.md b/docs/mapview.md index 1b8abc8d7..34999e236 100644 --- a/docs/mapview.md +++ b/docs/mapview.md @@ -8,7 +8,7 @@ | `initialRegion` | `Region` | | The initial region to be displayed by the map. Use this prop instead of `region` only if you don't want to control the viewport of the map besides the initial region.

Changing this prop after the component has mounted will not result in a region change.

This is similar to the `initialValue` prop of a text input. | `mapType` | `String` | `"standard"` | The map type to be displayed.

- standard: standard road map (default)
- satellite: satellite view
- hybrid: satellite view with roads and points of interest overlayed
- terrain: (Android only) topographic view | `showsUserLocation` | `Boolean` | `false` | If `true` the app will ask for the user's location. **NOTE**: You need to add `NSLocationWhenInUseUsageDescription` key in Info.plist to enable geolocation, otherwise it is going to *fail silently*! -| `followsUserLocation` | `Boolean` | `false` | If `true` the map will focus on the user's location. This only works if `showsUserLocation` is true and the user has shared their location. +| `followsUserLocation` | `Boolean` | `false` | If `true` the map will focus on the user's location. This only works if `showsUserLocation` is true and the user has shared their location. **Note**: iOS only. | `showsPointsOfInterest` | `Boolean` | `true` | If `false` points of interest won't be displayed on the map. | `showsCompass` | `Boolean` | `true` | If `false` compass won't be displayed on the map. | `showsScale` | `Boolean` | `true` | A Boolean indicating whether the map shows scale information. From d96d39c279b11b9f193db52aab6a675210f5a427 Mon Sep 17 00:00:00 2001 From: johnryan Date: Tue, 23 Aug 2016 17:01:31 -0400 Subject: [PATCH 0005/1148] Added check on marker class in predicate --- ios/AirMaps/AIRMapManager.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ios/AirMaps/AIRMapManager.m b/ios/AirMaps/AIRMapManager.m index 4fa8df4c9..6794577a1 100644 --- a/ios/AirMaps/AIRMapManager.m +++ b/ios/AirMaps/AIRMapManager.m @@ -176,7 +176,7 @@ - (UIView *)view NSPredicate *filterMarkers = [NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary *bindings) { AIRMapMarker *marker = (AIRMapMarker *)evaluatedObject; - return [markers containsObject:marker.identifier]; + return [marker isKindOfClass:[AIRMapMarker class]] && [markers containsObject:marker.identifier]; }]; NSArray *filteredMarkers = [mapView.annotations filteredArrayUsingPredicate:filterMarkers]; From 064c67b96320ef7732cc1ee2eb5c57a8cc815c6f Mon Sep 17 00:00:00 2001 From: Saber King Date: Thu, 25 Aug 2016 15:15:28 +0100 Subject: [PATCH 0006/1148] Typo :) --- docs/installation.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/installation.md b/docs/installation.md index f1a6f9539..47ddc8d2a 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -168,12 +168,12 @@ module.exports = React.createClass({ From a5ef4ccf5c5abd2bd84f1ecc09020bc17cbe6152 Mon Sep 17 00:00:00 2001 From: Denis Date: Thu, 25 Aug 2016 17:29:16 +0300 Subject: [PATCH 0007/1148] absoluteFillObject https://github.com/facebook/react-native/blob/8eed600d5b2be78c405f7ef139a7b0e4a2480c85/Libraries/StyleSheet/StyleSheet.js#L108 --- README.md | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/README.md b/README.md index 6b36fb930..0c4fef84c 100644 --- a/README.md +++ b/README.md @@ -373,11 +373,7 @@ Pass an array of marker identifiers to have the map re-focus. ```javascript const styles = StyleSheet.create({ map: { - position: 'absolute', - top: 0, - left: 0, - right: 0, - bottom: 0, + ...StyleSheet.absoluteFillObject, }, }); ``` From 4a9a8cd3a4fde030a2968871990cef62b765a431 Mon Sep 17 00:00:00 2001 From: Spike Brehm Date: Thu, 25 Aug 2016 11:24:52 -0700 Subject: [PATCH 0008/1148] Add ESLint --- .eslintignore | 1 + .eslintrc | 13 +++++++++++++ example/.eslintrc | 5 +++++ package.json | 12 +++++++++--- 4 files changed, 28 insertions(+), 3 deletions(-) create mode 100644 .eslintignore create mode 100644 .eslintrc create mode 100644 example/.eslintrc diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 000000000..3c3629e64 --- /dev/null +++ b/.eslintignore @@ -0,0 +1 @@ +node_modules diff --git a/.eslintrc b/.eslintrc new file mode 100644 index 000000000..2ab7f953b --- /dev/null +++ b/.eslintrc @@ -0,0 +1,13 @@ +{ + "parser": "babel-eslint", + "extends": "airbnb", + "plugins": [ + "prefer-object-spread" + ], + "rules": { + "prefer-object-spread/prefer-object-spread": 2, + "react/jsx-filename-extension": 0, + "no-use-before-define": 0, + "no-underscore-dangle": 0 + } +} diff --git a/example/.eslintrc b/example/.eslintrc new file mode 100644 index 000000000..7753f32e7 --- /dev/null +++ b/example/.eslintrc @@ -0,0 +1,5 @@ +{ + "rules": { + "no-console": 0 + } +} diff --git a/package.json b/package.json index 00a4591f2..4f13c1cc2 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,8 @@ "author": "Leland Richardson ", "version": "0.7.1", "scripts": { - "start": "react-native start" + "start": "react-native start", + "lint": "eslint ." }, "repository": { "type": "git", @@ -25,8 +26,13 @@ "react-native": ">=0.30.0" }, "devDependencies": { - "react": "15.2.0", - "react-native": "^0.29.2" + "babel-eslint": "^6.1.2", + "eslint": "^3.3.1", + "eslint-config-airbnb": "^10.0.1", + "eslint-plugin-import": "^1.14.0", + "eslint-plugin-jsx-a11y": "^2.1.0", + "eslint-plugin-prefer-object-spread": "^1.1.0", + "eslint-plugin-react": "^6.1.2" }, "rnpm": { "android": { From 9be72f107600936fbda12579c64b8173bbe0b46d Mon Sep 17 00:00:00 2001 From: Denis Date: Thu, 25 Aug 2016 23:06:35 +0300 Subject: [PATCH 0009/1148] StyleSheet.absoluteFillObject --- docs/installation.md | 12 ++---------- example/App.js | 6 +----- example/examples/AnimatedMarkers.js | 12 ++---------- example/examples/AnimatedViews.js | 12 ++---------- example/examples/Callouts.js | 12 ++---------- example/examples/DefaultMarkers.js | 12 ++---------- example/examples/DisplayLatLng.js | 12 ++---------- example/examples/DraggableMarkers.js | 12 ++---------- example/examples/EventListener.js | 6 +----- example/examples/FitToSuppliedMarkers.js | 12 ++---------- example/examples/LoadingMap.js | 12 ++---------- example/examples/MarkerTypes.js | 12 ++---------- example/examples/Overlays.js | 12 ++---------- example/examples/PolygonCreator.js | 12 ++---------- example/examples/PolylineCreator.js | 12 ++---------- example/examples/TakeSnapshot.js | 12 ++---------- example/examples/ViewsAsMarkers.js | 12 ++---------- 17 files changed, 32 insertions(+), 160 deletions(-) diff --git a/docs/installation.md b/docs/installation.md index 47ddc8d2a..5a4206aa2 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -139,22 +139,14 @@ If you have a blank map issue, ([#118](https://github.com/lelandrichardson/react ... const styles = StyleSheet.create({ container: { - position: 'absolute', - top: 0, - left: 0, - right: 0, - bottom: 0, + ...StyleSheet.absoluteFillObject, height: 400, width: 400, justifyContent: 'flex-end', alignItems: 'center', }, map: { - position: 'absolute', - top: 0, - left: 0, - right: 0, - bottom: 0, + ...StyleSheet.absoluteFillObject, }, }); diff --git a/example/App.js b/example/App.js index bec55f008..4a040cf16 100644 --- a/example/App.js +++ b/example/App.js @@ -94,11 +94,7 @@ var App = React.createClass({ var styles = StyleSheet.create({ container: { - position: 'absolute', - top: 0, - left: 0, - right: 0, - bottom: 0, + ...StyleSheet.absoluteFillObject, justifyContent: 'flex-end', alignItems: 'center', }, diff --git a/example/examples/AnimatedMarkers.js b/example/examples/AnimatedMarkers.js index 22001efd1..261f48521 100644 --- a/example/examples/AnimatedMarkers.js +++ b/example/examples/AnimatedMarkers.js @@ -69,20 +69,12 @@ var AnimatedMarkers = React.createClass({ var styles = StyleSheet.create({ container: { - position: 'absolute', - top: 0, - left: 0, - right: 0, - bottom: 0, + ...StyleSheet.absoluteFillObject, justifyContent: 'flex-end', alignItems: 'center', }, map: { - position: 'absolute', - top: 0, - left: 0, - right: 0, - bottom: 0, + ...StyleSheet.absoluteFillObject, }, bubble: { flex: 1, diff --git a/example/examples/AnimatedViews.js b/example/examples/AnimatedViews.js index 519f22243..27aca9c7d 100644 --- a/example/examples/AnimatedViews.js +++ b/example/examples/AnimatedViews.js @@ -390,11 +390,7 @@ var AnimatedViews = React.createClass({ var styles = StyleSheet.create({ container: { - position: 'absolute', - top: 0, - left: 0, - right: 0, - bottom: 0, + ...StyleSheet.absoluteFillObject, }, itemContainer: { backgroundColor: 'transparent', @@ -407,11 +403,7 @@ var styles = StyleSheet.create({ }, map: { backgroundColor: 'transparent', - position: 'absolute', - top: 0, - left: 0, - bottom: 0, - right: 0, + ...StyleSheet.absoluteFillObject, }, item: { width: ITEM_WIDTH, diff --git a/example/examples/Callouts.js b/example/examples/Callouts.js index 0034a30d3..ae1f2d8e8 100644 --- a/example/examples/Callouts.js +++ b/example/examples/Callouts.js @@ -117,20 +117,12 @@ var Callouts = React.createClass({ var styles = StyleSheet.create({ container: { - position: 'absolute', - top: 0, - left: 0, - right: 0, - bottom: 0, + ...StyleSheet.absoluteFillObject, justifyContent: 'flex-end', alignItems: 'center', }, map: { - position: 'absolute', - top: 0, - left: 0, - right: 0, - bottom: 0, + ...StyleSheet.absoluteFillObject, }, bubble: { flex: 1, diff --git a/example/examples/DefaultMarkers.js b/example/examples/DefaultMarkers.js index b4c978d5a..62b3fbd73 100644 --- a/example/examples/DefaultMarkers.js +++ b/example/examples/DefaultMarkers.js @@ -78,20 +78,12 @@ var DefaultMarkers = React.createClass({ var styles = StyleSheet.create({ container: { - position: 'absolute', - top: 0, - left: 0, - right: 0, - bottom: 0, + ...StyleSheet.absoluteFillObject, justifyContent: 'flex-end', alignItems: 'center', }, map: { - position: 'absolute', - top: 0, - left: 0, - right: 0, - bottom: 0, + ...StyleSheet.absoluteFillObject, }, bubble: { backgroundColor: 'rgba(255,255,255,0.7)', diff --git a/example/examples/DisplayLatLng.js b/example/examples/DisplayLatLng.js index 8d8d70d8e..09c37641c 100644 --- a/example/examples/DisplayLatLng.js +++ b/example/examples/DisplayLatLng.js @@ -83,20 +83,12 @@ var DisplayLatLng = React.createClass({ var styles = StyleSheet.create({ container: { - position: 'absolute', - top: 0, - left: 0, - right: 0, - bottom: 0, + ...StyleSheet.absoluteFillObject, justifyContent: 'flex-end', alignItems: 'center', }, map: { - position: 'absolute', - top: 0, - left: 0, - right: 0, - bottom: 0, + ...StyleSheet.absoluteFillObject, }, bubble: { backgroundColor: 'rgba(255,255,255,0.7)', diff --git a/example/examples/DraggableMarkers.js b/example/examples/DraggableMarkers.js index ad888a837..3e9a47373 100644 --- a/example/examples/DraggableMarkers.js +++ b/example/examples/DraggableMarkers.js @@ -76,20 +76,12 @@ var MarkerTypes = React.createClass({ var styles = StyleSheet.create({ container: { - position: 'absolute', - top: 0, - left: 0, - right: 0, - bottom: 0, + ...StyleSheet.absoluteFillObject, justifyContent: 'flex-end', alignItems: 'center', }, map: { - position: 'absolute', - top: 0, - left: 0, - right: 0, - bottom: 0, + ...StyleSheet.absoluteFillObject, }, }); diff --git a/example/examples/EventListener.js b/example/examples/EventListener.js index 1515ee80f..2f1f90609 100644 --- a/example/examples/EventListener.js +++ b/example/examples/EventListener.js @@ -117,11 +117,7 @@ var DisplayLatLng = React.createClass({ var styles = StyleSheet.create({ container: { - position: 'absolute', - top: 0, - left: 0, - right: 0, - bottom: 0, + ...StyleSheet.absoluteFillObject, justifyContent: 'flex-end', alignItems: 'center', }, diff --git a/example/examples/FitToSuppliedMarkers.js b/example/examples/FitToSuppliedMarkers.js index bc5b86706..95ceb5644 100644 --- a/example/examples/FitToSuppliedMarkers.js +++ b/example/examples/FitToSuppliedMarkers.js @@ -146,20 +146,12 @@ var FocusOnMarkers = React.createClass({ var styles = StyleSheet.create({ container: { - position: 'absolute', - top: 0, - left: 0, - right: 0, - bottom: 0, + ...StyleSheet.absoluteFillObject, justifyContent: 'flex-end', alignItems: 'center', }, map: { - position: 'absolute', - top: 0, - left: 0, - right: 0, - bottom: 0, + ...StyleSheet.absoluteFillObject, }, }); diff --git a/example/examples/LoadingMap.js b/example/examples/LoadingMap.js index 22bdc2b23..4305de6fc 100644 --- a/example/examples/LoadingMap.js +++ b/example/examples/LoadingMap.js @@ -77,20 +77,12 @@ var LoadingMap = React.createClass({ var styles = StyleSheet.create({ container: { - position: 'absolute', - top: 0, - left: 0, - right: 0, - bottom: 0, + ...StyleSheet.absoluteFillObject, justifyContent: 'flex-end', alignItems: 'center', }, map: { - position: 'absolute', - top: 0, - left: 0, - right: 0, - bottom: 0, + ...StyleSheet.absoluteFillObject, }, bubble: { backgroundColor: 'rgba(255,255,255,0.7)', diff --git a/example/examples/MarkerTypes.js b/example/examples/MarkerTypes.js index dbd6671c5..aa4a4ead9 100644 --- a/example/examples/MarkerTypes.js +++ b/example/examples/MarkerTypes.js @@ -64,20 +64,12 @@ var MarkerTypes = React.createClass({ var styles = StyleSheet.create({ container: { - position: 'absolute', - top: 0, - left: 0, - right: 0, - bottom: 0, + ...StyleSheet.absoluteFillObject, justifyContent: 'flex-end', alignItems: 'center', }, map: { - position: 'absolute', - top: 0, - left: 0, - right: 0, - bottom: 0, + ...StyleSheet.absoluteFillObject, }, marker: { marginLeft: 33, diff --git a/example/examples/Overlays.js b/example/examples/Overlays.js index 590007250..f35702a65 100644 --- a/example/examples/Overlays.js +++ b/example/examples/Overlays.js @@ -111,20 +111,12 @@ var Overlays = React.createClass({ var styles = StyleSheet.create({ container: { - position: 'absolute', - top: 0, - left: 0, - right: 0, - bottom: 0, + ...StyleSheet.absoluteFillObject, justifyContent: 'flex-end', alignItems: 'center', }, map: { - position: 'absolute', - top: 0, - left: 0, - right: 0, - bottom: 0, + ...StyleSheet.absoluteFillObject, }, bubble: { flex: 1, diff --git a/example/examples/PolygonCreator.js b/example/examples/PolygonCreator.js index bd5585f35..129c26b34 100644 --- a/example/examples/PolygonCreator.js +++ b/example/examples/PolygonCreator.js @@ -115,20 +115,12 @@ var DisplayLatLng = React.createClass({ var styles = StyleSheet.create({ container: { - position: 'absolute', - top: 0, - left: 0, - right: 0, - bottom: 0, + ...StyleSheet.absoluteFillObject, justifyContent: 'flex-end', alignItems: 'center', }, map: { - position: 'absolute', - top: 0, - left: 0, - right: 0, - bottom: 0, + ...StyleSheet.absoluteFillObject, }, bubble: { backgroundColor: 'rgba(255,255,255,0.7)', diff --git a/example/examples/PolylineCreator.js b/example/examples/PolylineCreator.js index 02642f144..f4d8802bf 100644 --- a/example/examples/PolylineCreator.js +++ b/example/examples/PolylineCreator.js @@ -107,20 +107,12 @@ var PolylineCreator = React.createClass({ var styles = StyleSheet.create({ container: { - position: 'absolute', - top: 0, - left: 0, - right: 0, - bottom: 0, + ...StyleSheet.absoluteFillObject, justifyContent: 'flex-end', alignItems: 'center', }, map: { - position: 'absolute', - top: 0, - left: 0, - right: 0, - bottom: 0, + ...StyleSheet.absoluteFillObject, }, bubble: { backgroundColor: 'rgba(255,255,255,0.7)', diff --git a/example/examples/TakeSnapshot.js b/example/examples/TakeSnapshot.js index 3a749a62c..7fca97485 100644 --- a/example/examples/TakeSnapshot.js +++ b/example/examples/TakeSnapshot.js @@ -94,20 +94,12 @@ var MarkerTypes = React.createClass({ var styles = StyleSheet.create({ container: { - position: 'absolute', - top: 0, - left: 0, - right: 0, - bottom: 0, + ...StyleSheet.absoluteFillObject, justifyContent: 'flex-end', alignItems: 'center', }, map: { - position: 'absolute', - top: 0, - left: 0, - right: 0, - bottom: 0, + ...StyleSheet.absoluteFillObject, }, bubble: { backgroundColor: 'rgba(255,255,255,0.7)', diff --git a/example/examples/ViewsAsMarkers.js b/example/examples/ViewsAsMarkers.js index 3dfdc7ac5..8ba083c36 100644 --- a/example/examples/ViewsAsMarkers.js +++ b/example/examples/ViewsAsMarkers.js @@ -71,20 +71,12 @@ var DisplayLatLng = React.createClass({ var styles = StyleSheet.create({ container: { - position: 'absolute', - top: 0, - left: 0, - right: 0, - bottom: 0, + ...StyleSheet.absoluteFillObject, justifyContent: 'flex-end', alignItems: 'center', }, map: { - position: 'absolute', - top: 0, - left: 0, - right: 0, - bottom: 0, + ...StyleSheet.absoluteFillObject, }, bubble: { backgroundColor: 'rgba(255,255,255,0.7)', From ae713af39f28ebf564f76aefcf489658dcadc865 Mon Sep 17 00:00:00 2001 From: Spike Brehm Date: Thu, 25 Aug 2016 11:28:07 -0700 Subject: [PATCH 0010/1148] Autofix linting errors using `eslint --fix` --- components/AnimatedRegion.js | 30 +- components/MapCallout.js | 18 +- components/MapCircle.js | 18 +- components/MapMarker.js | 30 +- components/MapPolygon.js | 20 +- components/MapPolyline.js | 18 +- components/MapView.js | 54 +- example/App.js | 47 +- example/examples/AnimatedMarkers.js | 17 +- example/examples/AnimatedPriceMarker.js | 28 +- example/examples/AnimatedViews.js | 87 +- example/examples/CachedMap.js | 2481 +++++++++++----------- example/examples/Callouts.js | 18 +- example/examples/CustomCallout.js | 14 +- example/examples/DefaultMarkers.js | 16 +- example/examples/DisplayLatLng.js | 18 +- example/examples/DraggableMarkers.js | 18 +- example/examples/EventListener.js | 26 +- example/examples/FitToSuppliedMarkers.js | 40 +- example/examples/LoadingMap.js | 16 +- example/examples/MarkerTypes.js | 22 +- example/examples/Overlays.js | 14 +- example/examples/PanController.js | 643 +++--- example/examples/PolygonCreator.js | 26 +- example/examples/PolylineCreator.js | 22 +- example/examples/PriceMarker.js | 10 +- example/examples/TakeSnapshot.js | 37 +- example/examples/ViewsAsMarkers.js | 16 +- example/examples/finalindexfile.js | 117 +- example/index.android.js | 12 +- example/index.ios.js | 12 +- index.js | 2 +- 32 files changed, 1973 insertions(+), 1974 deletions(-) diff --git a/components/AnimatedRegion.js b/components/AnimatedRegion.js index d2f633a60..dba4e01b2 100644 --- a/components/AnimatedRegion.js +++ b/components/AnimatedRegion.js @@ -1,18 +1,18 @@ class AnimatedRegion extends AnimatedWithChildren { - //latitude: AnimatedValue; - //longitude: AnimatedValue; - //latitudeDelta: AnimatedValue; - //longitudeDelta: AnimatedValue; - //_listeners: {[key: string]: { + // latitude: AnimatedValue; + // longitude: AnimatedValue; + // latitudeDelta: AnimatedValue; + // longitudeDelta: AnimatedValue; + // _listeners: {[key: string]: { // latitude: string, // longitude: string, // latitudeDelta: string; // longitudeDelta: string, - //}}; + // }}; constructor(valueIn) { super(); - var value = valueIn || { // probably want to come up with better defaults + const value = valueIn || { // probably want to come up with better defaults latitude: 0, longitude: 0, latitudeDelta: 0, @@ -34,10 +34,10 @@ class AnimatedRegion extends AnimatedWithChildren { } setValue(value) { - //this.latitude.setValue(value.latitude); - //this.longitude.setValue(value.longitude); - //this.latitudeDelta.setValue(value.latitudeDelta); - //this.longitudeDelta.setValue(value.longitudeDelta); + // this.latitude.setValue(value.latitude); + // this.longitude.setValue(value.longitude); + // this.latitudeDelta.setValue(value.latitudeDelta); + // this.longitudeDelta.setValue(value.longitudeDelta); this.latitude._value = value.latitude; this.longitude._value = value.longitude; this.latitudeDelta._value = value.latitudeDelta; @@ -90,8 +90,8 @@ class AnimatedRegion extends AnimatedWithChildren { } addListener(callback) { - var id = String(_uniqueId++); - var jointCallback = ({value: number}) => { + const id = String(_uniqueId++); + const jointCallback = ({ value: number }) => { callback(this.__getValue()); }; this._listeners[id] = { @@ -112,7 +112,7 @@ class AnimatedRegion extends AnimatedWithChildren { } spring(config) { - var animations = []; + const animations = []; config.hasOwnProperty('latitude') && animations.push(timing(this.latitude, { ...config, @@ -141,7 +141,7 @@ class AnimatedRegion extends AnimatedWithChildren { } timing(config) { - var animations = []; + const animations = []; config.hasOwnProperty('latitude') && animations.push(timing(this.latitude, { ...config, diff --git a/components/MapCallout.js b/components/MapCallout.js index a4b4f809b..6da673529 100644 --- a/components/MapCallout.js +++ b/components/MapCallout.js @@ -1,18 +1,18 @@ -var React = require('react'); -var { +let React = require('react'); +const { PropTypes, } = React; -var ReactNative = require('react-native'); -var { +const ReactNative = require('react-native'); +let { View, NativeMethodsMixin, requireNativeComponent, StyleSheet, } = ReactNative; -var MapCallout = React.createClass({ +const MapCallout = React.createClass({ mixins: [NativeMethodsMixin], propTypes: { @@ -21,18 +21,18 @@ var MapCallout = React.createClass({ onPress: PropTypes.func, }, - getDefaultProps: function() { + getDefaultProps() { return { tooltip: false, }; }, - render: function() { + render() { return ; }, }); -var styles = StyleSheet.create({ +let styles = StyleSheet.create({ callout: { position: 'absolute', //flex: 0, @@ -40,6 +40,6 @@ var styles = StyleSheet.create({ }, }); -var AIRMapCallout = requireNativeComponent('AIRMapCallout', MapCallout); +let AIRMapCallout = requireNativeComponent('AIRMapCallout', MapCallout); module.exports = MapCallout; diff --git a/components/MapCircle.js b/components/MapCircle.js index cd6fe2425..c9cc8806e 100644 --- a/components/MapCircle.js +++ b/components/MapCircle.js @@ -1,18 +1,18 @@ -var React = require('react'); -var { +let React = require('react'); +const { PropTypes, } = React; -var ReactNative = require('react-native'); -var { +const ReactNative = require('react-native'); +let { View, NativeMethodsMixin, requireNativeComponent, StyleSheet, } = ReactNative; -var MapCircle = React.createClass({ +const MapCircle = React.createClass({ mixins: [NativeMethodsMixin], propTypes: { @@ -127,18 +127,18 @@ var MapCircle = React.createClass({ lineDashPattern: PropTypes.arrayOf(PropTypes.number), }, - getDefaultProps: function() { + getDefaultProps() { return { strokeColor: '#000', strokeWidth: 1, }; }, - _onPress: function(e) { + _onPress(e) { this.props.onPress && this.props.onPress(e); }, - render: function() { + render() { return ( ); }, }); -var styles = StyleSheet.create({ +const styles = StyleSheet.create({ polyline: { position: 'absolute', width: 0, @@ -148,6 +148,6 @@ var styles = StyleSheet.create({ }, }); -var AIRMapPolyline = requireNativeComponent('AIRMapPolyline', MapPolyline); +let AIRMapPolyline = requireNativeComponent('AIRMapPolyline', MapPolyline); module.exports = MapPolyline; diff --git a/components/MapView.js b/components/MapView.js index 774d7c2b0..87f52d49e 100644 --- a/components/MapView.js +++ b/components/MapView.js @@ -1,11 +1,11 @@ 'use strict'; -var React = require('react'); -var { +let React = require('react'); +const { PropTypes, } = React; -var ReactNative = require('react-native'); -var { +const ReactNative = require('react-native'); +let { EdgeInsetsPropType, NativeMethodsMixin, Platform, @@ -17,13 +17,13 @@ var { ColorPropType, } = ReactNative; -var MapMarker = require('./MapMarker'); -var MapPolyline = require('./MapPolyline'); -var MapPolygon = require('./MapPolygon'); -var MapCircle = require('./MapCircle'); -var MapCallout = require('./MapCallout'); +const MapMarker = require('./MapMarker'); +const MapPolyline = require('./MapPolyline'); +const MapPolygon = require('./MapPolygon'); +const MapCircle = require('./MapCircle'); +const MapCallout = require('./MapCallout'); -var MapView = React.createClass({ +const MapView = React.createClass({ mixins: [NativeMethodsMixin], viewConfig: { @@ -322,13 +322,13 @@ var MapView = React.createClass({ }, - getInitialState: function() { + getInitialState() { return { isReady: Platform.OS === 'ios', }; }, - componentDidMount: function() { + componentDidMount() { const { region, initialRegion } = this.props; if (region && this.state.isReady) { this.refs.map.setNativeProps({ region }); @@ -337,9 +337,9 @@ var MapView = React.createClass({ } }, - componentWillUpdate: function(nextProps) { - var a = this.__lastRegion; - var b = nextProps.region; + componentWillUpdate(nextProps) { + const a = this.__lastRegion; + const b = nextProps.region; if (!a || !b) return; if ( a.latitude !== b.latitude || @@ -351,7 +351,7 @@ var MapView = React.createClass({ } }, - _onMapReady: function() { + _onMapReady() { const { region, initialRegion } = this.props; if (region) { this.refs.map.setNativeProps({ region }); @@ -361,7 +361,7 @@ var MapView = React.createClass({ this.setState({ isReady: true }); }, - _onLayout: function(e) { + _onLayout(e) { const { region, initialRegion, onLayout } = this.props; const { isReady } = this.state; if (region && isReady && !this.__layoutCalled) { @@ -374,7 +374,7 @@ var MapView = React.createClass({ onLayout && onLayout(e); }, - _onChange: function(event: Event) { + _onChange(event: Event) { this.__lastRegion = event.nativeEvent.region; if (event.nativeEvent.continuous) { this.props.onRegionChange && @@ -385,34 +385,34 @@ var MapView = React.createClass({ } }, - animateToRegion: function (region, duration) { + animateToRegion(region, duration) { this._runCommand('animateToRegion', [region, duration || 500]); }, - animateToCoordinate: function (latLng, duration) { + animateToCoordinate(latLng, duration) { this._runCommand('animateToCoordinate', [latLng, duration || 500]); }, - fitToElements: function(animated) { + fitToElements(animated) { this._runCommand('fitToElements', [animated]); }, - fitToSuppliedMarkers: function(markers, animated) { + fitToSuppliedMarkers(markers, animated) { this._runCommand('fitToSuppliedMarkers', [markers, animated]); }, - takeSnapshot: function (width, height, region, callback) { + takeSnapshot(width, height, region, callback) { if (!region) { region = this.props.region || this.props.initialRegion; } this._runCommand('takeSnapshot', [width, height, region, callback]); }, - _getHandle: function() { + _getHandle() { return ReactNative.findNodeHandle(this.refs.map); }, - _runCommand: function (name, args) { + _runCommand(name, args) { switch (Platform.OS) { case 'android': NativeModules.UIManager.dispatchViewManagerCommand( @@ -431,7 +431,7 @@ var MapView = React.createClass({ } }, - render: function() { + render() { let props; if (this.state.isReady) { @@ -464,7 +464,7 @@ var MapView = React.createClass({ }, }); -var AIRMap = requireNativeComponent('AIRMap', MapView, { +let AIRMap = requireNativeComponent('AIRMap', MapView, { nativeOnly: { onChange: true, onMapReady: true, diff --git a/example/App.js b/example/App.js index bec55f008..3baef2a65 100644 --- a/example/App.js +++ b/example/App.js @@ -1,30 +1,30 @@ -var React = require('react'); -var ReactNative = require('react-native'); -var { +let React = require('react'); +const ReactNative = require('react-native'); +let { View, StyleSheet, TouchableOpacity, ScrollView, Text, } = ReactNative; -var DisplayLatLng = require('./examples/DisplayLatLng'); -var ViewsAsMarkers = require('./examples/ViewsAsMarkers'); -var EventListener = require('./examples/EventListener'); -var MarkerTypes = require('./examples/MarkerTypes'); -var DraggableMarkers = require('./examples/DraggableMarkers'); -var PolygonCreator = require('./examples/PolygonCreator'); -var PolylineCreator = require('./examples/PolylineCreator'); -var AnimatedViews = require('./examples/AnimatedViews'); -var AnimatedMarkers = require('./examples/AnimatedMarkers'); -var Callouts = require('./examples/Callouts'); -var Overlays = require('./examples/Overlays'); -var DefaultMarkers = require('./examples/DefaultMarkers'); -var CachedMap = require('./examples/CachedMap'); -var LoadingMap = require('./examples/LoadingMap'); -var TakeSnapshot = require('./examples/TakeSnapshot'); -var FitToSuppliedMarkers = require('./examples/FitToSuppliedMarkers'); +const DisplayLatLng = require('./examples/DisplayLatLng'); +const ViewsAsMarkers = require('./examples/ViewsAsMarkers'); +const EventListener = require('./examples/EventListener'); +const MarkerTypes = require('./examples/MarkerTypes'); +const DraggableMarkers = require('./examples/DraggableMarkers'); +const PolygonCreator = require('./examples/PolygonCreator'); +const PolylineCreator = require('./examples/PolylineCreator'); +const AnimatedViews = require('./examples/AnimatedViews'); +const AnimatedMarkers = require('./examples/AnimatedMarkers'); +const Callouts = require('./examples/Callouts'); +const Overlays = require('./examples/Overlays'); +const DefaultMarkers = require('./examples/DefaultMarkers'); +const CachedMap = require('./examples/CachedMap'); +const LoadingMap = require('./examples/LoadingMap'); +const TakeSnapshot = require('./examples/TakeSnapshot'); +const FitToSuppliedMarkers = require('./examples/FitToSuppliedMarkers'); -var App = React.createClass({ +const App = React.createClass({ getInitialState() { return { Component: null }; @@ -54,7 +54,7 @@ var App = React.createClass({ }, renderExamples(examples) { - var { Component } = this.state; + let { Component } = this.state; return ( {Component && } @@ -62,7 +62,8 @@ var App = React.createClass({ {!Component && ( + showsVerticalScrollIndicator={false} + > {examples.map(this.renderExample)} )} @@ -92,7 +93,7 @@ var App = React.createClass({ }, }); -var styles = StyleSheet.create({ +let styles = StyleSheet.create({ container: { position: 'absolute', top: 0, diff --git a/example/examples/AnimatedMarkers.js b/example/examples/AnimatedMarkers.js index 22001efd1..b59374974 100644 --- a/example/examples/AnimatedMarkers.js +++ b/example/examples/AnimatedMarkers.js @@ -1,6 +1,6 @@ -var React = require('react'); -var ReactNative = require('react-native'); -var { +let React = require('react'); +const ReactNative = require('react-native'); +let { StyleSheet, PropTypes, View, @@ -11,9 +11,9 @@ var { Platform, } = ReactNative; -var MapView = require('react-native-maps'); +let MapView = require('react-native-maps'); -var screen = Dimensions.get('window'); +const screen = Dimensions.get('window'); const ASPECT_RATIO = screen.width / screen.height; const LATITUDE = 37.78825; @@ -21,7 +21,7 @@ const LONGITUDE = -122.4324; const LATITUDE_DELTA = 0.0922; const LONGITUDE_DELTA = LATITUDE_DELTA * ASPECT_RATIO; -var AnimatedMarkers = React.createClass({ +const AnimatedMarkers = React.createClass({ getInitialState() { return { coordinate: new Animated.Region({ @@ -32,7 +32,7 @@ var AnimatedMarkers = React.createClass({ }, animate() { - var { coordinate } = this.state; + const { coordinate } = this.state; coordinate.timing({ latitude: LATITUDE + (Math.random() - 0.5) * LATITUDE_DELTA / 2, longitude: LONGITUDE + (Math.random() - 0.5) * LONGITUDE_DELTA / 2, @@ -66,8 +66,7 @@ var AnimatedMarkers = React.createClass({ }); - -var styles = StyleSheet.create({ +let styles = StyleSheet.create({ container: { position: 'absolute', top: 0, diff --git a/example/examples/AnimatedPriceMarker.js b/example/examples/AnimatedPriceMarker.js index 40047cf48..7de89fd02 100644 --- a/example/examples/AnimatedPriceMarker.js +++ b/example/examples/AnimatedPriceMarker.js @@ -1,10 +1,10 @@ -var React = require('react'); -var ReactNative = require('react-native'); -var { +let React = require('react'); +const ReactNative = require('react-native'); +const { PropTypes, } = React; -var { +let { StyleSheet, View, Text, @@ -12,13 +12,12 @@ var { } = ReactNative; const PriceMarker = ({ amount, selected, style }) => { - - var background = selected.interpolate({ + const background = selected.interpolate({ inputRange: [0, 1], outputRange: ['#FF5A5F', '#4da2ab'], }); - var border = selected.interpolate({ + const border = selected.interpolate({ inputRange: [0, 1], outputRange: ['#D23F44', '#007a87'], }); @@ -26,19 +25,18 @@ const PriceMarker = ({ amount, selected, style }) => { return ( + backgroundColor: background, + borderColor: border, + }]}> $ {amount} + borderTopColor: border, + }]} /> + borderTopColor: background, + }]} /> ); }; diff --git a/example/examples/AnimatedViews.js b/example/examples/AnimatedViews.js index 519f22243..36d97287c 100644 --- a/example/examples/AnimatedViews.js +++ b/example/examples/AnimatedViews.js @@ -1,6 +1,6 @@ -var React = require('react'); -var ReactNative = require('react-native'); -var { +let React = require('react'); +const ReactNative = require('react-native'); +let { StyleSheet, PropTypes, View, @@ -11,11 +11,11 @@ var { Platform, } = ReactNative; -var MapView = require('react-native-maps'); -var PanController = require('./PanController'); -var PriceMarker = require('./AnimatedPriceMarker'); +let MapView = require('react-native-maps'); +let PanController = require('./PanController'); +let PriceMarker = require('./AnimatedPriceMarker'); -var screen = Dimensions.get('window'); +const screen = Dimensions.get('window'); const ASPECT_RATIO = screen.width / screen.height; const LATITUDE = 37.78825; @@ -23,18 +23,18 @@ const LONGITUDE = -122.4324; const LATITUDE_DELTA = 0.0922; const LONGITUDE_DELTA = LATITUDE_DELTA * ASPECT_RATIO; -var ITEM_SPACING = 10; -var ITEM_PREVIEW = 10; -var ITEM_WIDTH = screen.width - 2 * ITEM_SPACING - 2 * ITEM_PREVIEW; -var SNAP_WIDTH = ITEM_WIDTH + ITEM_SPACING; -var ITEM_PREVIEW_HEIGHT = 150; -var SCALE_END = screen.width / ITEM_WIDTH; -var BREAKPOINT1 = 246; -var BREAKPOINT2 = 350; +const ITEM_SPACING = 10; +const ITEM_PREVIEW = 10; +const ITEM_WIDTH = screen.width - 2 * ITEM_SPACING - 2 * ITEM_PREVIEW; +let SNAP_WIDTH = ITEM_WIDTH + ITEM_SPACING; +const ITEM_PREVIEW_HEIGHT = 150; +const SCALE_END = screen.width / ITEM_WIDTH; +const BREAKPOINT1 = 246; +const BREAKPOINT2 = 350; const ANDROID = Platform.OS === 'android'; -var AnimatedViews = React.createClass({ +const AnimatedViews = React.createClass({ getInitialState() { const panX = new Animated.Value(0); const panY = new Animated.Value(0); @@ -90,19 +90,19 @@ var AnimatedViews = React.createClass({ }, ]; - const animations = markers.map((m, i) => { - const xLeft = -SNAP_WIDTH * i + SNAP_WIDTH/2; - const xRight = -SNAP_WIDTH * i - SNAP_WIDTH/2; + const animations = markers.map((m, i) => { + const xLeft = -SNAP_WIDTH * i + SNAP_WIDTH / 2; + const xRight = -SNAP_WIDTH * i - SNAP_WIDTH / 2; const xPos = -SNAP_WIDTH * i; const isIndex = panX.interpolate({ - inputRange: [xRight - 1, xRight, xLeft, xLeft+1], + inputRange: [xRight - 1, xRight, xLeft, xLeft + 1], outputRange: [0, 1, 1, 0], extrapolate: 'clamp', }); const isNotIndex = panX.interpolate({ - inputRange: [xRight - 1, xRight, xLeft, xLeft+1], + inputRange: [xRight - 1, xRight, xLeft, xLeft + 1], outputRange: [1, 0, 0, 1], extrapolate: 'clamp', }); @@ -131,12 +131,12 @@ var AnimatedViews = React.createClass({ const scale = Animated.add(ONE, Animated.multiply(isIndex, scrollY.interpolate({ inputRange: [BREAKPOINT1, BREAKPOINT2], - outputRange: [0, SCALE_END-1], + outputRange: [0, SCALE_END - 1], extrapolate: 'clamp', }))); // [0 => 1] - var opacity = scrollY.interpolate({ + let opacity = scrollY.interpolate({ inputRange: [BREAKPOINT1, BREAKPOINT2], outputRange: [0, 1], extrapolate: 'clamp', @@ -154,7 +154,7 @@ var AnimatedViews = React.createClass({ outputRange: [1, 0], }); - var markerOpacity = scrollY.interpolate({ + let markerOpacity = scrollY.interpolate({ inputRange: [0, BREAKPOINT1], outputRange: [0, 1], extrapolate: 'clamp', @@ -165,7 +165,7 @@ var AnimatedViews = React.createClass({ outputRange: [1, 0], }); - var markerScale = selected.interpolate({ + const markerScale = selected.interpolate({ inputRange: [0, 1], outputRange: [1, 1.2], }); @@ -204,7 +204,7 @@ var AnimatedViews = React.createClass({ }, componentDidMount() { - var { region, panX, panY, scrollX, markers } = this.state; + let { region, panX, panY, scrollX, markers } = this.state; panX.addListener(this.onPanXChange); panY.addListener(this.onPanYChange); @@ -227,38 +227,38 @@ var AnimatedViews = React.createClass({ // we only want to move the view if they are starting the gesture on top // of the view, so this calculates that and returns true if so. If we return // false, the gesture should get passed to the map view appropriately. - var { panY } = this.state; - var { pageY } = e.nativeEvent; - var topOfMainWindow = ITEM_PREVIEW_HEIGHT + 1 * panY.__getValue(); - var topOfTap = screen.height - pageY; + const { panY } = this.state; + const { pageY } = e.nativeEvent; + const topOfMainWindow = ITEM_PREVIEW_HEIGHT + 1 * panY.__getValue(); + const topOfTap = screen.height - pageY; return topOfTap < topOfMainWindow; }, onMoveShouldSetPanResponder(e) { - var { panY } = this.state; - var { pageY } = e.nativeEvent; - var topOfMainWindow = ITEM_PREVIEW_HEIGHT + 1 * panY.__getValue(); - var topOfTap = screen.height - pageY; + const { panY } = this.state; + const { pageY } = e.nativeEvent; + const topOfMainWindow = ITEM_PREVIEW_HEIGHT + 1 * panY.__getValue(); + const topOfTap = screen.height - pageY; return topOfTap < topOfMainWindow; }, onPanXChange({ value }) { - var { index, region, panX, markers } = this.state; - var newIndex = Math.floor((-1 * value + SNAP_WIDTH / 2) / SNAP_WIDTH); + let { index, region, panX, markers } = this.state; + const newIndex = Math.floor((-1 * value + SNAP_WIDTH / 2) / SNAP_WIDTH); if (index !== newIndex) { this.setState({ index: newIndex }); } }, onPanYChange({ value }) { - var { canMoveHorizontal, region, scrollY, scrollX, markers, index } = this.state; - var shouldBeMovable = Math.abs(value) < 2; + let { canMoveHorizontal, region, scrollY, scrollX, markers, index } = this.state; + const shouldBeMovable = Math.abs(value) < 2; if (shouldBeMovable !== canMoveHorizontal) { this.setState({ canMoveHorizontal: shouldBeMovable }); if (!shouldBeMovable) { - var { coordinate } = markers[index]; + const { coordinate } = markers[index]; region.stopAnimation(); region.timing({ latitude: scrollY.interpolate({ @@ -296,7 +296,7 @@ var AnimatedViews = React.createClass({ }, onRegionChange(region) { - //this.state.region.setValue(region); + // this.state.region.setValue(region); }, render() { @@ -318,7 +318,7 @@ var AnimatedViews = React.createClass({ xMode="snap" snapSpacingX={SNAP_WIDTH} yBounds={[-1 * screen.height, 0]} - xBounds={[-screen.width * (markers.length-1), 0]} + xBounds={[-screen.width * (markers.length - 1), 0]} panY={panY} panX={panX} onStartShouldSetPanResponder={this.onStartShouldSetPanResponder} @@ -387,8 +387,7 @@ var AnimatedViews = React.createClass({ }); - -var styles = StyleSheet.create({ +let styles = StyleSheet.create({ container: { position: 'absolute', top: 0, @@ -401,7 +400,7 @@ var styles = StyleSheet.create({ flexDirection: 'row', paddingHorizontal: ITEM_SPACING / 2 + ITEM_PREVIEW, position: 'absolute', - //top: screen.height - ITEM_PREVIEW_HEIGHT - 64, + // top: screen.height - ITEM_PREVIEW_HEIGHT - 64, paddingTop: screen.height - ITEM_PREVIEW_HEIGHT - 64, //paddingTop: !ANDROID ? 0 : screen.height - ITEM_PREVIEW_HEIGHT - 64, }, diff --git a/example/examples/CachedMap.js b/example/examples/CachedMap.js index c46e8665d..3e2cd4396 100644 --- a/example/examples/CachedMap.js +++ b/example/examples/CachedMap.js @@ -1,6 +1,6 @@ -var React = require('react'); -var ReactNative = require('react-native'); -var { +let React = require('react'); +const ReactNative = require('react-native'); +let { Text, View, Dimensions, @@ -9,14 +9,14 @@ var { TouchableOpacity, } = ReactNative; -var MapView = require('react-native-maps'); +let MapView = require('react-native-maps'); const HORIZONTAL_PADDING = 12; const VERTICAL_PADDING = 6; -var CachedMap = React.createClass({ +const CachedMap = React.createClass({ getInitialState() { - var ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2}); + const ds = new ListView.DataSource({ rowHasChanged: (r1, r2) => r1 !== r2 }); return { dataSource: ds.cloneWithRows(COUNTRIES), cache: true, @@ -35,12 +35,12 @@ var CachedMap = React.createClass({ }, render() { - var { width, height } = Dimensions.get('window'); + let { width, height } = Dimensions.get('window'); return ( - {this.state.cache ? "Cached" : "Not cached"} + {this.state.cache ? 'Cached' : 'Not cached'} { return ( + style={styles.item} + > {region.name} + loadingBackgroundColor={"#eeeeee"} + > ); - }} /> + }} + /> ); }, }); -var styles = StyleSheet.create({ +let styles = StyleSheet.create({ container: { flex: 1, }, @@ -105,1719 +108,1719 @@ var styles = StyleSheet.create({ justifyContent: 'flex-end', }, buttonText: { - color: 'white' - } + color: 'white', + }, }); const COUNTRIES = [ { - "latitude": 33.93911, - "longitudeDelta": 10.0, - "name": "Afghanistan", - "longitude": 67.709953, - "latitudeDelta": 10.0 + 'latitude': 33.93911, + 'longitudeDelta': 10.0, + 'name': 'Afghanistan', + 'longitude': 67.709953, + 'latitudeDelta': 10.0, }, { - "latitude": 41.153332, - "longitudeDelta": 10.0, - "name": "Albania", - "longitude": 20.168331, - "latitudeDelta": 10.0 + 'latitude': 41.153332, + 'longitudeDelta': 10.0, + 'name': 'Albania', + 'longitude': 20.168331, + 'latitudeDelta': 10.0, }, { - "latitude": 28.033886, - "longitudeDelta": 10.0, - "name": "Algeria", - "longitude": 1.659626, - "latitudeDelta": 10.0 + 'latitude': 28.033886, + 'longitudeDelta': 10.0, + 'name': 'Algeria', + 'longitude': 1.659626, + 'latitudeDelta': 10.0, }, { - "latitude": -14.270972, - "longitudeDelta": 10.0, - "name": "American Samoa", - "longitude": -170.132217, - "latitudeDelta": 10.0 + 'latitude': -14.270972, + 'longitudeDelta': 10.0, + 'name': 'American Samoa', + 'longitude': -170.132217, + 'latitudeDelta': 10.0, }, { - "latitude": 42.546245, - "longitudeDelta": 10.0, - "name": "Andorra", - "longitude": 1.601554, - "latitudeDelta": 10.0 + 'latitude': 42.546245, + 'longitudeDelta': 10.0, + 'name': 'Andorra', + 'longitude': 1.601554, + 'latitudeDelta': 10.0, }, { - "latitude": -11.202692, - "longitudeDelta": 10.0, - "name": "Angola", - "longitude": 17.873887, - "latitudeDelta": 10.0 + 'latitude': -11.202692, + 'longitudeDelta': 10.0, + 'name': 'Angola', + 'longitude': 17.873887, + 'latitudeDelta': 10.0, }, { - "latitude": 18.220554, - "longitudeDelta": 10.0, - "name": "Anguilla", - "longitude": -63.068615, - "latitudeDelta": 10.0 + 'latitude': 18.220554, + 'longitudeDelta': 10.0, + 'name': 'Anguilla', + 'longitude': -63.068615, + 'latitudeDelta': 10.0, }, { - "latitude": -75.250973, - "longitudeDelta": 10.0, - "name": "Antarctica", - "longitude": -0.071389, - "latitudeDelta": 10.0 + 'latitude': -75.250973, + 'longitudeDelta': 10.0, + 'name': 'Antarctica', + 'longitude': -0.071389, + 'latitudeDelta': 10.0, }, { - "latitude": 17.060816, - "longitudeDelta": 10.0, - "name": "Antigua and Barbuda", - "longitude": -61.796428, - "latitudeDelta": 10.0 + 'latitude': 17.060816, + 'longitudeDelta': 10.0, + 'name': 'Antigua and Barbuda', + 'longitude': -61.796428, + 'latitudeDelta': 10.0, }, { - "latitude": -38.416097, - "longitudeDelta": 10.0, - "name": "Argentina", - "longitude": -63.616672, - "latitudeDelta": 10.0 + 'latitude': -38.416097, + 'longitudeDelta': 10.0, + 'name': 'Argentina', + 'longitude': -63.616672, + 'latitudeDelta': 10.0, }, { - "latitude": 40.069099, - "longitudeDelta": 10.0, - "name": "Armenia", - "longitude": 45.038189, - "latitudeDelta": 10.0 + 'latitude': 40.069099, + 'longitudeDelta': 10.0, + 'name': 'Armenia', + 'longitude': 45.038189, + 'latitudeDelta': 10.0, }, { - "latitude": 12.52111, - "longitudeDelta": 10.0, - "name": "Aruba", - "longitude": -69.968338, - "latitudeDelta": 10.0 + 'latitude': 12.52111, + 'longitudeDelta': 10.0, + 'name': 'Aruba', + 'longitude': -69.968338, + 'latitudeDelta': 10.0, }, { - "latitude": -25.274398, - "longitudeDelta": 10.0, - "name": "Australia", - "longitude": 133.775136, - "latitudeDelta": 10.0 + 'latitude': -25.274398, + 'longitudeDelta': 10.0, + 'name': 'Australia', + 'longitude': 133.775136, + 'latitudeDelta': 10.0, }, { - "latitude": 47.516231, - "longitudeDelta": 10.0, - "name": "Austria", - "longitude": 14.550072, - "latitudeDelta": 10.0 + 'latitude': 47.516231, + 'longitudeDelta': 10.0, + 'name': 'Austria', + 'longitude': 14.550072, + 'latitudeDelta': 10.0, }, { - "latitude": 40.143105, - "longitudeDelta": 10.0, - "name": "Azerbaijan", - "longitude": 47.576927, - "latitudeDelta": 10.0 + 'latitude': 40.143105, + 'longitudeDelta': 10.0, + 'name': 'Azerbaijan', + 'longitude': 47.576927, + 'latitudeDelta': 10.0, }, { - "latitude": 25.03428, - "longitudeDelta": 10.0, - "name": "Bahamas", - "longitude": -77.39628, - "latitudeDelta": 10.0 + 'latitude': 25.03428, + 'longitudeDelta': 10.0, + 'name': 'Bahamas', + 'longitude': -77.39628, + 'latitudeDelta': 10.0, }, { - "latitude": 25.930414, - "longitudeDelta": 10.0, - "name": "Bahrain", - "longitude": 50.637772, - "latitudeDelta": 10.0 + 'latitude': 25.930414, + 'longitudeDelta': 10.0, + 'name': 'Bahrain', + 'longitude': 50.637772, + 'latitudeDelta': 10.0, }, { - "latitude": 23.684994, - "longitudeDelta": 10.0, - "name": "Bangladesh", - "longitude": 90.356331, - "latitudeDelta": 10.0 + 'latitude': 23.684994, + 'longitudeDelta': 10.0, + 'name': 'Bangladesh', + 'longitude': 90.356331, + 'latitudeDelta': 10.0, }, { - "latitude": 13.193887, - "longitudeDelta": 10.0, - "name": "Barbados", - "longitude": -59.543198, - "latitudeDelta": 10.0 + 'latitude': 13.193887, + 'longitudeDelta': 10.0, + 'name': 'Barbados', + 'longitude': -59.543198, + 'latitudeDelta': 10.0, }, { - "latitude": 53.709807, - "longitudeDelta": 10.0, - "name": "Belarus", - "longitude": 27.953389, - "latitudeDelta": 10.0 + 'latitude': 53.709807, + 'longitudeDelta': 10.0, + 'name': 'Belarus', + 'longitude': 27.953389, + 'latitudeDelta': 10.0, }, { - "latitude": 50.503887, - "longitudeDelta": 10.0, - "name": "Belgium", - "longitude": 4.469936, - "latitudeDelta": 10.0 + 'latitude': 50.503887, + 'longitudeDelta': 10.0, + 'name': 'Belgium', + 'longitude': 4.469936, + 'latitudeDelta': 10.0, }, { - "latitude": 17.189877, - "longitudeDelta": 10.0, - "name": "Belize", - "longitude": -88.49765, - "latitudeDelta": 10.0 + 'latitude': 17.189877, + 'longitudeDelta': 10.0, + 'name': 'Belize', + 'longitude': -88.49765, + 'latitudeDelta': 10.0, }, { - "latitude": 9.30769, - "longitudeDelta": 10.0, - "name": "Benin", - "longitude": 2.315834, - "latitudeDelta": 10.0 + 'latitude': 9.30769, + 'longitudeDelta': 10.0, + 'name': 'Benin', + 'longitude': 2.315834, + 'latitudeDelta': 10.0, }, { - "latitude": 32.321384, - "longitudeDelta": 10.0, - "name": "Bermuda", - "longitude": -64.75737, - "latitudeDelta": 10.0 + 'latitude': 32.321384, + 'longitudeDelta': 10.0, + 'name': 'Bermuda', + 'longitude': -64.75737, + 'latitudeDelta': 10.0, }, { - "latitude": 27.514162, - "longitudeDelta": 10.0, - "name": "Bhutan", - "longitude": 90.433601, - "latitudeDelta": 10.0 + 'latitude': 27.514162, + 'longitudeDelta': 10.0, + 'name': 'Bhutan', + 'longitude': 90.433601, + 'latitudeDelta': 10.0, }, { - "latitude": -16.290154, - "longitudeDelta": 10.0, - "name": "Bolivia", - "longitude": -63.588653, - "latitudeDelta": 10.0 + 'latitude': -16.290154, + 'longitudeDelta': 10.0, + 'name': 'Bolivia', + 'longitude': -63.588653, + 'latitudeDelta': 10.0, }, { - "latitude": 43.915886, - "longitudeDelta": 10.0, - "name": "Bosnia and Herzegovina", - "longitude": 17.679076, - "latitudeDelta": 10.0 + 'latitude': 43.915886, + 'longitudeDelta': 10.0, + 'name': 'Bosnia and Herzegovina', + 'longitude': 17.679076, + 'latitudeDelta': 10.0, }, { - "latitude": -22.328474, - "longitudeDelta": 10.0, - "name": "Botswana", - "longitude": 24.684866, - "latitudeDelta": 10.0 + 'latitude': -22.328474, + 'longitudeDelta': 10.0, + 'name': 'Botswana', + 'longitude': 24.684866, + 'latitudeDelta': 10.0, }, { - "latitude": -54.423199, - "longitudeDelta": 10.0, - "name": "Bouvet Island", - "longitude": 3.413194, - "latitudeDelta": 10.0 + 'latitude': -54.423199, + 'longitudeDelta': 10.0, + 'name': 'Bouvet Island', + 'longitude': 3.413194, + 'latitudeDelta': 10.0, }, { - "latitude": -14.235004, - "longitudeDelta": 10.0, - "name": "Brazil", - "longitude": -51.92528, - "latitudeDelta": 10.0 + 'latitude': -14.235004, + 'longitudeDelta': 10.0, + 'name': 'Brazil', + 'longitude': -51.92528, + 'latitudeDelta': 10.0, }, { - "latitude": -6.343194, - "longitudeDelta": 10.0, - "name": "British Indian Ocean Territory", - "longitude": 71.876519, - "latitudeDelta": 10.0 + 'latitude': -6.343194, + 'longitudeDelta': 10.0, + 'name': 'British Indian Ocean Territory', + 'longitude': 71.876519, + 'latitudeDelta': 10.0, }, { - "latitude": 18.420695, - "longitudeDelta": 10.0, - "name": "British Virgin Islands", - "longitude": -64.639968, - "latitudeDelta": 10.0 + 'latitude': 18.420695, + 'longitudeDelta': 10.0, + 'name': 'British Virgin Islands', + 'longitude': -64.639968, + 'latitudeDelta': 10.0, }, { - "latitude": 4.535277, - "longitudeDelta": 10.0, - "name": "Brunei", - "longitude": 114.727669, - "latitudeDelta": 10.0 + 'latitude': 4.535277, + 'longitudeDelta': 10.0, + 'name': 'Brunei', + 'longitude': 114.727669, + 'latitudeDelta': 10.0, }, { - "latitude": 42.733883, - "longitudeDelta": 10.0, - "name": "Bulgaria", - "longitude": 25.48583, - "latitudeDelta": 10.0 + 'latitude': 42.733883, + 'longitudeDelta': 10.0, + 'name': 'Bulgaria', + 'longitude': 25.48583, + 'latitudeDelta': 10.0, }, { - "latitude": 12.238333, - "longitudeDelta": 10.0, - "name": "Burkina Faso", - "longitude": -1.561593, - "latitudeDelta": 10.0 + 'latitude': 12.238333, + 'longitudeDelta': 10.0, + 'name': 'Burkina Faso', + 'longitude': -1.561593, + 'latitudeDelta': 10.0, }, { - "latitude": -3.373056, - "longitudeDelta": 10.0, - "name": "Burundi", - "longitude": 29.918886, - "latitudeDelta": 10.0 + 'latitude': -3.373056, + 'longitudeDelta': 10.0, + 'name': 'Burundi', + 'longitude': 29.918886, + 'latitudeDelta': 10.0, }, { - "latitude": 12.565679, - "longitudeDelta": 10.0, - "name": "Cambodia", - "longitude": 104.990963, - "latitudeDelta": 10.0 + 'latitude': 12.565679, + 'longitudeDelta': 10.0, + 'name': 'Cambodia', + 'longitude': 104.990963, + 'latitudeDelta': 10.0, }, { - "latitude": 7.369722, - "longitudeDelta": 10.0, - "name": "Cameroon", - "longitude": 12.354722, - "latitudeDelta": 10.0 + 'latitude': 7.369722, + 'longitudeDelta': 10.0, + 'name': 'Cameroon', + 'longitude': 12.354722, + 'latitudeDelta': 10.0, }, { - "latitude": 56.130366, - "longitudeDelta": 10.0, - "name": "Canada", - "longitude": -106.346771, - "latitudeDelta": 10.0 + 'latitude': 56.130366, + 'longitudeDelta': 10.0, + 'name': 'Canada', + 'longitude': -106.346771, + 'latitudeDelta': 10.0, }, { - "latitude": 16.002082, - "longitudeDelta": 10.0, - "name": "Cape Verde", - "longitude": -24.013197, - "latitudeDelta": 10.0 + 'latitude': 16.002082, + 'longitudeDelta': 10.0, + 'name': 'Cape Verde', + 'longitude': -24.013197, + 'latitudeDelta': 10.0, }, { - "latitude": 19.513469, - "longitudeDelta": 10.0, - "name": "Cayman Islands", - "longitude": -80.566956, - "latitudeDelta": 10.0 + 'latitude': 19.513469, + 'longitudeDelta': 10.0, + 'name': 'Cayman Islands', + 'longitude': -80.566956, + 'latitudeDelta': 10.0, }, { - "latitude": 6.611111, - "longitudeDelta": 10.0, - "name": "Central African Republic", - "longitude": 20.939444, - "latitudeDelta": 10.0 + 'latitude': 6.611111, + 'longitudeDelta': 10.0, + 'name': 'Central African Republic', + 'longitude': 20.939444, + 'latitudeDelta': 10.0, }, { - "latitude": 15.454166, - "longitudeDelta": 10.0, - "name": "Chad", - "longitude": 18.732207, - "latitudeDelta": 10.0 + 'latitude': 15.454166, + 'longitudeDelta': 10.0, + 'name': 'Chad', + 'longitude': 18.732207, + 'latitudeDelta': 10.0, }, { - "latitude": -35.675147, - "longitudeDelta": 10.0, - "name": "Chile", - "longitude": -71.542969, - "latitudeDelta": 10.0 + 'latitude': -35.675147, + 'longitudeDelta': 10.0, + 'name': 'Chile', + 'longitude': -71.542969, + 'latitudeDelta': 10.0, }, { - "latitude": 35.86166, - "longitudeDelta": 10.0, - "name": "China", - "longitude": 104.195397, - "latitudeDelta": 10.0 + 'latitude': 35.86166, + 'longitudeDelta': 10.0, + 'name': 'China', + 'longitude': 104.195397, + 'latitudeDelta': 10.0, }, { - "latitude": -10.447525, - "longitudeDelta": 10.0, - "name": "Christmas Island", - "longitude": 105.690449, - "latitudeDelta": 10.0 + 'latitude': -10.447525, + 'longitudeDelta': 10.0, + 'name': 'Christmas Island', + 'longitude': 105.690449, + 'latitudeDelta': 10.0, }, { - "latitude": -12.164165, - "longitudeDelta": 10.0, - "name": "Cocos [Keeling] Islands", - "longitude": 96.870956, - "latitudeDelta": 10.0 + 'latitude': -12.164165, + 'longitudeDelta': 10.0, + 'name': 'Cocos [Keeling] Islands', + 'longitude': 96.870956, + 'latitudeDelta': 10.0, }, { - "latitude": 4.570868, - "longitudeDelta": 10.0, - "name": "Colombia", - "longitude": -74.297333, - "latitudeDelta": 10.0 + 'latitude': 4.570868, + 'longitudeDelta': 10.0, + 'name': 'Colombia', + 'longitude': -74.297333, + 'latitudeDelta': 10.0, }, { - "latitude": -11.875001, - "longitudeDelta": 10.0, - "name": "Comoros", - "longitude": 43.872219, - "latitudeDelta": 10.0 + 'latitude': -11.875001, + 'longitudeDelta': 10.0, + 'name': 'Comoros', + 'longitude': 43.872219, + 'latitudeDelta': 10.0, }, { - "latitude": -4.038333, - "longitudeDelta": 10.0, - "name": "Congo [DRC]", - "longitude": 21.758664, - "latitudeDelta": 10.0 + 'latitude': -4.038333, + 'longitudeDelta': 10.0, + 'name': 'Congo [DRC]', + 'longitude': 21.758664, + 'latitudeDelta': 10.0, }, { - "latitude": -0.228021, - "longitudeDelta": 10.0, - "name": "Congo [Republic]", - "longitude": 15.827659, - "latitudeDelta": 10.0 + 'latitude': -0.228021, + 'longitudeDelta': 10.0, + 'name': 'Congo [Republic]', + 'longitude': 15.827659, + 'latitudeDelta': 10.0, }, { - "latitude": -21.236736, - "longitudeDelta": 10.0, - "name": "Cook Islands", - "longitude": -159.777671, - "latitudeDelta": 10.0 + 'latitude': -21.236736, + 'longitudeDelta': 10.0, + 'name': 'Cook Islands', + 'longitude': -159.777671, + 'latitudeDelta': 10.0, }, { - "latitude": 9.748917, - "longitudeDelta": 10.0, - "name": "Costa Rica", - "longitude": -83.753428, - "latitudeDelta": 10.0 + 'latitude': 9.748917, + 'longitudeDelta': 10.0, + 'name': 'Costa Rica', + 'longitude': -83.753428, + 'latitudeDelta': 10.0, }, { - "latitude": 45.1, - "longitudeDelta": 10.0, - "name": "Croatia", - "longitude": 15.2, - "latitudeDelta": 10.0 + 'latitude': 45.1, + 'longitudeDelta': 10.0, + 'name': 'Croatia', + 'longitude': 15.2, + 'latitudeDelta': 10.0, }, { - "latitude": 21.521757, - "longitudeDelta": 10.0, - "name": "Cuba", - "longitude": -77.781167, - "latitudeDelta": 10.0 + 'latitude': 21.521757, + 'longitudeDelta': 10.0, + 'name': 'Cuba', + 'longitude': -77.781167, + 'latitudeDelta': 10.0, }, { - "latitude": 35.126413, - "longitudeDelta": 10.0, - "name": "Cyprus", - "longitude": 33.429859, - "latitudeDelta": 10.0 + 'latitude': 35.126413, + 'longitudeDelta': 10.0, + 'name': 'Cyprus', + 'longitude': 33.429859, + 'latitudeDelta': 10.0, }, { - "latitude": 49.817492, - "longitudeDelta": 10.0, - "name": "Czech Republic", - "longitude": 15.472962, - "latitudeDelta": 10.0 + 'latitude': 49.817492, + 'longitudeDelta': 10.0, + 'name': 'Czech Republic', + 'longitude': 15.472962, + 'latitudeDelta': 10.0, }, { - "latitude": 7.539989, - "longitudeDelta": 10.0, - "name": "C\u00f4te d'Ivoire", - "longitude": -5.54708, - "latitudeDelta": 10.0 + 'latitude': 7.539989, + 'longitudeDelta': 10.0, + 'name': "C\u00f4te d'Ivoire", + 'longitude': -5.54708, + 'latitudeDelta': 10.0, }, { - "latitude": 56.26392, - "longitudeDelta": 10.0, - "name": "Denmark", - "longitude": 9.501785, - "latitudeDelta": 10.0 + 'latitude': 56.26392, + 'longitudeDelta': 10.0, + 'name': 'Denmark', + 'longitude': 9.501785, + 'latitudeDelta': 10.0, }, { - "latitude": 11.825138, - "longitudeDelta": 10.0, - "name": "Djibouti", - "longitude": 42.590275, - "latitudeDelta": 10.0 + 'latitude': 11.825138, + 'longitudeDelta': 10.0, + 'name': 'Djibouti', + 'longitude': 42.590275, + 'latitudeDelta': 10.0, }, { - "latitude": 15.414999, - "longitudeDelta": 10.0, - "name": "Dominica", - "longitude": -61.370976, - "latitudeDelta": 10.0 + 'latitude': 15.414999, + 'longitudeDelta': 10.0, + 'name': 'Dominica', + 'longitude': -61.370976, + 'latitudeDelta': 10.0, }, { - "latitude": 18.735693, - "longitudeDelta": 10.0, - "name": "Dominican Republic", - "longitude": -70.162651, - "latitudeDelta": 10.0 + 'latitude': 18.735693, + 'longitudeDelta': 10.0, + 'name': 'Dominican Republic', + 'longitude': -70.162651, + 'latitudeDelta': 10.0, }, { - "latitude": -1.831239, - "longitudeDelta": 10.0, - "name": "Ecuador", - "longitude": -78.183406, - "latitudeDelta": 10.0 + 'latitude': -1.831239, + 'longitudeDelta': 10.0, + 'name': 'Ecuador', + 'longitude': -78.183406, + 'latitudeDelta': 10.0, }, { - "latitude": 26.820553, - "longitudeDelta": 10.0, - "name": "Egypt", - "longitude": 30.802498, - "latitudeDelta": 10.0 + 'latitude': 26.820553, + 'longitudeDelta': 10.0, + 'name': 'Egypt', + 'longitude': 30.802498, + 'latitudeDelta': 10.0, }, { - "latitude": 13.794185, - "longitudeDelta": 10.0, - "name": "El Salvador", - "longitude": -88.89653, - "latitudeDelta": 10.0 + 'latitude': 13.794185, + 'longitudeDelta': 10.0, + 'name': 'El Salvador', + 'longitude': -88.89653, + 'latitudeDelta': 10.0, }, { - "latitude": 1.650801, - "longitudeDelta": 10.0, - "name": "Equatorial Guinea", - "longitude": 10.267895, - "latitudeDelta": 10.0 + 'latitude': 1.650801, + 'longitudeDelta': 10.0, + 'name': 'Equatorial Guinea', + 'longitude': 10.267895, + 'latitudeDelta': 10.0, }, { - "latitude": 15.179384, - "longitudeDelta": 10.0, - "name": "Eritrea", - "longitude": 39.782334, - "latitudeDelta": 10.0 + 'latitude': 15.179384, + 'longitudeDelta': 10.0, + 'name': 'Eritrea', + 'longitude': 39.782334, + 'latitudeDelta': 10.0, }, { - "latitude": 58.595272, - "longitudeDelta": 10.0, - "name": "Estonia", - "longitude": 25.013607, - "latitudeDelta": 10.0 + 'latitude': 58.595272, + 'longitudeDelta': 10.0, + 'name': 'Estonia', + 'longitude': 25.013607, + 'latitudeDelta': 10.0, }, { - "latitude": 9.145, - "longitudeDelta": 10.0, - "name": "Ethiopia", - "longitude": 40.489673, - "latitudeDelta": 10.0 + 'latitude': 9.145, + 'longitudeDelta': 10.0, + 'name': 'Ethiopia', + 'longitude': 40.489673, + 'latitudeDelta': 10.0, }, { - "latitude": -51.796253, - "longitudeDelta": 10.0, - "name": "Falkland Islands [Islas Malvinas]", - "longitude": -59.523613, - "latitudeDelta": 10.0 + 'latitude': -51.796253, + 'longitudeDelta': 10.0, + 'name': 'Falkland Islands [Islas Malvinas]', + 'longitude': -59.523613, + 'latitudeDelta': 10.0, }, { - "latitude": 61.892635, - "longitudeDelta": 10.0, - "name": "Faroe Islands", - "longitude": -6.911806, - "latitudeDelta": 10.0 + 'latitude': 61.892635, + 'longitudeDelta': 10.0, + 'name': 'Faroe Islands', + 'longitude': -6.911806, + 'latitudeDelta': 10.0, }, { - "latitude": -16.578193, - "longitudeDelta": 10.0, - "name": "Fiji", - "longitude": 179.414413, - "latitudeDelta": 10.0 + 'latitude': -16.578193, + 'longitudeDelta': 10.0, + 'name': 'Fiji', + 'longitude': 179.414413, + 'latitudeDelta': 10.0, }, { - "latitude": 61.92411, - "longitudeDelta": 10.0, - "name": "Finland", - "longitude": 25.748151, - "latitudeDelta": 10.0 + 'latitude': 61.92411, + 'longitudeDelta': 10.0, + 'name': 'Finland', + 'longitude': 25.748151, + 'latitudeDelta': 10.0, }, { - "latitude": 46.227638, - "longitudeDelta": 10.0, - "name": "France", - "longitude": 2.213749, - "latitudeDelta": 10.0 + 'latitude': 46.227638, + 'longitudeDelta': 10.0, + 'name': 'France', + 'longitude': 2.213749, + 'latitudeDelta': 10.0, }, { - "latitude": 3.933889, - "longitudeDelta": 10.0, - "name": "French Guiana", - "longitude": -53.125782, - "latitudeDelta": 10.0 + 'latitude': 3.933889, + 'longitudeDelta': 10.0, + 'name': 'French Guiana', + 'longitude': -53.125782, + 'latitudeDelta': 10.0, }, { - "latitude": -17.679742, - "longitudeDelta": 10.0, - "name": "French Polynesia", - "longitude": -149.406843, - "latitudeDelta": 10.0 + 'latitude': -17.679742, + 'longitudeDelta': 10.0, + 'name': 'French Polynesia', + 'longitude': -149.406843, + 'latitudeDelta': 10.0, }, { - "latitude": -49.280366, - "longitudeDelta": 10.0, - "name": "French Southern Territories", - "longitude": 69.348557, - "latitudeDelta": 10.0 + 'latitude': -49.280366, + 'longitudeDelta': 10.0, + 'name': 'French Southern Territories', + 'longitude': 69.348557, + 'latitudeDelta': 10.0, }, { - "latitude": -0.803689, - "longitudeDelta": 10.0, - "name": "Gabon", - "longitude": 11.609444, - "latitudeDelta": 10.0 + 'latitude': -0.803689, + 'longitudeDelta': 10.0, + 'name': 'Gabon', + 'longitude': 11.609444, + 'latitudeDelta': 10.0, }, { - "latitude": 13.443182, - "longitudeDelta": 10.0, - "name": "Gambia", - "longitude": -15.310139, - "latitudeDelta": 10.0 + 'latitude': 13.443182, + 'longitudeDelta': 10.0, + 'name': 'Gambia', + 'longitude': -15.310139, + 'latitudeDelta': 10.0, }, { - "latitude": 31.354676, - "longitudeDelta": 10.0, - "name": "Gaza Strip", - "longitude": 34.308825, - "latitudeDelta": 10.0 + 'latitude': 31.354676, + 'longitudeDelta': 10.0, + 'name': 'Gaza Strip', + 'longitude': 34.308825, + 'latitudeDelta': 10.0, }, { - "latitude": 42.315407, - "longitudeDelta": 10.0, - "name": "Georgia", - "longitude": 43.356892, - "latitudeDelta": 10.0 + 'latitude': 42.315407, + 'longitudeDelta': 10.0, + 'name': 'Georgia', + 'longitude': 43.356892, + 'latitudeDelta': 10.0, }, { - "latitude": 51.165691, - "longitudeDelta": 10.0, - "name": "Germany", - "longitude": 10.451526, - "latitudeDelta": 10.0 + 'latitude': 51.165691, + 'longitudeDelta': 10.0, + 'name': 'Germany', + 'longitude': 10.451526, + 'latitudeDelta': 10.0, }, { - "latitude": 7.946527, - "longitudeDelta": 10.0, - "name": "Ghana", - "longitude": -1.023194, - "latitudeDelta": 10.0 + 'latitude': 7.946527, + 'longitudeDelta': 10.0, + 'name': 'Ghana', + 'longitude': -1.023194, + 'latitudeDelta': 10.0, }, { - "latitude": 36.137741, - "longitudeDelta": 10.0, - "name": "Gibraltar", - "longitude": -5.345374, - "latitudeDelta": 10.0 + 'latitude': 36.137741, + 'longitudeDelta': 10.0, + 'name': 'Gibraltar', + 'longitude': -5.345374, + 'latitudeDelta': 10.0, }, { - "latitude": 39.074208, - "longitudeDelta": 10.0, - "name": "Greece", - "longitude": 21.824312, - "latitudeDelta": 10.0 + 'latitude': 39.074208, + 'longitudeDelta': 10.0, + 'name': 'Greece', + 'longitude': 21.824312, + 'latitudeDelta': 10.0, }, { - "latitude": 71.706936, - "longitudeDelta": 10.0, - "name": "Greenland", - "longitude": -42.604303, - "latitudeDelta": 10.0 + 'latitude': 71.706936, + 'longitudeDelta': 10.0, + 'name': 'Greenland', + 'longitude': -42.604303, + 'latitudeDelta': 10.0, }, { - "latitude": 12.262776, - "longitudeDelta": 10.0, - "name": "Grenada", - "longitude": -61.604171, - "latitudeDelta": 10.0 + 'latitude': 12.262776, + 'longitudeDelta': 10.0, + 'name': 'Grenada', + 'longitude': -61.604171, + 'latitudeDelta': 10.0, }, { - "latitude": 16.995971, - "longitudeDelta": 10.0, - "name": "Guadeloupe", - "longitude": -62.067641, - "latitudeDelta": 10.0 + 'latitude': 16.995971, + 'longitudeDelta': 10.0, + 'name': 'Guadeloupe', + 'longitude': -62.067641, + 'latitudeDelta': 10.0, }, { - "latitude": 13.444304, - "longitudeDelta": 10.0, - "name": "Guam", - "longitude": 144.793731, - "latitudeDelta": 10.0 + 'latitude': 13.444304, + 'longitudeDelta': 10.0, + 'name': 'Guam', + 'longitude': 144.793731, + 'latitudeDelta': 10.0, }, { - "latitude": 15.783471, - "longitudeDelta": 10.0, - "name": "Guatemala", - "longitude": -90.230759, - "latitudeDelta": 10.0 + 'latitude': 15.783471, + 'longitudeDelta': 10.0, + 'name': 'Guatemala', + 'longitude': -90.230759, + 'latitudeDelta': 10.0, }, { - "latitude": 49.465691, - "longitudeDelta": 10.0, - "name": "Guernsey", - "longitude": -2.585278, - "latitudeDelta": 10.0 + 'latitude': 49.465691, + 'longitudeDelta': 10.0, + 'name': 'Guernsey', + 'longitude': -2.585278, + 'latitudeDelta': 10.0, }, { - "latitude": 9.945587, - "longitudeDelta": 10.0, - "name": "Guinea", - "longitude": -9.696645, - "latitudeDelta": 10.0 + 'latitude': 9.945587, + 'longitudeDelta': 10.0, + 'name': 'Guinea', + 'longitude': -9.696645, + 'latitudeDelta': 10.0, }, { - "latitude": 11.803749, - "longitudeDelta": 10.0, - "name": "Guinea-Bissau", - "longitude": -15.180413, - "latitudeDelta": 10.0 + 'latitude': 11.803749, + 'longitudeDelta': 10.0, + 'name': 'Guinea-Bissau', + 'longitude': -15.180413, + 'latitudeDelta': 10.0, }, { - "latitude": 4.860416, - "longitudeDelta": 10.0, - "name": "Guyana", - "longitude": -58.93018, - "latitudeDelta": 10.0 + 'latitude': 4.860416, + 'longitudeDelta': 10.0, + 'name': 'Guyana', + 'longitude': -58.93018, + 'latitudeDelta': 10.0, }, { - "latitude": 18.971187, - "longitudeDelta": 10.0, - "name": "Haiti", - "longitude": -72.285215, - "latitudeDelta": 10.0 + 'latitude': 18.971187, + 'longitudeDelta': 10.0, + 'name': 'Haiti', + 'longitude': -72.285215, + 'latitudeDelta': 10.0, }, { - "latitude": -53.08181, - "longitudeDelta": 10.0, - "name": "Heard Island and McDonald Islands", - "longitude": 73.504158, - "latitudeDelta": 10.0 + 'latitude': -53.08181, + 'longitudeDelta': 10.0, + 'name': 'Heard Island and McDonald Islands', + 'longitude': 73.504158, + 'latitudeDelta': 10.0, }, { - "latitude": 15.199999, - "longitudeDelta": 10.0, - "name": "Honduras", - "longitude": -86.241905, - "latitudeDelta": 10.0 + 'latitude': 15.199999, + 'longitudeDelta': 10.0, + 'name': 'Honduras', + 'longitude': -86.241905, + 'latitudeDelta': 10.0, }, { - "latitude": 22.396428, - "longitudeDelta": 10.0, - "name": "Hong Kong", - "longitude": 114.109497, - "latitudeDelta": 10.0 + 'latitude': 22.396428, + 'longitudeDelta': 10.0, + 'name': 'Hong Kong', + 'longitude': 114.109497, + 'latitudeDelta': 10.0, }, { - "latitude": 47.162494, - "longitudeDelta": 10.0, - "name": "Hungary", - "longitude": 19.503304, - "latitudeDelta": 10.0 + 'latitude': 47.162494, + 'longitudeDelta': 10.0, + 'name': 'Hungary', + 'longitude': 19.503304, + 'latitudeDelta': 10.0, }, { - "latitude": 64.963051, - "longitudeDelta": 10.0, - "name": "Iceland", - "longitude": -19.020835, - "latitudeDelta": 10.0 + 'latitude': 64.963051, + 'longitudeDelta': 10.0, + 'name': 'Iceland', + 'longitude': -19.020835, + 'latitudeDelta': 10.0, }, { - "latitude": 20.593684, - "longitudeDelta": 10.0, - "name": "India", - "longitude": 78.96288, - "latitudeDelta": 10.0 + 'latitude': 20.593684, + 'longitudeDelta': 10.0, + 'name': 'India', + 'longitude': 78.96288, + 'latitudeDelta': 10.0, }, { - "latitude": -0.789275, - "longitudeDelta": 10.0, - "name": "Indonesia", - "longitude": 113.921327, - "latitudeDelta": 10.0 + 'latitude': -0.789275, + 'longitudeDelta': 10.0, + 'name': 'Indonesia', + 'longitude': 113.921327, + 'latitudeDelta': 10.0, }, { - "latitude": 32.427908, - "longitudeDelta": 10.0, - "name": "Iran", - "longitude": 53.688046, - "latitudeDelta": 10.0 + 'latitude': 32.427908, + 'longitudeDelta': 10.0, + 'name': 'Iran', + 'longitude': 53.688046, + 'latitudeDelta': 10.0, }, { - "latitude": 33.223191, - "longitudeDelta": 10.0, - "name": "Iraq", - "longitude": 43.679291, - "latitudeDelta": 10.0 + 'latitude': 33.223191, + 'longitudeDelta': 10.0, + 'name': 'Iraq', + 'longitude': 43.679291, + 'latitudeDelta': 10.0, }, { - "latitude": 53.41291, - "longitudeDelta": 10.0, - "name": "Ireland", - "longitude": -8.24389, - "latitudeDelta": 10.0 + 'latitude': 53.41291, + 'longitudeDelta': 10.0, + 'name': 'Ireland', + 'longitude': -8.24389, + 'latitudeDelta': 10.0, }, { - "latitude": 54.236107, - "longitudeDelta": 10.0, - "name": "Isle of Man", - "longitude": -4.548056, - "latitudeDelta": 10.0 + 'latitude': 54.236107, + 'longitudeDelta': 10.0, + 'name': 'Isle of Man', + 'longitude': -4.548056, + 'latitudeDelta': 10.0, }, { - "latitude": 31.046051, - "longitudeDelta": 10.0, - "name": "Israel", - "longitude": 34.851612, - "latitudeDelta": 10.0 + 'latitude': 31.046051, + 'longitudeDelta': 10.0, + 'name': 'Israel', + 'longitude': 34.851612, + 'latitudeDelta': 10.0, }, { - "latitude": 41.87194, - "longitudeDelta": 10.0, - "name": "Italy", - "longitude": 12.56738, - "latitudeDelta": 10.0 + 'latitude': 41.87194, + 'longitudeDelta': 10.0, + 'name': 'Italy', + 'longitude': 12.56738, + 'latitudeDelta': 10.0, }, { - "latitude": 18.109581, - "longitudeDelta": 10.0, - "name": "Jamaica", - "longitude": -77.297508, - "latitudeDelta": 10.0 + 'latitude': 18.109581, + 'longitudeDelta': 10.0, + 'name': 'Jamaica', + 'longitude': -77.297508, + 'latitudeDelta': 10.0, }, { - "latitude": 36.204824, - "longitudeDelta": 10.0, - "name": "Japan", - "longitude": 138.252924, - "latitudeDelta": 10.0 + 'latitude': 36.204824, + 'longitudeDelta': 10.0, + 'name': 'Japan', + 'longitude': 138.252924, + 'latitudeDelta': 10.0, }, { - "latitude": 49.214439, - "longitudeDelta": 10.0, - "name": "Jersey", - "longitude": -2.13125, - "latitudeDelta": 10.0 + 'latitude': 49.214439, + 'longitudeDelta': 10.0, + 'name': 'Jersey', + 'longitude': -2.13125, + 'latitudeDelta': 10.0, }, { - "latitude": 30.585164, - "longitudeDelta": 10.0, - "name": "Jordan", - "longitude": 36.238414, - "latitudeDelta": 10.0 + 'latitude': 30.585164, + 'longitudeDelta': 10.0, + 'name': 'Jordan', + 'longitude': 36.238414, + 'latitudeDelta': 10.0, }, { - "latitude": 48.019573, - "longitudeDelta": 10.0, - "name": "Kazakhstan", - "longitude": 66.923684, - "latitudeDelta": 10.0 + 'latitude': 48.019573, + 'longitudeDelta': 10.0, + 'name': 'Kazakhstan', + 'longitude': 66.923684, + 'latitudeDelta': 10.0, }, { - "latitude": -0.023559, - "longitudeDelta": 10.0, - "name": "Kenya", - "longitude": 37.906193, - "latitudeDelta": 10.0 + 'latitude': -0.023559, + 'longitudeDelta': 10.0, + 'name': 'Kenya', + 'longitude': 37.906193, + 'latitudeDelta': 10.0, }, { - "latitude": -3.370417, - "longitudeDelta": 10.0, - "name": "Kiribati", - "longitude": -168.734039, - "latitudeDelta": 10.0 + 'latitude': -3.370417, + 'longitudeDelta': 10.0, + 'name': 'Kiribati', + 'longitude': -168.734039, + 'latitudeDelta': 10.0, }, { - "latitude": 42.602636, - "longitudeDelta": 10.0, - "name": "Kosovo", - "longitude": 20.902977, - "latitudeDelta": 10.0 + 'latitude': 42.602636, + 'longitudeDelta': 10.0, + 'name': 'Kosovo', + 'longitude': 20.902977, + 'latitudeDelta': 10.0, }, { - "latitude": 29.31166, - "longitudeDelta": 10.0, - "name": "Kuwait", - "longitude": 47.481766, - "latitudeDelta": 10.0 + 'latitude': 29.31166, + 'longitudeDelta': 10.0, + 'name': 'Kuwait', + 'longitude': 47.481766, + 'latitudeDelta': 10.0, }, { - "latitude": 41.20438, - "longitudeDelta": 10.0, - "name": "Kyrgyzstan", - "longitude": 74.766098, - "latitudeDelta": 10.0 + 'latitude': 41.20438, + 'longitudeDelta': 10.0, + 'name': 'Kyrgyzstan', + 'longitude': 74.766098, + 'latitudeDelta': 10.0, }, { - "latitude": 19.85627, - "longitudeDelta": 10.0, - "name": "Laos", - "longitude": 102.495496, - "latitudeDelta": 10.0 + 'latitude': 19.85627, + 'longitudeDelta': 10.0, + 'name': 'Laos', + 'longitude': 102.495496, + 'latitudeDelta': 10.0, }, { - "latitude": 56.879635, - "longitudeDelta": 10.0, - "name": "Latvia", - "longitude": 24.603189, - "latitudeDelta": 10.0 + 'latitude': 56.879635, + 'longitudeDelta': 10.0, + 'name': 'Latvia', + 'longitude': 24.603189, + 'latitudeDelta': 10.0, }, { - "latitude": 33.854721, - "longitudeDelta": 10.0, - "name": "Lebanon", - "longitude": 35.862285, - "latitudeDelta": 10.0 + 'latitude': 33.854721, + 'longitudeDelta': 10.0, + 'name': 'Lebanon', + 'longitude': 35.862285, + 'latitudeDelta': 10.0, }, { - "latitude": -29.609988, - "longitudeDelta": 10.0, - "name": "Lesotho", - "longitude": 28.233608, - "latitudeDelta": 10.0 + 'latitude': -29.609988, + 'longitudeDelta': 10.0, + 'name': 'Lesotho', + 'longitude': 28.233608, + 'latitudeDelta': 10.0, }, { - "latitude": 6.428055, - "longitudeDelta": 10.0, - "name": "Liberia", - "longitude": -9.429499, - "latitudeDelta": 10.0 + 'latitude': 6.428055, + 'longitudeDelta': 10.0, + 'name': 'Liberia', + 'longitude': -9.429499, + 'latitudeDelta': 10.0, }, { - "latitude": 26.3351, - "longitudeDelta": 10.0, - "name": "Libya", - "longitude": 17.228331, - "latitudeDelta": 10.0 + 'latitude': 26.3351, + 'longitudeDelta': 10.0, + 'name': 'Libya', + 'longitude': 17.228331, + 'latitudeDelta': 10.0, }, { - "latitude": 47.166, - "longitudeDelta": 10.0, - "name": "Liechtenstein", - "longitude": 9.555373, - "latitudeDelta": 10.0 + 'latitude': 47.166, + 'longitudeDelta': 10.0, + 'name': 'Liechtenstein', + 'longitude': 9.555373, + 'latitudeDelta': 10.0, }, { - "latitude": 55.169438, - "longitudeDelta": 10.0, - "name": "Lithuania", - "longitude": 23.881275, - "latitudeDelta": 10.0 + 'latitude': 55.169438, + 'longitudeDelta': 10.0, + 'name': 'Lithuania', + 'longitude': 23.881275, + 'latitudeDelta': 10.0, }, { - "latitude": 49.815273, - "longitudeDelta": 10.0, - "name": "Luxembourg", - "longitude": 6.129583, - "latitudeDelta": 10.0 + 'latitude': 49.815273, + 'longitudeDelta': 10.0, + 'name': 'Luxembourg', + 'longitude': 6.129583, + 'latitudeDelta': 10.0, }, { - "latitude": 22.198745, - "longitudeDelta": 10.0, - "name": "Macau", - "longitude": 113.543873, - "latitudeDelta": 10.0 + 'latitude': 22.198745, + 'longitudeDelta': 10.0, + 'name': 'Macau', + 'longitude': 113.543873, + 'latitudeDelta': 10.0, }, { - "latitude": 41.608635, - "longitudeDelta": 10.0, - "name": "Macedonia [FYROM]", - "longitude": 21.745275, - "latitudeDelta": 10.0 + 'latitude': 41.608635, + 'longitudeDelta': 10.0, + 'name': 'Macedonia [FYROM]', + 'longitude': 21.745275, + 'latitudeDelta': 10.0, }, { - "latitude": -18.766947, - "longitudeDelta": 10.0, - "name": "Madagascar", - "longitude": 46.869107, - "latitudeDelta": 10.0 + 'latitude': -18.766947, + 'longitudeDelta': 10.0, + 'name': 'Madagascar', + 'longitude': 46.869107, + 'latitudeDelta': 10.0, }, { - "latitude": -13.254308, - "longitudeDelta": 10.0, - "name": "Malawi", - "longitude": 34.301525, - "latitudeDelta": 10.0 + 'latitude': -13.254308, + 'longitudeDelta': 10.0, + 'name': 'Malawi', + 'longitude': 34.301525, + 'latitudeDelta': 10.0, }, { - "latitude": 4.210484, - "longitudeDelta": 10.0, - "name": "Malaysia", - "longitude": 101.975766, - "latitudeDelta": 10.0 + 'latitude': 4.210484, + 'longitudeDelta': 10.0, + 'name': 'Malaysia', + 'longitude': 101.975766, + 'latitudeDelta': 10.0, }, { - "latitude": 3.202778, - "longitudeDelta": 10.0, - "name": "Maldives", - "longitude": 73.22068, - "latitudeDelta": 10.0 + 'latitude': 3.202778, + 'longitudeDelta': 10.0, + 'name': 'Maldives', + 'longitude': 73.22068, + 'latitudeDelta': 10.0, }, { - "latitude": 17.570692, - "longitudeDelta": 10.0, - "name": "Mali", - "longitude": -3.996166, - "latitudeDelta": 10.0 + 'latitude': 17.570692, + 'longitudeDelta': 10.0, + 'name': 'Mali', + 'longitude': -3.996166, + 'latitudeDelta': 10.0, }, { - "latitude": 35.937496, - "longitudeDelta": 10.0, - "name": "Malta", - "longitude": 14.375416, - "latitudeDelta": 10.0 + 'latitude': 35.937496, + 'longitudeDelta': 10.0, + 'name': 'Malta', + 'longitude': 14.375416, + 'latitudeDelta': 10.0, }, { - "latitude": 7.131474, - "longitudeDelta": 10.0, - "name": "Marshall Islands", - "longitude": 171.184478, - "latitudeDelta": 10.0 + 'latitude': 7.131474, + 'longitudeDelta': 10.0, + 'name': 'Marshall Islands', + 'longitude': 171.184478, + 'latitudeDelta': 10.0, }, { - "latitude": 14.641528, - "longitudeDelta": 10.0, - "name": "Martinique", - "longitude": -61.024174, - "latitudeDelta": 10.0 + 'latitude': 14.641528, + 'longitudeDelta': 10.0, + 'name': 'Martinique', + 'longitude': -61.024174, + 'latitudeDelta': 10.0, }, { - "latitude": 21.00789, - "longitudeDelta": 10.0, - "name": "Mauritania", - "longitude": -10.940835, - "latitudeDelta": 10.0 + 'latitude': 21.00789, + 'longitudeDelta': 10.0, + 'name': 'Mauritania', + 'longitude': -10.940835, + 'latitudeDelta': 10.0, }, { - "latitude": -20.348404, - "longitudeDelta": 10.0, - "name": "Mauritius", - "longitude": 57.552152, - "latitudeDelta": 10.0 + 'latitude': -20.348404, + 'longitudeDelta': 10.0, + 'name': 'Mauritius', + 'longitude': 57.552152, + 'latitudeDelta': 10.0, }, { - "latitude": -12.8275, - "longitudeDelta": 10.0, - "name": "Mayotte", - "longitude": 45.166244, - "latitudeDelta": 10.0 + 'latitude': -12.8275, + 'longitudeDelta': 10.0, + 'name': 'Mayotte', + 'longitude': 45.166244, + 'latitudeDelta': 10.0, }, { - "latitude": 23.634501, - "longitudeDelta": 10.0, - "name": "Mexico", - "longitude": -102.552784, - "latitudeDelta": 10.0 + 'latitude': 23.634501, + 'longitudeDelta': 10.0, + 'name': 'Mexico', + 'longitude': -102.552784, + 'latitudeDelta': 10.0, }, { - "latitude": 7.425554, - "longitudeDelta": 10.0, - "name": "Micronesia", - "longitude": 150.550812, - "latitudeDelta": 10.0 + 'latitude': 7.425554, + 'longitudeDelta': 10.0, + 'name': 'Micronesia', + 'longitude': 150.550812, + 'latitudeDelta': 10.0, }, { - "latitude": 47.411631, - "longitudeDelta": 10.0, - "name": "Moldova", - "longitude": 28.369885, - "latitudeDelta": 10.0 + 'latitude': 47.411631, + 'longitudeDelta': 10.0, + 'name': 'Moldova', + 'longitude': 28.369885, + 'latitudeDelta': 10.0, }, { - "latitude": 43.750298, - "longitudeDelta": 10.0, - "name": "Monaco", - "longitude": 7.412841, - "latitudeDelta": 10.0 + 'latitude': 43.750298, + 'longitudeDelta': 10.0, + 'name': 'Monaco', + 'longitude': 7.412841, + 'latitudeDelta': 10.0, }, { - "latitude": 46.862496, - "longitudeDelta": 10.0, - "name": "Mongolia", - "longitude": 103.846656, - "latitudeDelta": 10.0 + 'latitude': 46.862496, + 'longitudeDelta': 10.0, + 'name': 'Mongolia', + 'longitude': 103.846656, + 'latitudeDelta': 10.0, }, { - "latitude": 42.708678, - "longitudeDelta": 10.0, - "name": "Montenegro", - "longitude": 19.37439, - "latitudeDelta": 10.0 + 'latitude': 42.708678, + 'longitudeDelta': 10.0, + 'name': 'Montenegro', + 'longitude': 19.37439, + 'latitudeDelta': 10.0, }, { - "latitude": 16.742498, - "longitudeDelta": 10.0, - "name": "Montserrat", - "longitude": -62.187366, - "latitudeDelta": 10.0 + 'latitude': 16.742498, + 'longitudeDelta': 10.0, + 'name': 'Montserrat', + 'longitude': -62.187366, + 'latitudeDelta': 10.0, }, { - "latitude": 31.791702, - "longitudeDelta": 10.0, - "name": "Morocco", - "longitude": -7.09262, - "latitudeDelta": 10.0 + 'latitude': 31.791702, + 'longitudeDelta': 10.0, + 'name': 'Morocco', + 'longitude': -7.09262, + 'latitudeDelta': 10.0, }, { - "latitude": -18.665695, - "longitudeDelta": 10.0, - "name": "Mozambique", - "longitude": 35.529562, - "latitudeDelta": 10.0 + 'latitude': -18.665695, + 'longitudeDelta': 10.0, + 'name': 'Mozambique', + 'longitude': 35.529562, + 'latitudeDelta': 10.0, }, { - "latitude": 21.913965, - "longitudeDelta": 10.0, - "name": "Myanmar [Burma]", - "longitude": 95.956223, - "latitudeDelta": 10.0 + 'latitude': 21.913965, + 'longitudeDelta': 10.0, + 'name': 'Myanmar [Burma]', + 'longitude': 95.956223, + 'latitudeDelta': 10.0, }, { - "latitude": -22.95764, - "longitudeDelta": 10.0, - "name": "Namibia", - "longitude": 18.49041, - "latitudeDelta": 10.0 + 'latitude': -22.95764, + 'longitudeDelta': 10.0, + 'name': 'Namibia', + 'longitude': 18.49041, + 'latitudeDelta': 10.0, }, { - "latitude": -0.522778, - "longitudeDelta": 10.0, - "name": "Nauru", - "longitude": 166.931503, - "latitudeDelta": 10.0 + 'latitude': -0.522778, + 'longitudeDelta': 10.0, + 'name': 'Nauru', + 'longitude': 166.931503, + 'latitudeDelta': 10.0, }, { - "latitude": 28.394857, - "longitudeDelta": 10.0, - "name": "Nepal", - "longitude": 84.124008, - "latitudeDelta": 10.0 + 'latitude': 28.394857, + 'longitudeDelta': 10.0, + 'name': 'Nepal', + 'longitude': 84.124008, + 'latitudeDelta': 10.0, }, { - "latitude": 52.132633, - "longitudeDelta": 10.0, - "name": "Netherlands", - "longitude": 5.291266, - "latitudeDelta": 10.0 + 'latitude': 52.132633, + 'longitudeDelta': 10.0, + 'name': 'Netherlands', + 'longitude': 5.291266, + 'latitudeDelta': 10.0, }, { - "latitude": 12.226079, - "longitudeDelta": 10.0, - "name": "Netherlands Antilles", - "longitude": -69.060087, - "latitudeDelta": 10.0 + 'latitude': 12.226079, + 'longitudeDelta': 10.0, + 'name': 'Netherlands Antilles', + 'longitude': -69.060087, + 'latitudeDelta': 10.0, }, { - "latitude": -20.904305, - "longitudeDelta": 10.0, - "name": "New Caledonia", - "longitude": 165.618042, - "latitudeDelta": 10.0 + 'latitude': -20.904305, + 'longitudeDelta': 10.0, + 'name': 'New Caledonia', + 'longitude': 165.618042, + 'latitudeDelta': 10.0, }, { - "latitude": -40.900557, - "longitudeDelta": 10.0, - "name": "New Zealand", - "longitude": 174.885971, - "latitudeDelta": 10.0 + 'latitude': -40.900557, + 'longitudeDelta': 10.0, + 'name': 'New Zealand', + 'longitude': 174.885971, + 'latitudeDelta': 10.0, }, { - "latitude": 12.865416, - "longitudeDelta": 10.0, - "name": "Nicaragua", - "longitude": -85.207229, - "latitudeDelta": 10.0 + 'latitude': 12.865416, + 'longitudeDelta': 10.0, + 'name': 'Nicaragua', + 'longitude': -85.207229, + 'latitudeDelta': 10.0, }, { - "latitude": 17.607789, - "longitudeDelta": 10.0, - "name": "Niger", - "longitude": 8.081666, - "latitudeDelta": 10.0 + 'latitude': 17.607789, + 'longitudeDelta': 10.0, + 'name': 'Niger', + 'longitude': 8.081666, + 'latitudeDelta': 10.0, }, { - "latitude": 9.081999, - "longitudeDelta": 10.0, - "name": "Nigeria", - "longitude": 8.675277, - "latitudeDelta": 10.0 + 'latitude': 9.081999, + 'longitudeDelta': 10.0, + 'name': 'Nigeria', + 'longitude': 8.675277, + 'latitudeDelta': 10.0, }, { - "latitude": -19.054445, - "longitudeDelta": 10.0, - "name": "Niue", - "longitude": -169.867233, - "latitudeDelta": 10.0 + 'latitude': -19.054445, + 'longitudeDelta': 10.0, + 'name': 'Niue', + 'longitude': -169.867233, + 'latitudeDelta': 10.0, }, { - "latitude": -29.040835, - "longitudeDelta": 10.0, - "name": "Norfolk Island", - "longitude": 167.954712, - "latitudeDelta": 10.0 + 'latitude': -29.040835, + 'longitudeDelta': 10.0, + 'name': 'Norfolk Island', + 'longitude': 167.954712, + 'latitudeDelta': 10.0, }, { - "latitude": 40.339852, - "longitudeDelta": 10.0, - "name": "North Korea", - "longitude": 127.510093, - "latitudeDelta": 10.0 + 'latitude': 40.339852, + 'longitudeDelta': 10.0, + 'name': 'North Korea', + 'longitude': 127.510093, + 'latitudeDelta': 10.0, }, { - "latitude": 17.33083, - "longitudeDelta": 10.0, - "name": "Northern Mariana Islands", - "longitude": 145.38469, - "latitudeDelta": 10.0 + 'latitude': 17.33083, + 'longitudeDelta': 10.0, + 'name': 'Northern Mariana Islands', + 'longitude': 145.38469, + 'latitudeDelta': 10.0, }, { - "latitude": 60.472024, - "longitudeDelta": 10.0, - "name": "Norway", - "longitude": 8.468946, - "latitudeDelta": 10.0 + 'latitude': 60.472024, + 'longitudeDelta': 10.0, + 'name': 'Norway', + 'longitude': 8.468946, + 'latitudeDelta': 10.0, }, { - "latitude": 21.512583, - "longitudeDelta": 10.0, - "name": "Oman", - "longitude": 55.923255, - "latitudeDelta": 10.0 + 'latitude': 21.512583, + 'longitudeDelta': 10.0, + 'name': 'Oman', + 'longitude': 55.923255, + 'latitudeDelta': 10.0, }, { - "latitude": 30.375321, - "longitudeDelta": 10.0, - "name": "Pakistan", - "longitude": 69.345116, - "latitudeDelta": 10.0 + 'latitude': 30.375321, + 'longitudeDelta': 10.0, + 'name': 'Pakistan', + 'longitude': 69.345116, + 'latitudeDelta': 10.0, }, { - "latitude": 7.51498, - "longitudeDelta": 10.0, - "name": "Palau", - "longitude": 134.58252, - "latitudeDelta": 10.0 + 'latitude': 7.51498, + 'longitudeDelta': 10.0, + 'name': 'Palau', + 'longitude': 134.58252, + 'latitudeDelta': 10.0, }, { - "latitude": 31.952162, - "longitudeDelta": 10.0, - "name": "Palestinian Territories", - "longitude": 35.233154, - "latitudeDelta": 10.0 + 'latitude': 31.952162, + 'longitudeDelta': 10.0, + 'name': 'Palestinian Territories', + 'longitude': 35.233154, + 'latitudeDelta': 10.0, }, { - "latitude": 8.537981, - "longitudeDelta": 10.0, - "name": "Panama", - "longitude": -80.782127, - "latitudeDelta": 10.0 + 'latitude': 8.537981, + 'longitudeDelta': 10.0, + 'name': 'Panama', + 'longitude': -80.782127, + 'latitudeDelta': 10.0, }, { - "latitude": -6.314993, - "longitudeDelta": 10.0, - "name": "Papua New Guinea", - "longitude": 143.95555, - "latitudeDelta": 10.0 + 'latitude': -6.314993, + 'longitudeDelta': 10.0, + 'name': 'Papua New Guinea', + 'longitude': 143.95555, + 'latitudeDelta': 10.0, }, { - "latitude": -23.442503, - "longitudeDelta": 10.0, - "name": "Paraguay", - "longitude": -58.443832, - "latitudeDelta": 10.0 + 'latitude': -23.442503, + 'longitudeDelta': 10.0, + 'name': 'Paraguay', + 'longitude': -58.443832, + 'latitudeDelta': 10.0, }, { - "latitude": -9.189967, - "longitudeDelta": 10.0, - "name": "Peru", - "longitude": -75.015152, - "latitudeDelta": 10.0 + 'latitude': -9.189967, + 'longitudeDelta': 10.0, + 'name': 'Peru', + 'longitude': -75.015152, + 'latitudeDelta': 10.0, }, { - "latitude": 12.879721, - "longitudeDelta": 10.0, - "name": "Philippines", - "longitude": 121.774017, - "latitudeDelta": 10.0 + 'latitude': 12.879721, + 'longitudeDelta': 10.0, + 'name': 'Philippines', + 'longitude': 121.774017, + 'latitudeDelta': 10.0, }, { - "latitude": -24.703615, - "longitudeDelta": 10.0, - "name": "Pitcairn Islands", - "longitude": -127.439308, - "latitudeDelta": 10.0 + 'latitude': -24.703615, + 'longitudeDelta': 10.0, + 'name': 'Pitcairn Islands', + 'longitude': -127.439308, + 'latitudeDelta': 10.0, }, { - "latitude": 51.919438, - "longitudeDelta": 10.0, - "name": "Poland", - "longitude": 19.145136, - "latitudeDelta": 10.0 + 'latitude': 51.919438, + 'longitudeDelta': 10.0, + 'name': 'Poland', + 'longitude': 19.145136, + 'latitudeDelta': 10.0, }, { - "latitude": 39.399872, - "longitudeDelta": 10.0, - "name": "Portugal", - "longitude": -8.224454, - "latitudeDelta": 10.0 + 'latitude': 39.399872, + 'longitudeDelta': 10.0, + 'name': 'Portugal', + 'longitude': -8.224454, + 'latitudeDelta': 10.0, }, { - "latitude": 18.220833, - "longitudeDelta": 10.0, - "name": "Puerto Rico", - "longitude": -66.590149, - "latitudeDelta": 10.0 + 'latitude': 18.220833, + 'longitudeDelta': 10.0, + 'name': 'Puerto Rico', + 'longitude': -66.590149, + 'latitudeDelta': 10.0, }, { - "latitude": 25.354826, - "longitudeDelta": 10.0, - "name": "Qatar", - "longitude": 51.183884, - "latitudeDelta": 10.0 + 'latitude': 25.354826, + 'longitudeDelta': 10.0, + 'name': 'Qatar', + 'longitude': 51.183884, + 'latitudeDelta': 10.0, }, { - "latitude": 45.943161, - "longitudeDelta": 10.0, - "name": "Romania", - "longitude": 24.96676, - "latitudeDelta": 10.0 + 'latitude': 45.943161, + 'longitudeDelta': 10.0, + 'name': 'Romania', + 'longitude': 24.96676, + 'latitudeDelta': 10.0, }, { - "latitude": 61.52401, - "longitudeDelta": 10.0, - "name": "Russia", - "longitude": 105.318756, - "latitudeDelta": 10.0 + 'latitude': 61.52401, + 'longitudeDelta': 10.0, + 'name': 'Russia', + 'longitude': 105.318756, + 'latitudeDelta': 10.0, }, { - "latitude": -1.940278, - "longitudeDelta": 10.0, - "name": "Rwanda", - "longitude": 29.873888, - "latitudeDelta": 10.0 + 'latitude': -1.940278, + 'longitudeDelta': 10.0, + 'name': 'Rwanda', + 'longitude': 29.873888, + 'latitudeDelta': 10.0, }, { - "latitude": -21.115141, - "longitudeDelta": 10.0, - "name": "R\u00e9union", - "longitude": 55.536384, - "latitudeDelta": 10.0 + 'latitude': -21.115141, + 'longitudeDelta': 10.0, + 'name': 'R\u00e9union', + 'longitude': 55.536384, + 'latitudeDelta': 10.0, }, { - "latitude": -24.143474, - "longitudeDelta": 10.0, - "name": "Saint Helena", - "longitude": -10.030696, - "latitudeDelta": 10.0 + 'latitude': -24.143474, + 'longitudeDelta': 10.0, + 'name': 'Saint Helena', + 'longitude': -10.030696, + 'latitudeDelta': 10.0, }, { - "latitude": 17.357822, - "longitudeDelta": 10.0, - "name": "Saint Kitts and Nevis", - "longitude": -62.782998, - "latitudeDelta": 10.0 + 'latitude': 17.357822, + 'longitudeDelta': 10.0, + 'name': 'Saint Kitts and Nevis', + 'longitude': -62.782998, + 'latitudeDelta': 10.0, }, { - "latitude": 13.909444, - "longitudeDelta": 10.0, - "name": "Saint Lucia", - "longitude": -60.978893, - "latitudeDelta": 10.0 + 'latitude': 13.909444, + 'longitudeDelta': 10.0, + 'name': 'Saint Lucia', + 'longitude': -60.978893, + 'latitudeDelta': 10.0, }, { - "latitude": 46.941936, - "longitudeDelta": 10.0, - "name": "Saint Pierre and Miquelon", - "longitude": -56.27111, - "latitudeDelta": 10.0 + 'latitude': 46.941936, + 'longitudeDelta': 10.0, + 'name': 'Saint Pierre and Miquelon', + 'longitude': -56.27111, + 'latitudeDelta': 10.0, }, { - "latitude": 12.984305, - "longitudeDelta": 10.0, - "name": "Saint Vincent and the Grenadines", - "longitude": -61.287228, - "latitudeDelta": 10.0 + 'latitude': 12.984305, + 'longitudeDelta': 10.0, + 'name': 'Saint Vincent and the Grenadines', + 'longitude': -61.287228, + 'latitudeDelta': 10.0, }, { - "latitude": -13.759029, - "longitudeDelta": 10.0, - "name": "Samoa", - "longitude": -172.104629, - "latitudeDelta": 10.0 + 'latitude': -13.759029, + 'longitudeDelta': 10.0, + 'name': 'Samoa', + 'longitude': -172.104629, + 'latitudeDelta': 10.0, }, { - "latitude": 43.94236, - "longitudeDelta": 10.0, - "name": "San Marino", - "longitude": 12.457777, - "latitudeDelta": 10.0 + 'latitude': 43.94236, + 'longitudeDelta': 10.0, + 'name': 'San Marino', + 'longitude': 12.457777, + 'latitudeDelta': 10.0, }, { - "latitude": 23.885942, - "longitudeDelta": 10.0, - "name": "Saudi Arabia", - "longitude": 45.079162, - "latitudeDelta": 10.0 + 'latitude': 23.885942, + 'longitudeDelta': 10.0, + 'name': 'Saudi Arabia', + 'longitude': 45.079162, + 'latitudeDelta': 10.0, }, { - "latitude": 14.497401, - "longitudeDelta": 10.0, - "name": "Senegal", - "longitude": -14.452362, - "latitudeDelta": 10.0 + 'latitude': 14.497401, + 'longitudeDelta': 10.0, + 'name': 'Senegal', + 'longitude': -14.452362, + 'latitudeDelta': 10.0, }, { - "latitude": 44.016521, - "longitudeDelta": 10.0, - "name": "Serbia", - "longitude": 21.005859, - "latitudeDelta": 10.0 + 'latitude': 44.016521, + 'longitudeDelta': 10.0, + 'name': 'Serbia', + 'longitude': 21.005859, + 'latitudeDelta': 10.0, }, { - "latitude": -4.679574, - "longitudeDelta": 10.0, - "name": "Seychelles", - "longitude": 55.491977, - "latitudeDelta": 10.0 + 'latitude': -4.679574, + 'longitudeDelta': 10.0, + 'name': 'Seychelles', + 'longitude': 55.491977, + 'latitudeDelta': 10.0, }, { - "latitude": 8.460555, - "longitudeDelta": 10.0, - "name": "Sierra Leone", - "longitude": -11.779889, - "latitudeDelta": 10.0 + 'latitude': 8.460555, + 'longitudeDelta': 10.0, + 'name': 'Sierra Leone', + 'longitude': -11.779889, + 'latitudeDelta': 10.0, }, { - "latitude": 1.352083, - "longitudeDelta": 10.0, - "name": "Singapore", - "longitude": 103.819836, - "latitudeDelta": 10.0 + 'latitude': 1.352083, + 'longitudeDelta': 10.0, + 'name': 'Singapore', + 'longitude': 103.819836, + 'latitudeDelta': 10.0, }, { - "latitude": 48.669026, - "longitudeDelta": 10.0, - "name": "Slovakia", - "longitude": 19.699024, - "latitudeDelta": 10.0 + 'latitude': 48.669026, + 'longitudeDelta': 10.0, + 'name': 'Slovakia', + 'longitude': 19.699024, + 'latitudeDelta': 10.0, }, { - "latitude": 46.151241, - "longitudeDelta": 10.0, - "name": "Slovenia", - "longitude": 14.995463, - "latitudeDelta": 10.0 + 'latitude': 46.151241, + 'longitudeDelta': 10.0, + 'name': 'Slovenia', + 'longitude': 14.995463, + 'latitudeDelta': 10.0, }, { - "latitude": -9.64571, - "longitudeDelta": 10.0, - "name": "Solomon Islands", - "longitude": 160.156194, - "latitudeDelta": 10.0 + 'latitude': -9.64571, + 'longitudeDelta': 10.0, + 'name': 'Solomon Islands', + 'longitude': 160.156194, + 'latitudeDelta': 10.0, }, { - "latitude": 5.152149, - "longitudeDelta": 10.0, - "name": "Somalia", - "longitude": 46.199616, - "latitudeDelta": 10.0 + 'latitude': 5.152149, + 'longitudeDelta': 10.0, + 'name': 'Somalia', + 'longitude': 46.199616, + 'latitudeDelta': 10.0, }, { - "latitude": -30.559482, - "longitudeDelta": 10.0, - "name": "South Africa", - "longitude": 22.937506, - "latitudeDelta": 10.0 + 'latitude': -30.559482, + 'longitudeDelta': 10.0, + 'name': 'South Africa', + 'longitude': 22.937506, + 'latitudeDelta': 10.0, }, { - "latitude": -54.429579, - "longitudeDelta": 10.0, - "name": "South Georgia and the South Sandwich Islands", - "longitude": -36.587909, - "latitudeDelta": 10.0 + 'latitude': -54.429579, + 'longitudeDelta': 10.0, + 'name': 'South Georgia and the South Sandwich Islands', + 'longitude': -36.587909, + 'latitudeDelta': 10.0, }, { - "latitude": 35.907757, - "longitudeDelta": 10.0, - "name": "South Korea", - "longitude": 127.766922, - "latitudeDelta": 10.0 + 'latitude': 35.907757, + 'longitudeDelta': 10.0, + 'name': 'South Korea', + 'longitude': 127.766922, + 'latitudeDelta': 10.0, }, { - "latitude": 40.463667, - "longitudeDelta": 10.0, - "name": "Spain", - "longitude": -3.74922, - "latitudeDelta": 10.0 + 'latitude': 40.463667, + 'longitudeDelta': 10.0, + 'name': 'Spain', + 'longitude': -3.74922, + 'latitudeDelta': 10.0, }, { - "latitude": 7.873054, - "longitudeDelta": 10.0, - "name": "Sri Lanka", - "longitude": 80.771797, - "latitudeDelta": 10.0 + 'latitude': 7.873054, + 'longitudeDelta': 10.0, + 'name': 'Sri Lanka', + 'longitude': 80.771797, + 'latitudeDelta': 10.0, }, { - "latitude": 12.862807, - "longitudeDelta": 10.0, - "name": "Sudan", - "longitude": 30.217636, - "latitudeDelta": 10.0 + 'latitude': 12.862807, + 'longitudeDelta': 10.0, + 'name': 'Sudan', + 'longitude': 30.217636, + 'latitudeDelta': 10.0, }, { - "latitude": 3.919305, - "longitudeDelta": 10.0, - "name": "Suriname", - "longitude": -56.027783, - "latitudeDelta": 10.0 + 'latitude': 3.919305, + 'longitudeDelta': 10.0, + 'name': 'Suriname', + 'longitude': -56.027783, + 'latitudeDelta': 10.0, }, { - "latitude": 77.553604, - "longitudeDelta": 10.0, - "name": "Svalbard and Jan Mayen", - "longitude": 23.670272, - "latitudeDelta": 10.0 + 'latitude': 77.553604, + 'longitudeDelta': 10.0, + 'name': 'Svalbard and Jan Mayen', + 'longitude': 23.670272, + 'latitudeDelta': 10.0, }, { - "latitude": -26.522503, - "longitudeDelta": 10.0, - "name": "Swaziland", - "longitude": 31.465866, - "latitudeDelta": 10.0 + 'latitude': -26.522503, + 'longitudeDelta': 10.0, + 'name': 'Swaziland', + 'longitude': 31.465866, + 'latitudeDelta': 10.0, }, { - "latitude": 60.128161, - "longitudeDelta": 10.0, - "name": "Sweden", - "longitude": 18.643501, - "latitudeDelta": 10.0 + 'latitude': 60.128161, + 'longitudeDelta': 10.0, + 'name': 'Sweden', + 'longitude': 18.643501, + 'latitudeDelta': 10.0, }, { - "latitude": 46.818188, - "longitudeDelta": 10.0, - "name": "Switzerland", - "longitude": 8.227512, - "latitudeDelta": 10.0 + 'latitude': 46.818188, + 'longitudeDelta': 10.0, + 'name': 'Switzerland', + 'longitude': 8.227512, + 'latitudeDelta': 10.0, }, { - "latitude": 34.802075, - "longitudeDelta": 10.0, - "name": "Syria", - "longitude": 38.996815, - "latitudeDelta": 10.0 + 'latitude': 34.802075, + 'longitudeDelta': 10.0, + 'name': 'Syria', + 'longitude': 38.996815, + 'latitudeDelta': 10.0, }, { - "latitude": 0.18636, - "longitudeDelta": 10.0, - "name": "S\u00e3o Tom\u00e9 and Pr\u00edncipe", - "longitude": 6.613081, - "latitudeDelta": 10.0 + 'latitude': 0.18636, + 'longitudeDelta': 10.0, + 'name': 'S\u00e3o Tom\u00e9 and Pr\u00edncipe', + 'longitude': 6.613081, + 'latitudeDelta': 10.0, }, { - "latitude": 23.69781, - "longitudeDelta": 10.0, - "name": "Taiwan", - "longitude": 120.960515, - "latitudeDelta": 10.0 + 'latitude': 23.69781, + 'longitudeDelta': 10.0, + 'name': 'Taiwan', + 'longitude': 120.960515, + 'latitudeDelta': 10.0, }, { - "latitude": 38.861034, - "longitudeDelta": 10.0, - "name": "Tajikistan", - "longitude": 71.276093, - "latitudeDelta": 10.0 + 'latitude': 38.861034, + 'longitudeDelta': 10.0, + 'name': 'Tajikistan', + 'longitude': 71.276093, + 'latitudeDelta': 10.0, }, { - "latitude": -6.369028, - "longitudeDelta": 10.0, - "name": "Tanzania", - "longitude": 34.888822, - "latitudeDelta": 10.0 + 'latitude': -6.369028, + 'longitudeDelta': 10.0, + 'name': 'Tanzania', + 'longitude': 34.888822, + 'latitudeDelta': 10.0, }, { - "latitude": 15.870032, - "longitudeDelta": 10.0, - "name": "Thailand", - "longitude": 100.992541, - "latitudeDelta": 10.0 + 'latitude': 15.870032, + 'longitudeDelta': 10.0, + 'name': 'Thailand', + 'longitude': 100.992541, + 'latitudeDelta': 10.0, }, { - "latitude": -8.874217, - "longitudeDelta": 10.0, - "name": "Timor-Leste", - "longitude": 125.727539, - "latitudeDelta": 10.0 + 'latitude': -8.874217, + 'longitudeDelta': 10.0, + 'name': 'Timor-Leste', + 'longitude': 125.727539, + 'latitudeDelta': 10.0, }, { - "latitude": 8.619543, - "longitudeDelta": 10.0, - "name": "Togo", - "longitude": 0.824782, - "latitudeDelta": 10.0 + 'latitude': 8.619543, + 'longitudeDelta': 10.0, + 'name': 'Togo', + 'longitude': 0.824782, + 'latitudeDelta': 10.0, }, { - "latitude": -8.967363, - "longitudeDelta": 10.0, - "name": "Tokelau", - "longitude": -171.855881, - "latitudeDelta": 10.0 + 'latitude': -8.967363, + 'longitudeDelta': 10.0, + 'name': 'Tokelau', + 'longitude': -171.855881, + 'latitudeDelta': 10.0, }, { - "latitude": -21.178986, - "longitudeDelta": 10.0, - "name": "Tonga", - "longitude": -175.198242, - "latitudeDelta": 10.0 + 'latitude': -21.178986, + 'longitudeDelta': 10.0, + 'name': 'Tonga', + 'longitude': -175.198242, + 'latitudeDelta': 10.0, }, { - "latitude": 10.691803, - "longitudeDelta": 10.0, - "name": "Trinidad and Tobago", - "longitude": -61.222503, - "latitudeDelta": 10.0 + 'latitude': 10.691803, + 'longitudeDelta': 10.0, + 'name': 'Trinidad and Tobago', + 'longitude': -61.222503, + 'latitudeDelta': 10.0, }, { - "latitude": 33.886917, - "longitudeDelta": 10.0, - "name": "Tunisia", - "longitude": 9.537499, - "latitudeDelta": 10.0 + 'latitude': 33.886917, + 'longitudeDelta': 10.0, + 'name': 'Tunisia', + 'longitude': 9.537499, + 'latitudeDelta': 10.0, }, { - "latitude": 38.963745, - "longitudeDelta": 10.0, - "name": "Turkey", - "longitude": 35.243322, - "latitudeDelta": 10.0 + 'latitude': 38.963745, + 'longitudeDelta': 10.0, + 'name': 'Turkey', + 'longitude': 35.243322, + 'latitudeDelta': 10.0, }, { - "latitude": 38.969719, - "longitudeDelta": 10.0, - "name": "Turkmenistan", - "longitude": 59.556278, - "latitudeDelta": 10.0 + 'latitude': 38.969719, + 'longitudeDelta': 10.0, + 'name': 'Turkmenistan', + 'longitude': 59.556278, + 'latitudeDelta': 10.0, }, { - "latitude": 21.694025, - "longitudeDelta": 10.0, - "name": "Turks and Caicos Islands", - "longitude": -71.797928, - "latitudeDelta": 10.0 + 'latitude': 21.694025, + 'longitudeDelta': 10.0, + 'name': 'Turks and Caicos Islands', + 'longitude': -71.797928, + 'latitudeDelta': 10.0, }, { - "latitude": -7.109535, - "longitudeDelta": 10.0, - "name": "Tuvalu", - "longitude": 177.64933, - "latitudeDelta": 10.0 + 'latitude': -7.109535, + 'longitudeDelta': 10.0, + 'name': 'Tuvalu', + 'longitude': 177.64933, + 'latitudeDelta': 10.0, }, { - "latitude": 18.335765, - "longitudeDelta": 10.0, - "name": "U.S. Virgin Islands", - "longitude": -64.896335, - "latitudeDelta": 10.0 + 'latitude': 18.335765, + 'longitudeDelta': 10.0, + 'name': 'U.S. Virgin Islands', + 'longitude': -64.896335, + 'latitudeDelta': 10.0, }, { - "latitude": 1.373333, - "longitudeDelta": 10.0, - "name": "Uganda", - "longitude": 32.290275, - "latitudeDelta": 10.0 + 'latitude': 1.373333, + 'longitudeDelta': 10.0, + 'name': 'Uganda', + 'longitude': 32.290275, + 'latitudeDelta': 10.0, }, { - "latitude": 48.379433, - "longitudeDelta": 10.0, - "name": "Ukraine", - "longitude": 31.16558, - "latitudeDelta": 10.0 + 'latitude': 48.379433, + 'longitudeDelta': 10.0, + 'name': 'Ukraine', + 'longitude': 31.16558, + 'latitudeDelta': 10.0, }, { - "latitude": 23.424076, - "longitudeDelta": 10.0, - "name": "United Arab Emirates", - "longitude": 53.847818, - "latitudeDelta": 10.0 + 'latitude': 23.424076, + 'longitudeDelta': 10.0, + 'name': 'United Arab Emirates', + 'longitude': 53.847818, + 'latitudeDelta': 10.0, }, { - "latitude": 55.378051, - "longitudeDelta": 10.0, - "name": "United Kingdom", - "longitude": -3.435973, - "latitudeDelta": 10.0 + 'latitude': 55.378051, + 'longitudeDelta': 10.0, + 'name': 'United Kingdom', + 'longitude': -3.435973, + 'latitudeDelta': 10.0, }, { - "latitude": 37.09024, - "longitudeDelta": 10.0, - "name": "United States", - "longitude": -95.712891, - "latitudeDelta": 10.0 + 'latitude': 37.09024, + 'longitudeDelta': 10.0, + 'name': 'United States', + 'longitude': -95.712891, + 'latitudeDelta': 10.0, }, { - "latitude": -32.522779, - "longitudeDelta": 10.0, - "name": "Uruguay", - "longitude": -55.765835, - "latitudeDelta": 10.0 + 'latitude': -32.522779, + 'longitudeDelta': 10.0, + 'name': 'Uruguay', + 'longitude': -55.765835, + 'latitudeDelta': 10.0, }, { - "latitude": 41.377491, - "longitudeDelta": 10.0, - "name": "Uzbekistan", - "longitude": 64.585262, - "latitudeDelta": 10.0 + 'latitude': 41.377491, + 'longitudeDelta': 10.0, + 'name': 'Uzbekistan', + 'longitude': 64.585262, + 'latitudeDelta': 10.0, }, { - "latitude": -15.376706, - "longitudeDelta": 10.0, - "name": "Vanuatu", - "longitude": 166.959158, - "latitudeDelta": 10.0 + 'latitude': -15.376706, + 'longitudeDelta': 10.0, + 'name': 'Vanuatu', + 'longitude': 166.959158, + 'latitudeDelta': 10.0, }, { - "latitude": 41.902916, - "longitudeDelta": 10.0, - "name": "Vatican City", - "longitude": 12.453389, - "latitudeDelta": 10.0 + 'latitude': 41.902916, + 'longitudeDelta': 10.0, + 'name': 'Vatican City', + 'longitude': 12.453389, + 'latitudeDelta': 10.0, }, { - "latitude": 6.42375, - "longitudeDelta": 10.0, - "name": "Venezuela", - "longitude": -66.58973, - "latitudeDelta": 10.0 + 'latitude': 6.42375, + 'longitudeDelta': 10.0, + 'name': 'Venezuela', + 'longitude': -66.58973, + 'latitudeDelta': 10.0, }, { - "latitude": 14.058324, - "longitudeDelta": 10.0, - "name": "Vietnam", - "longitude": 108.277199, - "latitudeDelta": 10.0 + 'latitude': 14.058324, + 'longitudeDelta': 10.0, + 'name': 'Vietnam', + 'longitude': 108.277199, + 'latitudeDelta': 10.0, }, { - "latitude": -13.768752, - "longitudeDelta": 10.0, - "name": "Wallis and Futuna", - "longitude": -177.156097, - "latitudeDelta": 10.0 + 'latitude': -13.768752, + 'longitudeDelta': 10.0, + 'name': 'Wallis and Futuna', + 'longitude': -177.156097, + 'latitudeDelta': 10.0, }, { - "latitude": 24.215527, - "longitudeDelta": 10.0, - "name": "Western Sahara", - "longitude": -12.885834, - "latitudeDelta": 10.0 + 'latitude': 24.215527, + 'longitudeDelta': 10.0, + 'name': 'Western Sahara', + 'longitude': -12.885834, + 'latitudeDelta': 10.0, }, { - "latitude": 15.552727, - "longitudeDelta": 10.0, - "name": "Yemen", - "longitude": 48.516388, - "latitudeDelta": 10.0 + 'latitude': 15.552727, + 'longitudeDelta': 10.0, + 'name': 'Yemen', + 'longitude': 48.516388, + 'latitudeDelta': 10.0, }, { - "latitude": -13.133897, - "longitudeDelta": 10.0, - "name": "Zambia", - "longitude": 27.849332, - "latitudeDelta": 10.0 + 'latitude': -13.133897, + 'longitudeDelta': 10.0, + 'name': 'Zambia', + 'longitude': 27.849332, + 'latitudeDelta': 10.0, }, { - "latitude": -19.015438, - "longitudeDelta": 10.0, - "name": "Zimbabwe", - "longitude": 29.154857, - "latitudeDelta": 10.0 - } + 'latitude': -19.015438, + 'longitudeDelta': 10.0, + 'name': 'Zimbabwe', + 'longitude': 29.154857, + 'latitudeDelta': 10.0, + }, ]; diff --git a/example/examples/Callouts.js b/example/examples/Callouts.js index 0034a30d3..46b219142 100644 --- a/example/examples/Callouts.js +++ b/example/examples/Callouts.js @@ -1,6 +1,6 @@ -var React = require('react'); -var ReactNative = require('react-native'); -var { +let React = require('react'); +const ReactNative = require('react-native'); +let { StyleSheet, PropTypes, View, @@ -10,11 +10,11 @@ var { Image, } = ReactNative; -var MapView = require('react-native-maps'); -var PriceMarker = require('./PriceMarker'); -var CustomCallout = require('./CustomCallout'); +let MapView = require('react-native-maps'); +const PriceMarker = require('./PriceMarker'); +let CustomCallout = require('./CustomCallout'); -var { width, height } = Dimensions.get('window'); +let { width, height } = Dimensions.get('window'); const ASPECT_RATIO = width / height; const LATITUDE = 37.78825; @@ -23,7 +23,7 @@ const LATITUDE_DELTA = 0.0922; const LONGITUDE_DELTA = LATITUDE_DELTA * ASPECT_RATIO; const SPACE = 0.01; -var Callouts = React.createClass({ +const Callouts = React.createClass({ getInitialState() { return { region: { @@ -115,7 +115,7 @@ var Callouts = React.createClass({ }, }); -var styles = StyleSheet.create({ +let styles = StyleSheet.create({ container: { position: 'absolute', top: 0, diff --git a/example/examples/CustomCallout.js b/example/examples/CustomCallout.js index 080d715b6..05edd66b1 100644 --- a/example/examples/CustomCallout.js +++ b/example/examples/CustomCallout.js @@ -1,12 +1,12 @@ -var React = require('react'); -var ReactNative = require('react-native'); -var { +let React = require('react'); +const ReactNative = require('react-native'); +let { StyleSheet, View, Text, } = ReactNative; -var CustomCallout = React.createClass({ +const CustomCallout = React.createClass({ render() { return ( @@ -22,7 +22,7 @@ var CustomCallout = React.createClass({ }, }); -var styles = StyleSheet.create({ +let styles = StyleSheet.create({ container: { flexDirection: 'column', alignSelf: 'flex-start', @@ -40,8 +40,8 @@ var styles = StyleSheet.create({ }, dollar: { - //color: '#FFFFFF', - //fontSize: 10, + // color: '#FFFFFF', + // fontSize: 10, }, amount: { flex: 1, diff --git a/example/examples/DefaultMarkers.js b/example/examples/DefaultMarkers.js index b4c978d5a..da64fb5b0 100644 --- a/example/examples/DefaultMarkers.js +++ b/example/examples/DefaultMarkers.js @@ -1,6 +1,6 @@ -var React = require('react'); -var ReactNative = require('react-native'); -var { +let React = require('react'); +const ReactNative = require('react-native'); +let { StyleSheet, PropTypes, View, @@ -9,9 +9,9 @@ var { TouchableOpacity, } = ReactNative; -var MapView = require('react-native-maps'); +let MapView = require('react-native-maps'); -var { width, height } = Dimensions.get('window'); +let { width, height } = Dimensions.get('window'); const ASPECT_RATIO = width / height; const LATITUDE = 37.78825; @@ -21,10 +21,10 @@ const LONGITUDE_DELTA = LATITUDE_DELTA * ASPECT_RATIO; let id = 0; function randomColor() { - return '#'+Math.floor(Math.random()*16777215).toString(16); + return '#' + Math.floor(Math.random() * 16777215).toString(16); } -var DefaultMarkers = React.createClass({ +const DefaultMarkers = React.createClass({ getInitialState() { return { region: { @@ -76,7 +76,7 @@ var DefaultMarkers = React.createClass({ }, }); -var styles = StyleSheet.create({ +let styles = StyleSheet.create({ container: { position: 'absolute', top: 0, diff --git a/example/examples/DisplayLatLng.js b/example/examples/DisplayLatLng.js index 8d8d70d8e..c7960e12d 100644 --- a/example/examples/DisplayLatLng.js +++ b/example/examples/DisplayLatLng.js @@ -1,6 +1,6 @@ -var React = require('react'); -var ReactNative = require('react-native'); -var { +let React = require('react'); +const ReactNative = require('react-native'); +let { StyleSheet, PropTypes, View, @@ -9,9 +9,9 @@ var { TouchableOpacity, } = ReactNative; -var MapView = require('react-native-maps'); +let MapView = require('react-native-maps'); -var { width, height } = Dimensions.get('window'); +let { width, height } = Dimensions.get('window'); const ASPECT_RATIO = width / height; const LATITUDE = 37.78825; @@ -19,7 +19,7 @@ const LONGITUDE = -122.4324; const LATITUDE_DELTA = 0.0922; const LONGITUDE_DELTA = LATITUDE_DELTA * ASPECT_RATIO; -var DisplayLatLng = React.createClass({ +const DisplayLatLng = React.createClass({ getInitialState() { return { region: { @@ -44,7 +44,7 @@ var DisplayLatLng = React.createClass({ }, randomRegion() { - var { region } = this.state; + const { region } = this.state; return { ...this.state.region, latitude: region.latitude + (Math.random() - 0.5) * region.latitudeDelta / 2, @@ -64,7 +64,7 @@ var DisplayLatLng = React.createClass({ > - + {`${this.state.region.latitude.toPrecision(7)}, ${this.state.region.longitude.toPrecision(7)}`} @@ -81,7 +81,7 @@ var DisplayLatLng = React.createClass({ }, }); -var styles = StyleSheet.create({ +let styles = StyleSheet.create({ container: { position: 'absolute', top: 0, diff --git a/example/examples/DraggableMarkers.js b/example/examples/DraggableMarkers.js index ad888a837..88db4c3b8 100644 --- a/example/examples/DraggableMarkers.js +++ b/example/examples/DraggableMarkers.js @@ -1,6 +1,6 @@ -var React = require('react'); -var ReactNative = require('react-native'); -var { +let React = require('react'); +const ReactNative = require('react-native'); +let { StyleSheet, PropTypes, View, @@ -10,10 +10,10 @@ var { Image, } = ReactNative; -var MapView = require('react-native-maps'); -var PriceMarker = require('./PriceMarker'); +let MapView = require('react-native-maps'); +let PriceMarker = require('./PriceMarker'); -var { width, height } = Dimensions.get('window'); +let { width, height } = Dimensions.get('window'); const ASPECT_RATIO = width / height; const LATITUDE = 37.78825; @@ -22,7 +22,7 @@ const LATITUDE_DELTA = 0.0922; const LONGITUDE_DELTA = LATITUDE_DELTA * ASPECT_RATIO; const SPACE = 0.01; -var MarkerTypes = React.createClass({ +const MarkerTypes = React.createClass({ getInitialState() { return { a: { @@ -33,7 +33,7 @@ var MarkerTypes = React.createClass({ latitude: LATITUDE - SPACE, longitude: LONGITUDE - SPACE, }, - } + }; }, render() { return ( @@ -74,7 +74,7 @@ var MarkerTypes = React.createClass({ }, }); -var styles = StyleSheet.create({ +let styles = StyleSheet.create({ container: { position: 'absolute', top: 0, diff --git a/example/examples/EventListener.js b/example/examples/EventListener.js index 1515ee80f..9ca37bcf0 100644 --- a/example/examples/EventListener.js +++ b/example/examples/EventListener.js @@ -1,6 +1,6 @@ -var React = require('react'); -var ReactNative = require('react-native'); -var { +let React = require('react'); +const ReactNative = require('react-native'); +let { StyleSheet, PropTypes, View, @@ -10,24 +10,24 @@ var { ScrollView, } = ReactNative; -var MapView = require('react-native-maps'); -var PriceMarker = require('./PriceMarker'); +let MapView = require('react-native-maps'); +let PriceMarker = require('./PriceMarker'); -var { width, height } = Dimensions.get('window'); +let { width, height } = Dimensions.get('window'); const ASPECT_RATIO = width / height; const LATITUDE = 37.78825; const LONGITUDE = -122.4324; const LATITUDE_DELTA = 0.0922; const LONGITUDE_DELTA = LATITUDE_DELTA * ASPECT_RATIO; -var id = 0; +let id = 0; -var Event = React.createClass({ +let Event = React.createClass({ shouldComponentUpdate(nextProps) { return this.props.event.id !== nextProps.event.id; }, render() { - var { event } = this.props; + const { event } = this.props; return ( {event.name} @@ -37,7 +37,7 @@ var Event = React.createClass({ }, }); -var DisplayLatLng = React.createClass({ +const DisplayLatLng = React.createClass({ getInitialState() { return { region: { @@ -53,14 +53,14 @@ var DisplayLatLng = React.createClass({ makeEvent(e, name) { return { id: id++, - name: name, + name, data: e.nativeEvent ? e.nativeEvent : e, }; }, recordEvent(name) { return e => { - var { events } = this.state; + const { events } = this.state; this.setState({ events: [ this.makeEvent(e, name), @@ -115,7 +115,7 @@ var DisplayLatLng = React.createClass({ }, }); -var styles = StyleSheet.create({ +let styles = StyleSheet.create({ container: { position: 'absolute', top: 0, diff --git a/example/examples/FitToSuppliedMarkers.js b/example/examples/FitToSuppliedMarkers.js index bc5b86706..d72ebb907 100644 --- a/example/examples/FitToSuppliedMarkers.js +++ b/example/examples/FitToSuppliedMarkers.js @@ -1,6 +1,6 @@ -var React = require('react'); -var ReactNative = require('react-native'); -var { +let React = require('react'); +const ReactNative = require('react-native'); +let { StyleSheet, PropTypes, View, @@ -10,10 +10,10 @@ var { Image, } = ReactNative; -var MapView = require('react-native-maps'); -var PriceMarker = require('./PriceMarker'); +let MapView = require('react-native-maps'); +const PriceMarker = require('./PriceMarker'); -var { width, height } = Dimensions.get('window'); +let { width, height } = Dimensions.get('window'); const ASPECT_RATIO = width / height; const LATITUDE = 37.78825; @@ -22,11 +22,11 @@ const LATITUDE_DELTA = 0.0922; const LONGITUDE_DELTA = LATITUDE_DELTA * ASPECT_RATIO; const SPACE = 0.01; -var markerIDs = ['Marker1', 'Marker2', 'Marker3', 'Marker4', 'Marker5']; -var timeout = 4000; -var animationTimeout; +const markerIDs = ['Marker1', 'Marker2', 'Marker3', 'Marker4', 'Marker5']; +const timeout = 4000; +let animationTimeout; -var FocusOnMarkers = React.createClass({ +const FocusOnMarkers = React.createClass({ getInitialState() { return { a: { @@ -49,17 +49,17 @@ var FocusOnMarkers = React.createClass({ latitude: LATITUDE - (SPACE * 4), longitude: LONGITUDE - (SPACE * 4), }, - } + }; }, focusMap(markers, animated) { - console.log("Markers received to populate map: " + markers); + console.log('Markers received to populate map: ' + markers); this.refs.map.fitToSuppliedMarkers(markers, animated); }, focus1() { animationTimeout = setTimeout(() => { this.focusMap([ markerIDs[1], - markerIDs[4] + markerIDs[4], ], true); this.focus2(); @@ -69,17 +69,17 @@ var FocusOnMarkers = React.createClass({ animationTimeout = setTimeout(() => { this.focusMap([ markerIDs[2], - markerIDs[3] + markerIDs[3], ], false); - this.focus3() + this.focus3(); }, timeout); }, focus3() { animationTimeout = setTimeout(() => { this.focusMap([ markerIDs[1], - markerIDs[2] + markerIDs[2], ], false); this.focus4(); @@ -89,16 +89,16 @@ var FocusOnMarkers = React.createClass({ animationTimeout = setTimeout(() => { this.focusMap([ markerIDs[0], - markerIDs[3] + markerIDs[3], ], true); this.focus1(); - }, timeout) + }, timeout); }, componentDidMount() { animationTimeout = setTimeout(() => { this.focus1(); - }, timeout) + }, timeout); }, componentWillUnmount() { if (animationTimeout) { @@ -144,7 +144,7 @@ var FocusOnMarkers = React.createClass({ }, }); -var styles = StyleSheet.create({ +let styles = StyleSheet.create({ container: { position: 'absolute', top: 0, diff --git a/example/examples/LoadingMap.js b/example/examples/LoadingMap.js index 22bdc2b23..1cb4c6ef4 100644 --- a/example/examples/LoadingMap.js +++ b/example/examples/LoadingMap.js @@ -1,15 +1,15 @@ -var React = require('react'); -var ReactNative = require('react-native'); -var { +let React = require('react'); +const ReactNative = require('react-native'); +let { Text, View, Dimensions, StyleSheet, } = ReactNative; -var MapView = require('react-native-maps'); +let MapView = require('react-native-maps'); -var { width, height } = Dimensions.get('window'); +let { width, height } = Dimensions.get('window'); const ASPECT_RATIO = width / height; const LATITUDE = 37.78825; @@ -18,7 +18,7 @@ const LATITUDE_DELTA = 0.0922; const LONGITUDE_DELTA = LATITUDE_DELTA * ASPECT_RATIO; const SPACE = 0.01; -var LoadingMap = React.createClass({ +const LoadingMap = React.createClass({ getInitialState() { return { region: { @@ -37,7 +37,7 @@ var LoadingMap = React.createClass({ style={styles.map} initialRegion={this.state.region} onPress={this.onMapPress} - loadingEnabled={true} + loadingEnabled loadingIndicatorColor={"#666666"} loadingBackgroundColor={"#eeeeee"} > @@ -75,7 +75,7 @@ var LoadingMap = React.createClass({ }, }); -var styles = StyleSheet.create({ +let styles = StyleSheet.create({ container: { position: 'absolute', top: 0, diff --git a/example/examples/MarkerTypes.js b/example/examples/MarkerTypes.js index dbd6671c5..3d9f5b103 100644 --- a/example/examples/MarkerTypes.js +++ b/example/examples/MarkerTypes.js @@ -1,6 +1,6 @@ -var React = require('react'); -var ReactNative = require('react-native'); -var { +let React = require('react'); +const ReactNative = require('react-native'); +let { StyleSheet, PropTypes, View, @@ -10,10 +10,10 @@ var { Image, } = ReactNative; -var MapView = require('react-native-maps'); -var PriceMarker = require('./PriceMarker'); +let MapView = require('react-native-maps'); +const PriceMarker = require('./PriceMarker'); -var { width, height } = Dimensions.get('window'); +let { width, height } = Dimensions.get('window'); const ASPECT_RATIO = width / height; const LATITUDE = 37.78825; @@ -22,7 +22,7 @@ const LATITUDE_DELTA = 0.0922; const LONGITUDE_DELTA = LATITUDE_DELTA * ASPECT_RATIO; const SPACE = 0.01; -var MarkerTypes = React.createClass({ +const MarkerTypes = React.createClass({ render() { return ( @@ -35,7 +35,7 @@ var MarkerTypes = React.createClass({ latitudeDelta: LATITUDE_DELTA, longitudeDelta: LONGITUDE_DELTA, }} - > + > + /> ); }, }); -var styles = StyleSheet.create({ +let styles = StyleSheet.create({ container: { position: 'absolute', top: 0, @@ -83,7 +83,7 @@ var styles = StyleSheet.create({ marginLeft: 33, marginTop: 18, fontWeight: 'bold', - } + }, }); module.exports = MarkerTypes; diff --git a/example/examples/Overlays.js b/example/examples/Overlays.js index 590007250..67cc13550 100644 --- a/example/examples/Overlays.js +++ b/example/examples/Overlays.js @@ -1,6 +1,6 @@ -var React = require('react'); -var ReactNative = require('react-native'); -var { +let React = require('react'); +const ReactNative = require('react-native'); +let { StyleSheet, PropTypes, View, @@ -10,9 +10,9 @@ var { Image, } = ReactNative; -var MapView = require('react-native-maps'); +let MapView = require('react-native-maps'); -var { width, height } = Dimensions.get('window'); +let { width, height } = Dimensions.get('window'); const ASPECT_RATIO = width / height; const LATITUDE = 37.78825; @@ -21,7 +21,7 @@ const LATITUDE_DELTA = 0.0922; const LONGITUDE_DELTA = LATITUDE_DELTA * ASPECT_RATIO; const SPACE = 0.01; -var Overlays = React.createClass({ +const Overlays = React.createClass({ getInitialState() { return { region: { @@ -109,7 +109,7 @@ var Overlays = React.createClass({ }, }); -var styles = StyleSheet.create({ +let styles = StyleSheet.create({ container: { position: 'absolute', top: 0, diff --git a/example/examples/PanController.js b/example/examples/PanController.js index a5338fa74..a490110c8 100644 --- a/example/examples/PanController.js +++ b/example/examples/PanController.js @@ -1,77 +1,77 @@ -var React = require('react'); -var ReactNative = require('react-native'); -var { +let React = require('react'); +const ReactNative = require('react-native'); +const { PropTypes, } = React; -var { +let { View, Animated, PanResponder, } = ReactNative; -var ModePropType = PropTypes.oneOf(["decay", "snap", "spring-origin"]); -var OvershootPropType = PropTypes.oneOf(["spring", "clamp"]); -var AnimatedPropType = PropTypes.any; +const ModePropType = PropTypes.oneOf(['decay', 'snap', 'spring-origin']); +const OvershootPropType = PropTypes.oneOf(['spring', 'clamp']); +const AnimatedPropType = PropTypes.any; -var PanController = React.createClass({ +const PanController = React.createClass({ - propTypes: { + propTypes: { // Component Config - lockDirection: PropTypes.bool, - horizontal: PropTypes.bool, - vertical: PropTypes.bool, - overshootX: OvershootPropType, - overshootY: OvershootPropType, - xBounds: PropTypes.arrayOf(PropTypes.number), - yBounds: PropTypes.arrayOf(PropTypes.number), - xMode: ModePropType, - yMode: ModePropType, - snapSpacingX: PropTypes.number, // TODO: also allow an array of values? - snapSpacingY: PropTypes.number, + lockDirection: PropTypes.bool, + horizontal: PropTypes.bool, + vertical: PropTypes.bool, + overshootX: OvershootPropType, + overshootY: OvershootPropType, + xBounds: PropTypes.arrayOf(PropTypes.number), + yBounds: PropTypes.arrayOf(PropTypes.number), + xMode: ModePropType, + yMode: ModePropType, + snapSpacingX: PropTypes.number, // TODO: also allow an array of values? + snapSpacingY: PropTypes.number, // Animated Values - panX: AnimatedPropType, - panY: AnimatedPropType, + panX: AnimatedPropType, + panY: AnimatedPropType, // Animation Config - overshootSpringConfig: PropTypes.any, - momentumDecayConfig: PropTypes.any, - springOriginConfig: PropTypes.any, - directionLockDistance: PropTypes.number, - overshootReductionFactor: PropTypes.number, + overshootSpringConfig: PropTypes.any, + momentumDecayConfig: PropTypes.any, + springOriginConfig: PropTypes.any, + directionLockDistance: PropTypes.number, + overshootReductionFactor: PropTypes.number, // Events - onOvershoot: PropTypes.func, - onDirectionChange: PropTypes.func, - onReleaseX: PropTypes.func, - onReleaseY: PropTypes.func, - onRelease: PropTypes.func, + onOvershoot: PropTypes.func, + onDirectionChange: PropTypes.func, + onReleaseX: PropTypes.func, + onReleaseY: PropTypes.func, + onRelease: PropTypes.func, //...PanResponderPropTypes, - }, - - getDefaultProps() { - return { - horizontal: false, - vertical: false, - lockDirection: true, - overshootX: "spring", - overshootY: "spring", - panX: new Animated.Value(0), - panY: new Animated.Value(0), - xBounds: [-Infinity, Infinity], - yBounds: [-Infinity, Infinity], - yMode: "decay", - xMode: "decay", - overshootSpringConfig: { friction: 7, tension: 40 }, - momentumDecayConfig: { deceleration: 0.993 }, - springOriginConfig: { friction: 7, tension: 40 }, - overshootReductionFactor: 3, - directionLockDistance: 10, - onStartShouldSetPanResponder: () => true, - onMoveShouldSetPanResponder: () => true, - }; - }, + }, + + getDefaultProps() { + return { + horizontal: false, + vertical: false, + lockDirection: true, + overshootX: 'spring', + overshootY: 'spring', + panX: new Animated.Value(0), + panY: new Animated.Value(0), + xBounds: [-Infinity, Infinity], + yBounds: [-Infinity, Infinity], + yMode: 'decay', + xMode: 'decay', + overshootSpringConfig: { friction: 7, tension: 40 }, + momentumDecayConfig: { deceleration: 0.993 }, + springOriginConfig: { friction: 7, tension: 40 }, + overshootReductionFactor: 3, + directionLockDistance: 10, + onStartShouldSetPanResponder: () => true, + onMoveShouldSetPanResponder: () => true, + }; + }, // getInitialState() { // //TODO: @@ -86,28 +86,28 @@ var PanController = React.createClass({ // }; // }, - _responder: null, - _listener: null, - _direction: null, - - componentWillMount() { - this._responder = PanResponder.create({ - onStartShouldSetPanResponder: this.props.onStartShouldSetPanResponder, - onMoveShouldSetPanResponder: this.props.onMoveShouldSetPanResponder, - onPanResponderGrant: (...args) => { - if (this.props.onPanResponderGrant) { - this.props.onPanResponderGrant(...args); - } - var { panX, panY, horizontal, vertical, xMode, yMode } = this.props; + _responder: null, + _listener: null, + _direction: null, + + componentWillMount() { + this._responder = PanResponder.create({ + onStartShouldSetPanResponder: this.props.onStartShouldSetPanResponder, + onMoveShouldSetPanResponder: this.props.onMoveShouldSetPanResponder, + onPanResponderGrant: (...args) => { + if (this.props.onPanResponderGrant) { + this.props.onPanResponderGrant(...args); + } + let { panX, panY, horizontal, vertical, xMode, yMode } = this.props; - this.handleResponderGrant(panX, xMode); - this.handleResponderGrant(panY, yMode); + this.handleResponderGrant(panX, xMode); + this.handleResponderGrant(panY, yMode); - this._direction = horizontal && !vertical ? 'x' : (vertical && !horizontal ? 'y' : null); - }, + this._direction = horizontal && !vertical ? 'x' : (vertical && !horizontal ? 'y' : null); + }, - onPanResponderMove: (_, { dx, dy, x0, y0 }) => { - var { + onPanResponderMove: (_, { dx, dy, x0, y0 }) => { + let { panX, panY, xBounds, @@ -120,38 +120,38 @@ var PanController = React.createClass({ directionLockDistance, } = this.props; - if (!this._direction) { - var dx2 = dx * dx; - var dy2 = dy * dy; - if (dx2 + dy2 > directionLockDistance) { - this._direction = dx2 > dy2 ? 'x' : 'y'; - if (this.props.onDirectionChange) { - this.props.onDirectionChange(this._direction, { dx, dy, x0, y0 }); - } + if (!this._direction) { + const dx2 = dx * dx; + const dy2 = dy * dy; + if (dx2 + dy2 > directionLockDistance) { + this._direction = dx2 > dy2 ? 'x' : 'y'; + if (this.props.onDirectionChange) { + this.props.onDirectionChange(this._direction, { dx, dy, x0, y0 }); } } + } - var dir = this._direction; + const dir = this._direction; - if (this.props.onPanResponderMove) { - this.props.onPanResponderMove(_, { dx, dy, x0, y0 }); - } + if (this.props.onPanResponderMove) { + this.props.onPanResponderMove(_, { dx, dy, x0, y0 }); + } - if (horizontal && (!lockDirection || dir === 'x')) { - var [xMin, xMax] = xBounds; + if (horizontal && (!lockDirection || dir === 'x')) { + let [xMin, xMax] = xBounds; - this.handleResponderMove(panX, dx, xMin, xMax, overshootX); - } + this.handleResponderMove(panX, dx, xMin, xMax, overshootX); + } - if (vertical && (!lockDirection || dir === 'y')) { - var [yMin, yMax] = yBounds; + if (vertical && (!lockDirection || dir === 'y')) { + let [yMin, yMax] = yBounds; - this.handleResponderMove(panY, dy, yMin, yMax, overshootY); - } - }, + this.handleResponderMove(panY, dy, yMin, yMax, overshootY); + } + }, - onPanResponderRelease: (_, { vx, vy, dx, dy }) => { - var { + onPanResponderRelease: (_, { vx, vy, dx, dy }) => { + let { panX, panY, xBounds, @@ -167,265 +167,264 @@ var PanController = React.createClass({ snapSpacingY, } = this.props; - var cancel = false; + let cancel = false; - var dir = this._direction; + const dir = this._direction; - if (this.props.onRelease) { - cancel = false === this.props.onRelease({ vx, vy, dx, dy }); - } + if (this.props.onRelease) { + cancel = false === this.props.onRelease({ vx, vy, dx, dy }); + } - if (!cancel && horizontal && (!lockDirection || dir === 'x')) { - var [xMin, xMax] = xBounds; - if (this.props.onReleaseX) { - cancel = false === this.props.onReleaseX({ vx, vy, dx, dy }); - } - !cancel && this.handleResponderRelease(panX, xMin, xMax, vx, overshootX, xMode, snapSpacingX); + if (!cancel && horizontal && (!lockDirection || dir === 'x')) { + let [xMin, xMax] = xBounds; + if (this.props.onReleaseX) { + cancel = false === this.props.onReleaseX({ vx, vy, dx, dy }); } + !cancel && this.handleResponderRelease(panX, xMin, xMax, vx, overshootX, xMode, snapSpacingX); + } - if (!cancel && vertical && (!lockDirection || dir === 'y')) { - var [yMin, yMax] = yBounds; - if (this.props.onReleaseY) { - cancel = false === this.props.onReleaseY({ vx, vy, dx, dy }); - } - !cancel && this.handleResponderRelease(panY, yMin, yMax, vy, overshootY, yMode, snapSpacingY); + if (!cancel && vertical && (!lockDirection || dir === 'y')) { + let [yMin, yMax] = yBounds; + if (this.props.onReleaseY) { + cancel = false === this.props.onReleaseY({ vx, vy, dx, dy }); } - - this._direction = horizontal && !vertical ? 'x' : (vertical && !horizontal ? 'y' : null); + !cancel && this.handleResponderRelease(panY, yMin, yMax, vy, overshootY, yMode, snapSpacingY); } - }); - }, - handleResponderMove(anim, delta, min, max, overshoot) { - var val = anim._offset + delta; + this._direction = horizontal && !vertical ? 'x' : (vertical && !horizontal ? 'y' : null); + }, + }); + }, + + handleResponderMove(anim, delta, min, max, overshoot) { + let val = anim._offset + delta; + + if (val > max) { + switch (overshoot) { + case 'spring': + val = max + (val - max) / this.props.overshootReductionFactor; + break; + case 'clamp': + val = max; + break; + } + } + if (val < min) { + switch (overshoot) { + case 'spring': + val = min - (min - val) / this.props.overshootReductionFactor; + break; + case 'clamp': + val = min; + break; + } + } + val = val - anim._offset; + anim.setValue(val); + }, - if (val > max) { - switch (overshoot) { - case "spring": - val = max + (val - max) / this.props.overshootReductionFactor; - break; - case "clamp": - val = max; - break; - } + handleResponderRelease(anim, min, max, velocity, overshoot, mode, snapSpacing) { + anim.flattenOffset(); + + + if (anim._value < min) { + if (this.props.onOvershoot) { + this.props.onOvershoot(); // TODO: what args should we pass to this } - if (val < min) { - switch (overshoot) { - case "spring": - val = min - (min - val) / this.props.overshootReductionFactor; - break; - case "clamp": - val = min; - break; - } + switch (overshoot) { + case 'spring': + Animated.spring(anim, { + ...this.props.overshootSpringConfig, + toValue: min, + velocity, + }).start(); + break; + case 'clamp': + anim.setValue(min); + break; } - val = val - anim._offset; - anim.setValue(val); - }, + } else if (anim._value > max) { + if (this.props.onOvershoot) { + this.props.onOvershoot(); // TODO: what args should we pass to this + } + switch (overshoot) { + case 'spring': + Animated.spring(anim, { + ...this.props.overshootSpringConfig, + toValue: max, + velocity, + }).start(); + break; + case 'clamp': + anim.setValue(min); + break; + } + } else { + switch (mode) { + case 'snap': + this.handleSnappedScroll(anim, min, max, velocity, snapSpacing, overshoot); + break; + + case 'decay': + this.handleMomentumScroll(anim, min, max, velocity, overshoot); + break; + + case 'spring-origin': + Animated.spring(anim, { + ...this.props.springOriginConfig, + toValue: 0, + velocity, + }).start(); + break; + } + } + }, - handleResponderRelease(anim, min, max, velocity, overshoot, mode, snapSpacing) { - anim.flattenOffset(); + handleResponderGrant(anim, mode) { + switch (mode) { + case 'spring-origin': + anim.setValue(0); + break; + case 'snap': + case 'decay': + anim.setOffset(anim._value + anim._offset); + anim.setValue(0); + break; + } + }, + handleMomentumScroll(anim, min, max, velocity, overshoot) { + Animated.decay(anim, { + ...this.props.momentumDecayConfig, + velocity, + }).start(() => { + anim.removeListener(this._listener); + }); - if (anim._value < min) { + this._listener = anim.addListener(({ value }) => { + if (value < min) { + anim.removeListener(this._listener); if (this.props.onOvershoot) { - this.props.onOvershoot(); //TODO: what args should we pass to this + this.props.onOvershoot(); // TODO: what args should we pass to this } switch (overshoot) { - case "spring": + case 'spring': Animated.spring(anim, { - ...this.props.overshootSpringConfig, + ...this.props.overshootSpringConfig, toValue: min, - velocity, - }).start(); - break; - case "clamp": - anim.setValue(min); - break; + velocity, + }).start(); + break; + case 'clamp': + anim.setValue(min); + break; + } + } else if (value > max) { + anim.removeListener(this._listener); + if (this.props.onOvershoot) { + this.props.onOvershoot(); // TODO: what args should we pass to this + } + switch (overshoot) { + case 'spring': + Animated.spring(anim, { + ...this.props.overshootSpringConfig, + toValue: max, + velocity, + }).start(); + break; + case 'clamp': + anim.setValue(min); + break; + } } - } else if (anim._value > max) { - if (this.props.onOvershoot) { - this.props.onOvershoot(); //TODO: what args should we pass to this - } - switch (overshoot) { - case "spring": - Animated.spring(anim, { - ...this.props.overshootSpringConfig, - toValue: max, - velocity, - }).start(); - break; -case "clamp": - anim.setValue(min); - break; -} -} else { - - switch (mode) { - case "snap": - this.handleSnappedScroll(anim, min, max, velocity, snapSpacing, overshoot); - break; - - case "decay": - this.handleMomentumScroll(anim, min, max, velocity, overshoot); - break; - - case "spring-origin": - Animated.spring(anim, { - ...this.props.springOriginConfig, - toValue: 0, - velocity, - }).start(); - break; -} -} -}, - -handleResponderGrant(anim, mode) { - switch (mode) { - case "spring-origin": - anim.setValue(0); - break; - case "snap": - case "decay": - anim.setOffset(anim._value + anim._offset); - anim.setValue(0); - break; - } -}, - -handleMomentumScroll(anim, min, max, velocity, overshoot) { - Animated.decay(anim, { - ...this.props.momentumDecayConfig, - velocity, -}).start(() => { - anim.removeListener(this._listener); -}); - -this._listener = anim.addListener(({ value }) => { - if (value < min) { - anim.removeListener(this._listener); - if (this.props.onOvershoot) { - this.props.onOvershoot(); //TODO: what args should we pass to this - } - switch (overshoot) { - case "spring": + }); + }, + + handleSnappedScroll(anim, min, max, velocity, spacing) { + let endX = this.momentumCenter(anim._value, velocity, spacing); + endX = Math.max(endX, min); + endX = Math.min(endX, max); + const bounds = [endX - spacing / 2, endX + spacing / 2]; + const endV = this.velocityAtBounds(anim._value, velocity, bounds); + + this._listener = anim.addListener(({ value }) => { + if (value > bounds[0] && value < bounds[1]) { Animated.spring(anim, { - ...this.props.overshootSpringConfig, - toValue: min, - velocity, - }).start(); - break; - case "clamp": - anim.setValue(min); - break; - } -} else if (value > max) { - anim.removeListener(this._listener); - if (this.props.onOvershoot) { - this.props.onOvershoot(); //TODO: what args should we pass to this - } - switch (overshoot) { - case "spring": - Animated.spring(anim, { - ...this.props.overshootSpringConfig, - toValue: max, - velocity, - }).start(); - break; -case "clamp": - anim.setValue(min); - break; -} -} -}); -}, - -handleSnappedScroll(anim, min, max, velocity, spacing) { - var endX = this.momentumCenter(anim._value, velocity, spacing); - endX = Math.max(endX, min); - endX = Math.min(endX, max); - var bounds = [endX-spacing/2, endX+spacing/2]; - var endV = this.velocityAtBounds(anim._value, velocity, bounds); - - this._listener = anim.addListener(( { value } ) => { - if (value > bounds[0] && value < bounds[1]) { - Animated.spring(anim, { - toValue: endX, - velocity: endV, - }).start(); - } - }); + toValue: endX, + velocity: endV, + }).start(); + } + }); - Animated.decay(anim, { + Animated.decay(anim, { ...this.props.momentumDecayConfig, - velocity, -}).start(()=> { - anim.removeListener(this._listener); -}); -}, - -closestCenter(x, spacing) { - var plus = (x % spacing) < spacing / 2 ? 0 : spacing; - return Math.round(x / spacing) * spacing + plus; -}, - -momentumCenter(x0, vx, spacing) { - var t = 0; - var deceleration = this.props.momentumDecayConfig.deceleration || 0.997; - var x1 = x0; - var x = x1; - - while (true) { - t += 16; - x = x0 + (vx / (1 - deceleration)) * + velocity, + }).start(() => { + anim.removeListener(this._listener); + }); + }, + + closestCenter(x, spacing) { + const plus = (x % spacing) < spacing / 2 ? 0 : spacing; + return Math.round(x / spacing) * spacing + plus; + }, + + momentumCenter(x0, vx, spacing) { + let t = 0; + const deceleration = this.props.momentumDecayConfig.deceleration || 0.997; + let x1 = x0; + let x = x1; + + while (true) { + t += 16; + x = x0 + (vx / (1 - deceleration)) * (1 - Math.exp(-(1 - deceleration) * t)); - if (Math.abs(x-x1) < 0.1) { + if (Math.abs(x - x1) < 0.1) { + x1 = x; + break; + } x1 = x; - break; } - x1 = x; - } - return this.closestCenter(x1, spacing); -}, - -velocityAtBounds(x0, vx, bounds) { - var t = 0; - var deceleration = this.props.momentumDecayConfig.deceleration || 0.997; - var x1 = x0; - var x = x1; - var vf; - while (true) { - t += 16; - x = x0 + (vx / (1 - deceleration)) * + return this.closestCenter(x1, spacing); + }, + + velocityAtBounds(x0, vx, bounds) { + let t = 0; + const deceleration = this.props.momentumDecayConfig.deceleration || 0.997; + let x1 = x0; + let x = x1; + let vf; + while (true) { + t += 16; + x = x0 + (vx / (1 - deceleration)) * (1 - Math.exp(-(1 - deceleration) * t)); - vf = (x-x1) / 16; - if (x > bounds[0] && x < bounds[1]) { - break; - } - if (Math.abs(vf) < 0.1) { - break; + vf = (x - x1) / 16; + if (x > bounds[0] && x < bounds[1]) { + break; + } + if (Math.abs(vf) < 0.1) { + break; + } + x1 = x; } - x1 = x; - } - return vf; -}, + return vf; + }, -//componentDidMount() { +// componentDidMount() { // //TODO: we may need to measure the children width/height here? -//}, +// }, // -//componentWillUnmount() { +// componentWillUnmount() { // -//}, +// }, // -//componentDidUnmount() { +// componentDidUnmount() { // -//}, +// }, -render: function () { - return -}, + render() { + return ; + }, }); module.exports = PanController; diff --git a/example/examples/PolygonCreator.js b/example/examples/PolygonCreator.js index bd5585f35..3b0654efc 100644 --- a/example/examples/PolygonCreator.js +++ b/example/examples/PolygonCreator.js @@ -1,6 +1,6 @@ -var React = require('react'); -var ReactNative = require('react-native'); -var { +let React = require('react'); +const ReactNative = require('react-native'); +let { StyleSheet, PropTypes, View, @@ -9,19 +9,19 @@ var { TouchableOpacity, } = ReactNative; -var MapView = require('react-native-maps'); -var PriceMarker = require('./PriceMarker'); +let MapView = require('react-native-maps'); +const PriceMarker = require('./PriceMarker'); -var { width, height } = Dimensions.get('window'); +let { width, height } = Dimensions.get('window'); const ASPECT_RATIO = width / height; const LATITUDE = 37.78825; const LONGITUDE = -122.4324; const LATITUDE_DELTA = 0.0922; const LONGITUDE_DELTA = LATITUDE_DELTA * ASPECT_RATIO; -var id = 0; +let id = 0; -var DisplayLatLng = React.createClass({ +const DisplayLatLng = React.createClass({ getInitialState() { return { region: { @@ -36,7 +36,7 @@ var DisplayLatLng = React.createClass({ }, finish() { - var { polygons, editing } = this.state; + let { polygons, editing } = this.state; this.setState({ polygons: [...polygons, editing], editing: null, @@ -44,7 +44,7 @@ var DisplayLatLng = React.createClass({ }, onPress(e) { - var { editing } = this.state; + const { editing } = this.state; if (!editing) { this.setState({ editing: { @@ -66,13 +66,13 @@ var DisplayLatLng = React.createClass({ }, render() { - var mapOptions = { + const mapOptions = { scrollEnabled: true, }; if (this.state.editing) { mapOptions.scrollEnabled = false; - mapOptions.onPanDrag = this.onPress; + mapOptions.onPanDrag = this.onPress; } return ( @@ -113,7 +113,7 @@ var DisplayLatLng = React.createClass({ }, }); -var styles = StyleSheet.create({ +let styles = StyleSheet.create({ container: { position: 'absolute', top: 0, diff --git a/example/examples/PolylineCreator.js b/example/examples/PolylineCreator.js index 02642f144..c48bdf76c 100644 --- a/example/examples/PolylineCreator.js +++ b/example/examples/PolylineCreator.js @@ -1,6 +1,6 @@ -var React = require('react'); -var ReactNative = require('react-native'); -var { +let React = require('react'); +const ReactNative = require('react-native'); +let { StyleSheet, PropTypes, View, @@ -9,19 +9,19 @@ var { TouchableOpacity, } = ReactNative; -var MapView = require('react-native-maps'); -var PriceMarker = require('./PriceMarker'); +let MapView = require('react-native-maps'); +const PriceMarker = require('./PriceMarker'); -var { width, height } = Dimensions.get('window'); +let { width, height } = Dimensions.get('window'); const ASPECT_RATIO = width / height; const LATITUDE = 37.78825; const LONGITUDE = -122.4324; const LATITUDE_DELTA = 0.0922; const LONGITUDE_DELTA = LATITUDE_DELTA * ASPECT_RATIO; -var id = 0; +let id = 0; -var PolylineCreator = React.createClass({ +const PolylineCreator = React.createClass({ getInitialState() { return { region: { @@ -36,7 +36,7 @@ var PolylineCreator = React.createClass({ }, finish() { - var { polygons, editing } = this.state; + let { polygons, editing } = this.state; this.setState({ polygons: [...polygons, editing], editing: null, @@ -44,7 +44,7 @@ var PolylineCreator = React.createClass({ }, onPanDrag(e) { - var { editing } = this.state; + const { editing } = this.state; if (!editing) { this.setState({ editing: { @@ -105,7 +105,7 @@ var PolylineCreator = React.createClass({ }, }); -var styles = StyleSheet.create({ +let styles = StyleSheet.create({ container: { position: 'absolute', top: 0, diff --git a/example/examples/PriceMarker.js b/example/examples/PriceMarker.js index df1ceda15..55c0f3ffc 100644 --- a/example/examples/PriceMarker.js +++ b/example/examples/PriceMarker.js @@ -1,12 +1,12 @@ -var React = require('react'); -var ReactNative = require('react-native'); -var { +let React = require('react'); +const ReactNative = require('react-native'); +let { StyleSheet, View, Text, } = ReactNative; -var PriceMarker = React.createClass({ +const PriceMarker = React.createClass({ getDefaultProps() { return { fontSize: 13, @@ -26,7 +26,7 @@ var PriceMarker = React.createClass({ }, }); -var styles = StyleSheet.create({ +let styles = StyleSheet.create({ container: { flexDirection: 'column', alignSelf: 'flex-start', diff --git a/example/examples/TakeSnapshot.js b/example/examples/TakeSnapshot.js index 3a749a62c..dd610ca2f 100644 --- a/example/examples/TakeSnapshot.js +++ b/example/examples/TakeSnapshot.js @@ -1,6 +1,6 @@ -var React = require('react'); -var ReactNative = require('react-native'); -var { +let React = require('react'); +const ReactNative = require('react-native'); +let { StyleSheet, PropTypes, View, @@ -10,10 +10,10 @@ var { Image, } = ReactNative; -var MapView = require('react-native-maps'); -var PriceMarker = require('./PriceMarker'); +let MapView = require('react-native-maps'); +const PriceMarker = require('./PriceMarker'); -var { width, height } = Dimensions.get('window'); +let { width, height } = Dimensions.get('window'); const ASPECT_RATIO = width / height; const LATITUDE = 37.78825; @@ -22,9 +22,9 @@ const LATITUDE_DELTA = 0.0922; const LONGITUDE_DELTA = LATITUDE_DELTA * ASPECT_RATIO; const SPACE = 0.01; -var MarkerTypes = React.createClass({ +const MarkerTypes = React.createClass({ getInitialState() { - return { mapSnapshot: null } + return { mapSnapshot: null }; }, takeSnapshot() { @@ -32,10 +32,10 @@ var MarkerTypes = React.createClass({ latitude: LATITUDE - SPACE, longitude: LONGITUDE - SPACE, latitudeDelta: 0.01, - longitudeDelta: 0.01 * ASPECT_RATIO + longitudeDelta: 0.01 * ASPECT_RATIO, }, (err, data) => { - if (err) console.log(err) - this.setState({ mapSnapshot: data }) + if (err) console.log(err); + this.setState({ mapSnapshot: data }); }); }, @@ -51,7 +51,7 @@ var MarkerTypes = React.createClass({ latitudeDelta: LATITUDE_DELTA, longitudeDelta: LONGITUDE_DELTA, }} - > + > + /> + /> @@ -80,11 +80,12 @@ var MarkerTypes = React.createClass({ {this.state.mapSnapshot ? this.setState({ mapSnapshot: null })}> + onPress={() => this.setState({ mapSnapshot: null })} + > + /> : null} @@ -92,7 +93,7 @@ var MarkerTypes = React.createClass({ }, }); -var styles = StyleSheet.create({ +let styles = StyleSheet.create({ container: { position: 'absolute', top: 0, @@ -129,7 +130,7 @@ var styles = StyleSheet.create({ overlay: { backgroundColor: 'rgba(0,0,0,0.5)', justifyContent: 'center', - } + }, }); module.exports = MarkerTypes; diff --git a/example/examples/ViewsAsMarkers.js b/example/examples/ViewsAsMarkers.js index 3dfdc7ac5..00188c809 100644 --- a/example/examples/ViewsAsMarkers.js +++ b/example/examples/ViewsAsMarkers.js @@ -1,6 +1,6 @@ -var React = require('react'); -var ReactNative = require('react-native'); -var { +let React = require('react'); +const ReactNative = require('react-native'); +let { StyleSheet, PropTypes, View, @@ -9,10 +9,10 @@ var { TouchableOpacity, } = ReactNative; -var MapView = require('react-native-maps'); -var PriceMarker = require('./PriceMarker'); +let MapView = require('react-native-maps'); +let PriceMarker = require('./PriceMarker'); -var { width, height } = Dimensions.get('window'); +let { width, height } = Dimensions.get('window'); const ASPECT_RATIO = width / height; const LATITUDE = 37.78825; @@ -20,7 +20,7 @@ const LONGITUDE = -122.4324; const LATITUDE_DELTA = 0.0922; const LONGITUDE_DELTA = LATITUDE_DELTA * ASPECT_RATIO; -var DisplayLatLng = React.createClass({ +const DisplayLatLng = React.createClass({ getInitialState() { return { region: { @@ -69,7 +69,7 @@ var DisplayLatLng = React.createClass({ }, }); -var styles = StyleSheet.create({ +let styles = StyleSheet.create({ container: { position: 'absolute', top: 0, diff --git a/example/examples/finalindexfile.js b/example/examples/finalindexfile.js index ffa045044..05f9c9010 100644 --- a/example/examples/finalindexfile.js +++ b/example/examples/finalindexfile.js @@ -4,9 +4,9 @@ */ 'use strict'; -var React = require('react'); -var ReactNative = require('react-native'); -var { +let React = require('react'); +const ReactNative = require('react-native'); +let { AppRegistry, StyleSheet, Text, @@ -15,10 +15,10 @@ var { Animated, TouchableOpacity, } = ReactNative; -var MapView = require('react-native-maps'); -var PriceMarker = require('./components/PriceMarker'); +let MapView = require('react-native-maps'); +let PriceMarker = require('./components/PriceMarker'); -var { width, height } = Dimensions.get('window'); +let { width, height } = Dimensions.get('window'); const LATITUDE = 37.78825; const LONGITUDE = -122.4324; @@ -29,7 +29,7 @@ const LNGD = LONGITUDE + 77.03659; const LATITUDE_DELTA = 0.0922; const LONGITUDE_DELTA = 0.1218; -var MapViewTest = React.createClass({ +const MapViewTest = React.createClass({ getInitialState() { const scale = new Animated.Value(1); const latitudeDelta = scale.interpolate({ @@ -46,8 +46,8 @@ var MapViewTest = React.createClass({ region: new Animated.Region({ latitude: LATITUDE, longitude: LONGITUDE, - latitudeDelta: latitudeDelta, - longitudeDelta: longitudeDelta, + latitudeDelta, + longitudeDelta, }), markers: [], coord: { @@ -58,13 +58,13 @@ var MapViewTest = React.createClass({ }, onRegionChange(region) { - //console.log("onRegionChange", region); + // console.log("onRegionChange", region); this.state.region.setValue(region); - //this.setState({ region }); + // this.setState({ region }); }, onAnimate() { - var { val } = this.state; + const { val } = this.state; Animated.sequence([ Animated.timing(val, { toValue: 0, duration: 500 }), Animated.timing(val, { toValue: 1, duration: 500 }), @@ -72,11 +72,11 @@ var MapViewTest = React.createClass({ }, onAddMarker() { - var coordinate = { + const coordinate = { latitude: LATITUDE + LATITUDE_DELTA * (Math.random() - 0.5), longitude: LONGITUDE + LONGITUDE_DELTA * (Math.random() - 0.5), }; - var markers = [...this.state.markers, coordinate]; + let markers = [...this.state.markers, coordinate]; if (markers.length > 5) { markers = markers.slice(1); } @@ -84,8 +84,8 @@ var MapViewTest = React.createClass({ }, onAnimateZoom() { - var { scale, region } = this.state; - var toValue = scale.__getValue() > 1 ? 1 : 2; + let { scale, region } = this.state; + const toValue = scale.__getValue() > 1 ? 1 : 2; Animated.parallel([ Animated.spring(region.latitude, { toValue: LATITUDE + LATITUDE_DELTA * (Math.random() - 0.5), @@ -105,7 +105,7 @@ var MapViewTest = React.createClass({ latitude: LATITUDE + LATITUDE_DELTA * (Math.random() - 0.5), longitude: LONGITUDE + LONGITUDE_DELTA * (Math.random() - 0.5), }, - }) + }); }, onAnimateMapRegion() { @@ -122,7 +122,6 @@ var MapViewTest = React.createClass({ }, render() { - return ( console.log("Map::onRegionChangeComplete", e.nativeEvent)} - onPress={(e) => console.log("Map::onPress", e.nativeEvent)} - onPanDrag={(e) => console.log("Map::onPanDrag", e.nativeEvent)} - onLongPress={(e) => console.log("Map::onLongPress", e.nativeEvent)} - onMarkerPress={(e) => console.log("Map::onMarkerPress", e.nativeEvent)} - onMarkerSelect={(e) => console.log("Map::onMarkerSelect", e.nativeEvent)} - onMarkerDeselect={(e) => console.log("Map::onMarkerDeselect", e.nativeEvent)} - onCalloutPress={(e) => console.log("Map::onCalloutPress", e.nativeEvent)} - onMapPress={(e) => console.log("Map::onMapPress", e.nativeEvent)} - > + onRegionChangeComplete={(e) => console.log('Map::onRegionChangeComplete', e.nativeEvent)} + onPress={(e) => console.log('Map::onPress', e.nativeEvent)} + onPanDrag={(e) => console.log('Map::onPanDrag', e.nativeEvent)} + onLongPress={(e) => console.log('Map::onLongPress', e.nativeEvent)} + onMarkerPress={(e) => console.log('Map::onMarkerPress', e.nativeEvent)} + onMarkerSelect={(e) => console.log('Map::onMarkerSelect', e.nativeEvent)} + onMarkerDeselect={(e) => console.log('Map::onMarkerDeselect', e.nativeEvent)} + onCalloutPress={(e) => console.log('Map::onCalloutPress', e.nativeEvent)} + onMapPress={(e) => console.log('Map::onMapPress', e.nativeEvent)} + > + /> + /> + /> console.log("Marker::onPress", e.nativeEvent)} - onCalloutPress={(e) => console.log("Marker::onCalloutPress", e.nativeEvent)} - > + onPress={(e) => console.log('Marker::onPress', e.nativeEvent)} + onCalloutPress={(e) => console.log('Marker::onCalloutPress', e.nativeEvent)} + > console.log("Callout::onPress", e.nativeEvent)} - > + onPress={(e) => console.log('Callout::onPress', e.nativeEvent)} + > Well hello there... @@ -192,14 +191,14 @@ var MapViewTest = React.createClass({ console.log("Marker::onPress", e.nativeEvent)} - onCalloutPress={(e) => console.log("Marker::onCalloutPress", e.nativeEvent)} - > + onPress={(e) => console.log('Marker::onPress', e.nativeEvent)} + onCalloutPress={(e) => console.log('Marker::onCalloutPress', e.nativeEvent)} + > console.log("Callout::onPress", e.nativeEvent)} - > + onPress={(e) => console.log('Callout::onPress', e.nativeEvent)} + > Well hello there... @@ -242,7 +241,7 @@ var MapViewTest = React.createClass({ }, }); -var styles = StyleSheet.create({ +let styles = StyleSheet.create({ map: { height: 350, margin: 10, @@ -279,13 +278,13 @@ var styles = StyleSheet.create({ backgroundColor: 'blue', }, callout: { - //flex: 0, - //flexDirection: 'column', - //position: 'absolute', - //flex: 0, - //backgroundColor: '#fff', - //width: 100, - //height: 100, + // flex: 0, + // flexDirection: 'column', + // position: 'absolute', + // flex: 0, + // backgroundColor: '#fff', + // width: 100, + // height: 100, }, }); diff --git a/example/index.android.js b/example/index.android.js index 7a347e3a6..d3cb8508d 100644 --- a/example/index.android.js +++ b/example/index.android.js @@ -1,14 +1,14 @@ -var React = require('react'); -var ReactNative = require('react-native'); -var { +let React = require('react'); +const ReactNative = require('react-native'); +const { AppRegistry, } = ReactNative; -var App = require('./App'); +let App = require('./App'); -var AirMapsExplorer = React.createClass({ +const AirMapsExplorer = React.createClass({ render() { - return + return ; }, }); diff --git a/example/index.ios.js b/example/index.ios.js index 7a347e3a6..d3cb8508d 100644 --- a/example/index.ios.js +++ b/example/index.ios.js @@ -1,14 +1,14 @@ -var React = require('react'); -var ReactNative = require('react-native'); -var { +let React = require('react'); +const ReactNative = require('react-native'); +const { AppRegistry, } = ReactNative; -var App = require('./App'); +let App = require('./App'); -var AirMapsExplorer = React.createClass({ +const AirMapsExplorer = React.createClass({ render() { - return + return ; }, }); diff --git a/index.js b/index.js index ab0e84b48..50d803692 100644 --- a/index.js +++ b/index.js @@ -1,3 +1,3 @@ -var MapView = require('./components/MapView'); +const MapView = require('./components/MapView'); module.exports = MapView; From 5d4cae378ade44894deb577af7a1e7503583a7cd Mon Sep 17 00:00:00 2001 From: Spike Brehm Date: Thu, 25 Aug 2016 11:40:11 -0700 Subject: [PATCH 0011/1148] First pass fixing linting errors in `components` --- components/MapCallout.js | 19 ++++++------------- components/MapCircle.js | 20 ++++++++------------ components/MapMarker.js | 27 ++++++++++++--------------- components/MapPolygon.js | 27 ++++++++------------------- components/MapPolyline.js | 23 +++++------------------ components/MapView.js | 30 ++++++++++++------------------ 6 files changed, 51 insertions(+), 95 deletions(-) diff --git a/components/MapCallout.js b/components/MapCallout.js index 6da673529..205c2b8a6 100644 --- a/components/MapCallout.js +++ b/components/MapCallout.js @@ -1,17 +1,12 @@ - -let React = require('react'); -const { - PropTypes, -} = React; - -const ReactNative = require('react-native'); -let { +import React, { PropTypes } from 'react'; +import { View, NativeMethodsMixin, requireNativeComponent, StyleSheet, -} = ReactNative; +} from 'react-native'; +// eslint-disable-next-line react/prefer-es6-class const MapCallout = React.createClass({ mixins: [NativeMethodsMixin], @@ -32,14 +27,12 @@ const MapCallout = React.createClass({ }, }); -let styles = StyleSheet.create({ +const styles = StyleSheet.create({ callout: { position: 'absolute', - //flex: 0, - //backgroundColor: 'transparent', }, }); -let AIRMapCallout = requireNativeComponent('AIRMapCallout', MapCallout); +const AIRMapCallout = requireNativeComponent('AIRMapCallout', MapCallout); module.exports = MapCallout; diff --git a/components/MapCircle.js b/components/MapCircle.js index c9cc8806e..8f42463f9 100644 --- a/components/MapCircle.js +++ b/components/MapCircle.js @@ -1,17 +1,11 @@ - -let React = require('react'); -const { - PropTypes, -} = React; - -const ReactNative = require('react-native'); -let { +import React, { PropTypes } from 'react'; +import { View, NativeMethodsMixin, requireNativeComponent, - StyleSheet, -} = ReactNative; +} from 'react-native'; +// eslint-disable-next-line react/prefer-es6-class const MapCircle = React.createClass({ mixins: [NativeMethodsMixin], @@ -135,7 +129,9 @@ const MapCircle = React.createClass({ }, _onPress(e) { - this.props.onPress && this.props.onPress(e); + if (this.props.onPress) { + this.props.onPress(e); + } }, render() { @@ -148,6 +144,6 @@ const MapCircle = React.createClass({ }, }); -let AIRMapCircle = requireNativeComponent('AIRMapCircle', MapCircle); +const AIRMapCircle = requireNativeComponent('AIRMapCircle', MapCircle); module.exports = MapCircle; diff --git a/components/MapMarker.js b/components/MapMarker.js index 74fceb020..c1ab7bb36 100644 --- a/components/MapMarker.js +++ b/components/MapMarker.js @@ -1,12 +1,5 @@ -'use strict'; - -let React = require('react'); -const { - PropTypes, -} = React; - -const ReactNative = require('react-native'); -let { +import React, { PropTypes } from 'react'; +import { View, NativeMethodsMixin, requireNativeComponent, @@ -14,10 +7,12 @@ let { Platform, NativeModules, Animated, -} = ReactNative; + findNodeHandle, +} from 'react-native'; const resolveAssetSource = require('react-native/Libraries/Image/resolveAssetSource'); +// eslint-disable-next-line react/prefer-es6-class const MapMarker = React.createClass({ mixins: [NativeMethodsMixin], @@ -217,7 +212,7 @@ const MapMarker = React.createClass({ }, _getHandle() { - return ReactNative.findNodeHandle(this.refs.marker); + return findNodeHandle(this.refs.marker); }, _runCommand(name, args) { @@ -240,11 +235,13 @@ const MapMarker = React.createClass({ }, _onPress(e) { - this.props.onPress && this.props.onPress(e); + if (this.props.onPress) { + this.props.onPress(e); + } }, render() { - let image = undefined; + let image; if (this.props.image) { image = resolveAssetSource(this.props.image) || {}; image = image.uri; @@ -262,14 +259,14 @@ const MapMarker = React.createClass({ }, }); -let styles = StyleSheet.create({ +const styles = StyleSheet.create({ marker: { position: 'absolute', backgroundColor: 'transparent', }, }); -let AIRMapMarker = requireNativeComponent('AIRMapMarker', MapMarker); +const AIRMapMarker = requireNativeComponent('AIRMapMarker', MapMarker); MapMarker.Animated = Animated.createAnimatedComponent(MapMarker); diff --git a/components/MapPolygon.js b/components/MapPolygon.js index 52c31b4c6..9d8af164c 100644 --- a/components/MapPolygon.js +++ b/components/MapPolygon.js @@ -1,16 +1,11 @@ -let React = require('react'); -const { - PropTypes, -} = React; - -const ReactNative = require('react-native'); -let { +import React, { PropTypes } from 'react'; +import { View, NativeMethodsMixin, requireNativeComponent, - StyleSheet, -} = ReactNative; +} from 'react-native'; +// eslint-disable-next-line react/prefer-es6-class const MapPolygon = React.createClass({ mixins: [NativeMethodsMixin], @@ -139,7 +134,9 @@ const MapPolygon = React.createClass({ }, _onPress(e) { - this.props.onPress && this.props.onPress(e); + if (this.props.onPress) { + this.props.onPress(e); + } }, render() { @@ -152,14 +149,6 @@ const MapPolygon = React.createClass({ }, }); -const styles = StyleSheet.create({ - polyline: { - position: 'absolute', - width: 0, - height: 0, - }, -}); - -let AIRMapPolygon = requireNativeComponent('AIRMapPolygon', MapPolygon); +const AIRMapPolygon = requireNativeComponent('AIRMapPolygon', MapPolygon); module.exports = MapPolygon; diff --git a/components/MapPolyline.js b/components/MapPolyline.js index 0292cc2fe..905d51b4a 100644 --- a/components/MapPolyline.js +++ b/components/MapPolyline.js @@ -1,16 +1,11 @@ -let React = require('react'); -const { - PropTypes, -} = React; - -const ReactNative = require('react-native'); -let { +import React, { PropTypes } from 'react'; +import { View, NativeMethodsMixin, requireNativeComponent, - StyleSheet, -} = ReactNative; +} from 'react-native'; +// eslint-disable-next-line react/prefer-es6-class const MapPolyline = React.createClass({ mixins: [NativeMethodsMixin], @@ -140,14 +135,6 @@ const MapPolyline = React.createClass({ }, }); -const styles = StyleSheet.create({ - polyline: { - position: 'absolute', - width: 0, - height: 0, - }, -}); - -let AIRMapPolyline = requireNativeComponent('AIRMapPolyline', MapPolyline); +const AIRMapPolyline = requireNativeComponent('AIRMapPolyline', MapPolyline); module.exports = MapPolyline; diff --git a/components/MapView.js b/components/MapView.js index 87f52d49e..7540ef50e 100644 --- a/components/MapView.js +++ b/components/MapView.js @@ -1,28 +1,22 @@ -'use strict'; - -let React = require('react'); -const { - PropTypes, -} = React; -const ReactNative = require('react-native'); -let { +import React, { PropTypes } from 'react'; +import { EdgeInsetsPropType, NativeMethodsMixin, Platform, - ReactNativeViewAttributes, View, Animated, requireNativeComponent, NativeModules, ColorPropType, -} = ReactNative; - -const MapMarker = require('./MapMarker'); -const MapPolyline = require('./MapPolyline'); -const MapPolygon = require('./MapPolygon'); -const MapCircle = require('./MapCircle'); -const MapCallout = require('./MapCallout'); - + findNodeHandle, +} from 'react-native'; +import MapMarker from './MapMarker'; +import MapPolyline from './MapPolyline'; +import MapPolygon from './MapPolygon'; +import MapCircle from './MapCircle'; +import MapCallout from './MapCallout'; + +// eslint-disable-next-line react/prefer-es6-class const MapView = React.createClass({ mixins: [NativeMethodsMixin], @@ -409,7 +403,7 @@ const MapView = React.createClass({ }, _getHandle() { - return ReactNative.findNodeHandle(this.refs.map); + return findNodeHandle(this.refs.map); }, _runCommand(name, args) { From 9ffe3a2225ccd1e22207539bd2f3afd25e6b2681 Mon Sep 17 00:00:00 2001 From: Spike Brehm Date: Thu, 25 Aug 2016 11:55:23 -0700 Subject: [PATCH 0012/1148] Fix ~1300 no-quote-props errors in CachedMap --- example/examples/CachedMap.js | 2440 ++++++++++++++++----------------- 1 file changed, 1220 insertions(+), 1220 deletions(-) diff --git a/example/examples/CachedMap.js b/example/examples/CachedMap.js index 3e2cd4396..227b2379d 100644 --- a/example/examples/CachedMap.js +++ b/example/examples/CachedMap.js @@ -114,1712 +114,1712 @@ let styles = StyleSheet.create({ const COUNTRIES = [ { - 'latitude': 33.93911, - 'longitudeDelta': 10.0, - 'name': 'Afghanistan', - 'longitude': 67.709953, - 'latitudeDelta': 10.0, + latitude: 33.93911, + longitudeDelta: 10.0, + name: 'Afghanistan', + longitude: 67.709953, + latitudeDelta: 10.0, }, { - 'latitude': 41.153332, - 'longitudeDelta': 10.0, - 'name': 'Albania', - 'longitude': 20.168331, - 'latitudeDelta': 10.0, + latitude: 41.153332, + longitudeDelta: 10.0, + name: 'Albania', + longitude: 20.168331, + latitudeDelta: 10.0, }, { - 'latitude': 28.033886, - 'longitudeDelta': 10.0, - 'name': 'Algeria', - 'longitude': 1.659626, - 'latitudeDelta': 10.0, + latitude: 28.033886, + longitudeDelta: 10.0, + name: 'Algeria', + longitude: 1.659626, + latitudeDelta: 10.0, }, { - 'latitude': -14.270972, - 'longitudeDelta': 10.0, - 'name': 'American Samoa', - 'longitude': -170.132217, - 'latitudeDelta': 10.0, + latitude: -14.270972, + longitudeDelta: 10.0, + name: 'American Samoa', + longitude: -170.132217, + latitudeDelta: 10.0, }, { - 'latitude': 42.546245, - 'longitudeDelta': 10.0, - 'name': 'Andorra', - 'longitude': 1.601554, - 'latitudeDelta': 10.0, + latitude: 42.546245, + longitudeDelta: 10.0, + name: 'Andorra', + longitude: 1.601554, + latitudeDelta: 10.0, }, { - 'latitude': -11.202692, - 'longitudeDelta': 10.0, - 'name': 'Angola', - 'longitude': 17.873887, - 'latitudeDelta': 10.0, + latitude: -11.202692, + longitudeDelta: 10.0, + name: 'Angola', + longitude: 17.873887, + latitudeDelta: 10.0, }, { - 'latitude': 18.220554, - 'longitudeDelta': 10.0, - 'name': 'Anguilla', - 'longitude': -63.068615, - 'latitudeDelta': 10.0, + latitude: 18.220554, + longitudeDelta: 10.0, + name: 'Anguilla', + longitude: -63.068615, + latitudeDelta: 10.0, }, { - 'latitude': -75.250973, - 'longitudeDelta': 10.0, - 'name': 'Antarctica', - 'longitude': -0.071389, - 'latitudeDelta': 10.0, + latitude: -75.250973, + longitudeDelta: 10.0, + name: 'Antarctica', + longitude: -0.071389, + latitudeDelta: 10.0, }, { - 'latitude': 17.060816, - 'longitudeDelta': 10.0, - 'name': 'Antigua and Barbuda', - 'longitude': -61.796428, - 'latitudeDelta': 10.0, + latitude: 17.060816, + longitudeDelta: 10.0, + name: 'Antigua and Barbuda', + longitude: -61.796428, + latitudeDelta: 10.0, }, { - 'latitude': -38.416097, - 'longitudeDelta': 10.0, - 'name': 'Argentina', - 'longitude': -63.616672, - 'latitudeDelta': 10.0, + latitude: -38.416097, + longitudeDelta: 10.0, + name: 'Argentina', + longitude: -63.616672, + latitudeDelta: 10.0, }, { - 'latitude': 40.069099, - 'longitudeDelta': 10.0, - 'name': 'Armenia', - 'longitude': 45.038189, - 'latitudeDelta': 10.0, + latitude: 40.069099, + longitudeDelta: 10.0, + name: 'Armenia', + longitude: 45.038189, + latitudeDelta: 10.0, }, { - 'latitude': 12.52111, - 'longitudeDelta': 10.0, - 'name': 'Aruba', - 'longitude': -69.968338, - 'latitudeDelta': 10.0, + latitude: 12.52111, + longitudeDelta: 10.0, + name: 'Aruba', + longitude: -69.968338, + latitudeDelta: 10.0, }, { - 'latitude': -25.274398, - 'longitudeDelta': 10.0, - 'name': 'Australia', - 'longitude': 133.775136, - 'latitudeDelta': 10.0, + latitude: -25.274398, + longitudeDelta: 10.0, + name: 'Australia', + longitude: 133.775136, + latitudeDelta: 10.0, }, { - 'latitude': 47.516231, - 'longitudeDelta': 10.0, - 'name': 'Austria', - 'longitude': 14.550072, - 'latitudeDelta': 10.0, + latitude: 47.516231, + longitudeDelta: 10.0, + name: 'Austria', + longitude: 14.550072, + latitudeDelta: 10.0, }, { - 'latitude': 40.143105, - 'longitudeDelta': 10.0, - 'name': 'Azerbaijan', - 'longitude': 47.576927, - 'latitudeDelta': 10.0, + latitude: 40.143105, + longitudeDelta: 10.0, + name: 'Azerbaijan', + longitude: 47.576927, + latitudeDelta: 10.0, }, { - 'latitude': 25.03428, - 'longitudeDelta': 10.0, - 'name': 'Bahamas', - 'longitude': -77.39628, - 'latitudeDelta': 10.0, + latitude: 25.03428, + longitudeDelta: 10.0, + name: 'Bahamas', + longitude: -77.39628, + latitudeDelta: 10.0, }, { - 'latitude': 25.930414, - 'longitudeDelta': 10.0, - 'name': 'Bahrain', - 'longitude': 50.637772, - 'latitudeDelta': 10.0, + latitude: 25.930414, + longitudeDelta: 10.0, + name: 'Bahrain', + longitude: 50.637772, + latitudeDelta: 10.0, }, { - 'latitude': 23.684994, - 'longitudeDelta': 10.0, - 'name': 'Bangladesh', - 'longitude': 90.356331, - 'latitudeDelta': 10.0, + latitude: 23.684994, + longitudeDelta: 10.0, + name: 'Bangladesh', + longitude: 90.356331, + latitudeDelta: 10.0, }, { - 'latitude': 13.193887, - 'longitudeDelta': 10.0, - 'name': 'Barbados', - 'longitude': -59.543198, - 'latitudeDelta': 10.0, + latitude: 13.193887, + longitudeDelta: 10.0, + name: 'Barbados', + longitude: -59.543198, + latitudeDelta: 10.0, }, { - 'latitude': 53.709807, - 'longitudeDelta': 10.0, - 'name': 'Belarus', - 'longitude': 27.953389, - 'latitudeDelta': 10.0, + latitude: 53.709807, + longitudeDelta: 10.0, + name: 'Belarus', + longitude: 27.953389, + latitudeDelta: 10.0, }, { - 'latitude': 50.503887, - 'longitudeDelta': 10.0, - 'name': 'Belgium', - 'longitude': 4.469936, - 'latitudeDelta': 10.0, + latitude: 50.503887, + longitudeDelta: 10.0, + name: 'Belgium', + longitude: 4.469936, + latitudeDelta: 10.0, }, { - 'latitude': 17.189877, - 'longitudeDelta': 10.0, - 'name': 'Belize', - 'longitude': -88.49765, - 'latitudeDelta': 10.0, + latitude: 17.189877, + longitudeDelta: 10.0, + name: 'Belize', + longitude: -88.49765, + latitudeDelta: 10.0, }, { - 'latitude': 9.30769, - 'longitudeDelta': 10.0, - 'name': 'Benin', - 'longitude': 2.315834, - 'latitudeDelta': 10.0, + latitude: 9.30769, + longitudeDelta: 10.0, + name: 'Benin', + longitude: 2.315834, + latitudeDelta: 10.0, }, { - 'latitude': 32.321384, - 'longitudeDelta': 10.0, - 'name': 'Bermuda', - 'longitude': -64.75737, - 'latitudeDelta': 10.0, + latitude: 32.321384, + longitudeDelta: 10.0, + name: 'Bermuda', + longitude: -64.75737, + latitudeDelta: 10.0, }, { - 'latitude': 27.514162, - 'longitudeDelta': 10.0, - 'name': 'Bhutan', - 'longitude': 90.433601, - 'latitudeDelta': 10.0, + latitude: 27.514162, + longitudeDelta: 10.0, + name: 'Bhutan', + longitude: 90.433601, + latitudeDelta: 10.0, }, { - 'latitude': -16.290154, - 'longitudeDelta': 10.0, - 'name': 'Bolivia', - 'longitude': -63.588653, - 'latitudeDelta': 10.0, + latitude: -16.290154, + longitudeDelta: 10.0, + name: 'Bolivia', + longitude: -63.588653, + latitudeDelta: 10.0, }, { - 'latitude': 43.915886, - 'longitudeDelta': 10.0, - 'name': 'Bosnia and Herzegovina', - 'longitude': 17.679076, - 'latitudeDelta': 10.0, + latitude: 43.915886, + longitudeDelta: 10.0, + name: 'Bosnia and Herzegovina', + longitude: 17.679076, + latitudeDelta: 10.0, }, { - 'latitude': -22.328474, - 'longitudeDelta': 10.0, - 'name': 'Botswana', - 'longitude': 24.684866, - 'latitudeDelta': 10.0, + latitude: -22.328474, + longitudeDelta: 10.0, + name: 'Botswana', + longitude: 24.684866, + latitudeDelta: 10.0, }, { - 'latitude': -54.423199, - 'longitudeDelta': 10.0, - 'name': 'Bouvet Island', - 'longitude': 3.413194, - 'latitudeDelta': 10.0, + latitude: -54.423199, + longitudeDelta: 10.0, + name: 'Bouvet Island', + longitude: 3.413194, + latitudeDelta: 10.0, }, { - 'latitude': -14.235004, - 'longitudeDelta': 10.0, - 'name': 'Brazil', - 'longitude': -51.92528, - 'latitudeDelta': 10.0, + latitude: -14.235004, + longitudeDelta: 10.0, + name: 'Brazil', + longitude: -51.92528, + latitudeDelta: 10.0, }, { - 'latitude': -6.343194, - 'longitudeDelta': 10.0, - 'name': 'British Indian Ocean Territory', - 'longitude': 71.876519, - 'latitudeDelta': 10.0, + latitude: -6.343194, + longitudeDelta: 10.0, + name: 'British Indian Ocean Territory', + longitude: 71.876519, + latitudeDelta: 10.0, }, { - 'latitude': 18.420695, - 'longitudeDelta': 10.0, - 'name': 'British Virgin Islands', - 'longitude': -64.639968, - 'latitudeDelta': 10.0, + latitude: 18.420695, + longitudeDelta: 10.0, + name: 'British Virgin Islands', + longitude: -64.639968, + latitudeDelta: 10.0, }, { - 'latitude': 4.535277, - 'longitudeDelta': 10.0, - 'name': 'Brunei', - 'longitude': 114.727669, - 'latitudeDelta': 10.0, + latitude: 4.535277, + longitudeDelta: 10.0, + name: 'Brunei', + longitude: 114.727669, + latitudeDelta: 10.0, }, { - 'latitude': 42.733883, - 'longitudeDelta': 10.0, - 'name': 'Bulgaria', - 'longitude': 25.48583, - 'latitudeDelta': 10.0, + latitude: 42.733883, + longitudeDelta: 10.0, + name: 'Bulgaria', + longitude: 25.48583, + latitudeDelta: 10.0, }, { - 'latitude': 12.238333, - 'longitudeDelta': 10.0, - 'name': 'Burkina Faso', - 'longitude': -1.561593, - 'latitudeDelta': 10.0, + latitude: 12.238333, + longitudeDelta: 10.0, + name: 'Burkina Faso', + longitude: -1.561593, + latitudeDelta: 10.0, }, { - 'latitude': -3.373056, - 'longitudeDelta': 10.0, - 'name': 'Burundi', - 'longitude': 29.918886, - 'latitudeDelta': 10.0, + latitude: -3.373056, + longitudeDelta: 10.0, + name: 'Burundi', + longitude: 29.918886, + latitudeDelta: 10.0, }, { - 'latitude': 12.565679, - 'longitudeDelta': 10.0, - 'name': 'Cambodia', - 'longitude': 104.990963, - 'latitudeDelta': 10.0, + latitude: 12.565679, + longitudeDelta: 10.0, + name: 'Cambodia', + longitude: 104.990963, + latitudeDelta: 10.0, }, { - 'latitude': 7.369722, - 'longitudeDelta': 10.0, - 'name': 'Cameroon', - 'longitude': 12.354722, - 'latitudeDelta': 10.0, + latitude: 7.369722, + longitudeDelta: 10.0, + name: 'Cameroon', + longitude: 12.354722, + latitudeDelta: 10.0, }, { - 'latitude': 56.130366, - 'longitudeDelta': 10.0, - 'name': 'Canada', - 'longitude': -106.346771, - 'latitudeDelta': 10.0, + latitude: 56.130366, + longitudeDelta: 10.0, + name: 'Canada', + longitude: -106.346771, + latitudeDelta: 10.0, }, { - 'latitude': 16.002082, - 'longitudeDelta': 10.0, - 'name': 'Cape Verde', - 'longitude': -24.013197, - 'latitudeDelta': 10.0, + latitude: 16.002082, + longitudeDelta: 10.0, + name: 'Cape Verde', + longitude: -24.013197, + latitudeDelta: 10.0, }, { - 'latitude': 19.513469, - 'longitudeDelta': 10.0, - 'name': 'Cayman Islands', - 'longitude': -80.566956, - 'latitudeDelta': 10.0, + latitude: 19.513469, + longitudeDelta: 10.0, + name: 'Cayman Islands', + longitude: -80.566956, + latitudeDelta: 10.0, }, { - 'latitude': 6.611111, - 'longitudeDelta': 10.0, - 'name': 'Central African Republic', - 'longitude': 20.939444, - 'latitudeDelta': 10.0, + latitude: 6.611111, + longitudeDelta: 10.0, + name: 'Central African Republic', + longitude: 20.939444, + latitudeDelta: 10.0, }, { - 'latitude': 15.454166, - 'longitudeDelta': 10.0, - 'name': 'Chad', - 'longitude': 18.732207, - 'latitudeDelta': 10.0, + latitude: 15.454166, + longitudeDelta: 10.0, + name: 'Chad', + longitude: 18.732207, + latitudeDelta: 10.0, }, { - 'latitude': -35.675147, - 'longitudeDelta': 10.0, - 'name': 'Chile', - 'longitude': -71.542969, - 'latitudeDelta': 10.0, + latitude: -35.675147, + longitudeDelta: 10.0, + name: 'Chile', + longitude: -71.542969, + latitudeDelta: 10.0, }, { - 'latitude': 35.86166, - 'longitudeDelta': 10.0, - 'name': 'China', - 'longitude': 104.195397, - 'latitudeDelta': 10.0, + latitude: 35.86166, + longitudeDelta: 10.0, + name: 'China', + longitude: 104.195397, + latitudeDelta: 10.0, }, { - 'latitude': -10.447525, - 'longitudeDelta': 10.0, - 'name': 'Christmas Island', - 'longitude': 105.690449, - 'latitudeDelta': 10.0, + latitude: -10.447525, + longitudeDelta: 10.0, + name: 'Christmas Island', + longitude: 105.690449, + latitudeDelta: 10.0, }, { - 'latitude': -12.164165, - 'longitudeDelta': 10.0, - 'name': 'Cocos [Keeling] Islands', - 'longitude': 96.870956, - 'latitudeDelta': 10.0, + latitude: -12.164165, + longitudeDelta: 10.0, + name: 'Cocos [Keeling] Islands', + longitude: 96.870956, + latitudeDelta: 10.0, }, { - 'latitude': 4.570868, - 'longitudeDelta': 10.0, - 'name': 'Colombia', - 'longitude': -74.297333, - 'latitudeDelta': 10.0, + latitude: 4.570868, + longitudeDelta: 10.0, + name: 'Colombia', + longitude: -74.297333, + latitudeDelta: 10.0, }, { - 'latitude': -11.875001, - 'longitudeDelta': 10.0, - 'name': 'Comoros', - 'longitude': 43.872219, - 'latitudeDelta': 10.0, + latitude: -11.875001, + longitudeDelta: 10.0, + name: 'Comoros', + longitude: 43.872219, + latitudeDelta: 10.0, }, { - 'latitude': -4.038333, - 'longitudeDelta': 10.0, - 'name': 'Congo [DRC]', - 'longitude': 21.758664, - 'latitudeDelta': 10.0, + latitude: -4.038333, + longitudeDelta: 10.0, + name: 'Congo [DRC]', + longitude: 21.758664, + latitudeDelta: 10.0, }, { - 'latitude': -0.228021, - 'longitudeDelta': 10.0, - 'name': 'Congo [Republic]', - 'longitude': 15.827659, - 'latitudeDelta': 10.0, + latitude: -0.228021, + longitudeDelta: 10.0, + name: 'Congo [Republic]', + longitude: 15.827659, + latitudeDelta: 10.0, }, { - 'latitude': -21.236736, - 'longitudeDelta': 10.0, - 'name': 'Cook Islands', - 'longitude': -159.777671, - 'latitudeDelta': 10.0, + latitude: -21.236736, + longitudeDelta: 10.0, + name: 'Cook Islands', + longitude: -159.777671, + latitudeDelta: 10.0, }, { - 'latitude': 9.748917, - 'longitudeDelta': 10.0, - 'name': 'Costa Rica', - 'longitude': -83.753428, - 'latitudeDelta': 10.0, + latitude: 9.748917, + longitudeDelta: 10.0, + name: 'Costa Rica', + longitude: -83.753428, + latitudeDelta: 10.0, }, { - 'latitude': 45.1, - 'longitudeDelta': 10.0, - 'name': 'Croatia', - 'longitude': 15.2, - 'latitudeDelta': 10.0, + latitude: 45.1, + longitudeDelta: 10.0, + name: 'Croatia', + longitude: 15.2, + latitudeDelta: 10.0, }, { - 'latitude': 21.521757, - 'longitudeDelta': 10.0, - 'name': 'Cuba', - 'longitude': -77.781167, - 'latitudeDelta': 10.0, + latitude: 21.521757, + longitudeDelta: 10.0, + name: 'Cuba', + longitude: -77.781167, + latitudeDelta: 10.0, }, { - 'latitude': 35.126413, - 'longitudeDelta': 10.0, - 'name': 'Cyprus', - 'longitude': 33.429859, - 'latitudeDelta': 10.0, + latitude: 35.126413, + longitudeDelta: 10.0, + name: 'Cyprus', + longitude: 33.429859, + latitudeDelta: 10.0, }, { - 'latitude': 49.817492, - 'longitudeDelta': 10.0, - 'name': 'Czech Republic', - 'longitude': 15.472962, - 'latitudeDelta': 10.0, + latitude: 49.817492, + longitudeDelta: 10.0, + name: 'Czech Republic', + longitude: 15.472962, + latitudeDelta: 10.0, }, { - 'latitude': 7.539989, - 'longitudeDelta': 10.0, - 'name': "C\u00f4te d'Ivoire", - 'longitude': -5.54708, - 'latitudeDelta': 10.0, + latitude: 7.539989, + longitudeDelta: 10.0, + name: "C\u00f4te d'Ivoire", + longitude: -5.54708, + latitudeDelta: 10.0, }, { - 'latitude': 56.26392, - 'longitudeDelta': 10.0, - 'name': 'Denmark', - 'longitude': 9.501785, - 'latitudeDelta': 10.0, + latitude: 56.26392, + longitudeDelta: 10.0, + name: 'Denmark', + longitude: 9.501785, + latitudeDelta: 10.0, }, { - 'latitude': 11.825138, - 'longitudeDelta': 10.0, - 'name': 'Djibouti', - 'longitude': 42.590275, - 'latitudeDelta': 10.0, + latitude: 11.825138, + longitudeDelta: 10.0, + name: 'Djibouti', + longitude: 42.590275, + latitudeDelta: 10.0, }, { - 'latitude': 15.414999, - 'longitudeDelta': 10.0, - 'name': 'Dominica', - 'longitude': -61.370976, - 'latitudeDelta': 10.0, + latitude: 15.414999, + longitudeDelta: 10.0, + name: 'Dominica', + longitude: -61.370976, + latitudeDelta: 10.0, }, { - 'latitude': 18.735693, - 'longitudeDelta': 10.0, - 'name': 'Dominican Republic', - 'longitude': -70.162651, - 'latitudeDelta': 10.0, + latitude: 18.735693, + longitudeDelta: 10.0, + name: 'Dominican Republic', + longitude: -70.162651, + latitudeDelta: 10.0, }, { - 'latitude': -1.831239, - 'longitudeDelta': 10.0, - 'name': 'Ecuador', - 'longitude': -78.183406, - 'latitudeDelta': 10.0, + latitude: -1.831239, + longitudeDelta: 10.0, + name: 'Ecuador', + longitude: -78.183406, + latitudeDelta: 10.0, }, { - 'latitude': 26.820553, - 'longitudeDelta': 10.0, - 'name': 'Egypt', - 'longitude': 30.802498, - 'latitudeDelta': 10.0, + latitude: 26.820553, + longitudeDelta: 10.0, + name: 'Egypt', + longitude: 30.802498, + latitudeDelta: 10.0, }, { - 'latitude': 13.794185, - 'longitudeDelta': 10.0, - 'name': 'El Salvador', - 'longitude': -88.89653, - 'latitudeDelta': 10.0, + latitude: 13.794185, + longitudeDelta: 10.0, + name: 'El Salvador', + longitude: -88.89653, + latitudeDelta: 10.0, }, { - 'latitude': 1.650801, - 'longitudeDelta': 10.0, - 'name': 'Equatorial Guinea', - 'longitude': 10.267895, - 'latitudeDelta': 10.0, + latitude: 1.650801, + longitudeDelta: 10.0, + name: 'Equatorial Guinea', + longitude: 10.267895, + latitudeDelta: 10.0, }, { - 'latitude': 15.179384, - 'longitudeDelta': 10.0, - 'name': 'Eritrea', - 'longitude': 39.782334, - 'latitudeDelta': 10.0, + latitude: 15.179384, + longitudeDelta: 10.0, + name: 'Eritrea', + longitude: 39.782334, + latitudeDelta: 10.0, }, { - 'latitude': 58.595272, - 'longitudeDelta': 10.0, - 'name': 'Estonia', - 'longitude': 25.013607, - 'latitudeDelta': 10.0, + latitude: 58.595272, + longitudeDelta: 10.0, + name: 'Estonia', + longitude: 25.013607, + latitudeDelta: 10.0, }, { - 'latitude': 9.145, - 'longitudeDelta': 10.0, - 'name': 'Ethiopia', - 'longitude': 40.489673, - 'latitudeDelta': 10.0, + latitude: 9.145, + longitudeDelta: 10.0, + name: 'Ethiopia', + longitude: 40.489673, + latitudeDelta: 10.0, }, { - 'latitude': -51.796253, - 'longitudeDelta': 10.0, - 'name': 'Falkland Islands [Islas Malvinas]', - 'longitude': -59.523613, - 'latitudeDelta': 10.0, + latitude: -51.796253, + longitudeDelta: 10.0, + name: 'Falkland Islands [Islas Malvinas]', + longitude: -59.523613, + latitudeDelta: 10.0, }, { - 'latitude': 61.892635, - 'longitudeDelta': 10.0, - 'name': 'Faroe Islands', - 'longitude': -6.911806, - 'latitudeDelta': 10.0, + latitude: 61.892635, + longitudeDelta: 10.0, + name: 'Faroe Islands', + longitude: -6.911806, + latitudeDelta: 10.0, }, { - 'latitude': -16.578193, - 'longitudeDelta': 10.0, - 'name': 'Fiji', - 'longitude': 179.414413, - 'latitudeDelta': 10.0, + latitude: -16.578193, + longitudeDelta: 10.0, + name: 'Fiji', + longitude: 179.414413, + latitudeDelta: 10.0, }, { - 'latitude': 61.92411, - 'longitudeDelta': 10.0, - 'name': 'Finland', - 'longitude': 25.748151, - 'latitudeDelta': 10.0, + latitude: 61.92411, + longitudeDelta: 10.0, + name: 'Finland', + longitude: 25.748151, + latitudeDelta: 10.0, }, { - 'latitude': 46.227638, - 'longitudeDelta': 10.0, - 'name': 'France', - 'longitude': 2.213749, - 'latitudeDelta': 10.0, + latitude: 46.227638, + longitudeDelta: 10.0, + name: 'France', + longitude: 2.213749, + latitudeDelta: 10.0, }, { - 'latitude': 3.933889, - 'longitudeDelta': 10.0, - 'name': 'French Guiana', - 'longitude': -53.125782, - 'latitudeDelta': 10.0, + latitude: 3.933889, + longitudeDelta: 10.0, + name: 'French Guiana', + longitude: -53.125782, + latitudeDelta: 10.0, }, { - 'latitude': -17.679742, - 'longitudeDelta': 10.0, - 'name': 'French Polynesia', - 'longitude': -149.406843, - 'latitudeDelta': 10.0, + latitude: -17.679742, + longitudeDelta: 10.0, + name: 'French Polynesia', + longitude: -149.406843, + latitudeDelta: 10.0, }, { - 'latitude': -49.280366, - 'longitudeDelta': 10.0, - 'name': 'French Southern Territories', - 'longitude': 69.348557, - 'latitudeDelta': 10.0, + latitude: -49.280366, + longitudeDelta: 10.0, + name: 'French Southern Territories', + longitude: 69.348557, + latitudeDelta: 10.0, }, { - 'latitude': -0.803689, - 'longitudeDelta': 10.0, - 'name': 'Gabon', - 'longitude': 11.609444, - 'latitudeDelta': 10.0, + latitude: -0.803689, + longitudeDelta: 10.0, + name: 'Gabon', + longitude: 11.609444, + latitudeDelta: 10.0, }, { - 'latitude': 13.443182, - 'longitudeDelta': 10.0, - 'name': 'Gambia', - 'longitude': -15.310139, - 'latitudeDelta': 10.0, + latitude: 13.443182, + longitudeDelta: 10.0, + name: 'Gambia', + longitude: -15.310139, + latitudeDelta: 10.0, }, { - 'latitude': 31.354676, - 'longitudeDelta': 10.0, - 'name': 'Gaza Strip', - 'longitude': 34.308825, - 'latitudeDelta': 10.0, + latitude: 31.354676, + longitudeDelta: 10.0, + name: 'Gaza Strip', + longitude: 34.308825, + latitudeDelta: 10.0, }, { - 'latitude': 42.315407, - 'longitudeDelta': 10.0, - 'name': 'Georgia', - 'longitude': 43.356892, - 'latitudeDelta': 10.0, + latitude: 42.315407, + longitudeDelta: 10.0, + name: 'Georgia', + longitude: 43.356892, + latitudeDelta: 10.0, }, { - 'latitude': 51.165691, - 'longitudeDelta': 10.0, - 'name': 'Germany', - 'longitude': 10.451526, - 'latitudeDelta': 10.0, + latitude: 51.165691, + longitudeDelta: 10.0, + name: 'Germany', + longitude: 10.451526, + latitudeDelta: 10.0, }, { - 'latitude': 7.946527, - 'longitudeDelta': 10.0, - 'name': 'Ghana', - 'longitude': -1.023194, - 'latitudeDelta': 10.0, + latitude: 7.946527, + longitudeDelta: 10.0, + name: 'Ghana', + longitude: -1.023194, + latitudeDelta: 10.0, }, { - 'latitude': 36.137741, - 'longitudeDelta': 10.0, - 'name': 'Gibraltar', - 'longitude': -5.345374, - 'latitudeDelta': 10.0, + latitude: 36.137741, + longitudeDelta: 10.0, + name: 'Gibraltar', + longitude: -5.345374, + latitudeDelta: 10.0, }, { - 'latitude': 39.074208, - 'longitudeDelta': 10.0, - 'name': 'Greece', - 'longitude': 21.824312, - 'latitudeDelta': 10.0, + latitude: 39.074208, + longitudeDelta: 10.0, + name: 'Greece', + longitude: 21.824312, + latitudeDelta: 10.0, }, { - 'latitude': 71.706936, - 'longitudeDelta': 10.0, - 'name': 'Greenland', - 'longitude': -42.604303, - 'latitudeDelta': 10.0, + latitude: 71.706936, + longitudeDelta: 10.0, + name: 'Greenland', + longitude: -42.604303, + latitudeDelta: 10.0, }, { - 'latitude': 12.262776, - 'longitudeDelta': 10.0, - 'name': 'Grenada', - 'longitude': -61.604171, - 'latitudeDelta': 10.0, + latitude: 12.262776, + longitudeDelta: 10.0, + name: 'Grenada', + longitude: -61.604171, + latitudeDelta: 10.0, }, { - 'latitude': 16.995971, - 'longitudeDelta': 10.0, - 'name': 'Guadeloupe', - 'longitude': -62.067641, - 'latitudeDelta': 10.0, + latitude: 16.995971, + longitudeDelta: 10.0, + name: 'Guadeloupe', + longitude: -62.067641, + latitudeDelta: 10.0, }, { - 'latitude': 13.444304, - 'longitudeDelta': 10.0, - 'name': 'Guam', - 'longitude': 144.793731, - 'latitudeDelta': 10.0, + latitude: 13.444304, + longitudeDelta: 10.0, + name: 'Guam', + longitude: 144.793731, + latitudeDelta: 10.0, }, { - 'latitude': 15.783471, - 'longitudeDelta': 10.0, - 'name': 'Guatemala', - 'longitude': -90.230759, - 'latitudeDelta': 10.0, + latitude: 15.783471, + longitudeDelta: 10.0, + name: 'Guatemala', + longitude: -90.230759, + latitudeDelta: 10.0, }, { - 'latitude': 49.465691, - 'longitudeDelta': 10.0, - 'name': 'Guernsey', - 'longitude': -2.585278, - 'latitudeDelta': 10.0, + latitude: 49.465691, + longitudeDelta: 10.0, + name: 'Guernsey', + longitude: -2.585278, + latitudeDelta: 10.0, }, { - 'latitude': 9.945587, - 'longitudeDelta': 10.0, - 'name': 'Guinea', - 'longitude': -9.696645, - 'latitudeDelta': 10.0, + latitude: 9.945587, + longitudeDelta: 10.0, + name: 'Guinea', + longitude: -9.696645, + latitudeDelta: 10.0, }, { - 'latitude': 11.803749, - 'longitudeDelta': 10.0, - 'name': 'Guinea-Bissau', - 'longitude': -15.180413, - 'latitudeDelta': 10.0, + latitude: 11.803749, + longitudeDelta: 10.0, + name: 'Guinea-Bissau', + longitude: -15.180413, + latitudeDelta: 10.0, }, { - 'latitude': 4.860416, - 'longitudeDelta': 10.0, - 'name': 'Guyana', - 'longitude': -58.93018, - 'latitudeDelta': 10.0, + latitude: 4.860416, + longitudeDelta: 10.0, + name: 'Guyana', + longitude: -58.93018, + latitudeDelta: 10.0, }, { - 'latitude': 18.971187, - 'longitudeDelta': 10.0, - 'name': 'Haiti', - 'longitude': -72.285215, - 'latitudeDelta': 10.0, + latitude: 18.971187, + longitudeDelta: 10.0, + name: 'Haiti', + longitude: -72.285215, + latitudeDelta: 10.0, }, { - 'latitude': -53.08181, - 'longitudeDelta': 10.0, - 'name': 'Heard Island and McDonald Islands', - 'longitude': 73.504158, - 'latitudeDelta': 10.0, + latitude: -53.08181, + longitudeDelta: 10.0, + name: 'Heard Island and McDonald Islands', + longitude: 73.504158, + latitudeDelta: 10.0, }, { - 'latitude': 15.199999, - 'longitudeDelta': 10.0, - 'name': 'Honduras', - 'longitude': -86.241905, - 'latitudeDelta': 10.0, + latitude: 15.199999, + longitudeDelta: 10.0, + name: 'Honduras', + longitude: -86.241905, + latitudeDelta: 10.0, }, { - 'latitude': 22.396428, - 'longitudeDelta': 10.0, - 'name': 'Hong Kong', - 'longitude': 114.109497, - 'latitudeDelta': 10.0, + latitude: 22.396428, + longitudeDelta: 10.0, + name: 'Hong Kong', + longitude: 114.109497, + latitudeDelta: 10.0, }, { - 'latitude': 47.162494, - 'longitudeDelta': 10.0, - 'name': 'Hungary', - 'longitude': 19.503304, - 'latitudeDelta': 10.0, + latitude: 47.162494, + longitudeDelta: 10.0, + name: 'Hungary', + longitude: 19.503304, + latitudeDelta: 10.0, }, { - 'latitude': 64.963051, - 'longitudeDelta': 10.0, - 'name': 'Iceland', - 'longitude': -19.020835, - 'latitudeDelta': 10.0, + latitude: 64.963051, + longitudeDelta: 10.0, + name: 'Iceland', + longitude: -19.020835, + latitudeDelta: 10.0, }, { - 'latitude': 20.593684, - 'longitudeDelta': 10.0, - 'name': 'India', - 'longitude': 78.96288, - 'latitudeDelta': 10.0, + latitude: 20.593684, + longitudeDelta: 10.0, + name: 'India', + longitude: 78.96288, + latitudeDelta: 10.0, }, { - 'latitude': -0.789275, - 'longitudeDelta': 10.0, - 'name': 'Indonesia', - 'longitude': 113.921327, - 'latitudeDelta': 10.0, + latitude: -0.789275, + longitudeDelta: 10.0, + name: 'Indonesia', + longitude: 113.921327, + latitudeDelta: 10.0, }, { - 'latitude': 32.427908, - 'longitudeDelta': 10.0, - 'name': 'Iran', - 'longitude': 53.688046, - 'latitudeDelta': 10.0, + latitude: 32.427908, + longitudeDelta: 10.0, + name: 'Iran', + longitude: 53.688046, + latitudeDelta: 10.0, }, { - 'latitude': 33.223191, - 'longitudeDelta': 10.0, - 'name': 'Iraq', - 'longitude': 43.679291, - 'latitudeDelta': 10.0, + latitude: 33.223191, + longitudeDelta: 10.0, + name: 'Iraq', + longitude: 43.679291, + latitudeDelta: 10.0, }, { - 'latitude': 53.41291, - 'longitudeDelta': 10.0, - 'name': 'Ireland', - 'longitude': -8.24389, - 'latitudeDelta': 10.0, + latitude: 53.41291, + longitudeDelta: 10.0, + name: 'Ireland', + longitude: -8.24389, + latitudeDelta: 10.0, }, { - 'latitude': 54.236107, - 'longitudeDelta': 10.0, - 'name': 'Isle of Man', - 'longitude': -4.548056, - 'latitudeDelta': 10.0, + latitude: 54.236107, + longitudeDelta: 10.0, + name: 'Isle of Man', + longitude: -4.548056, + latitudeDelta: 10.0, }, { - 'latitude': 31.046051, - 'longitudeDelta': 10.0, - 'name': 'Israel', - 'longitude': 34.851612, - 'latitudeDelta': 10.0, + latitude: 31.046051, + longitudeDelta: 10.0, + name: 'Israel', + longitude: 34.851612, + latitudeDelta: 10.0, }, { - 'latitude': 41.87194, - 'longitudeDelta': 10.0, - 'name': 'Italy', - 'longitude': 12.56738, - 'latitudeDelta': 10.0, + latitude: 41.87194, + longitudeDelta: 10.0, + name: 'Italy', + longitude: 12.56738, + latitudeDelta: 10.0, }, { - 'latitude': 18.109581, - 'longitudeDelta': 10.0, - 'name': 'Jamaica', - 'longitude': -77.297508, - 'latitudeDelta': 10.0, + latitude: 18.109581, + longitudeDelta: 10.0, + name: 'Jamaica', + longitude: -77.297508, + latitudeDelta: 10.0, }, { - 'latitude': 36.204824, - 'longitudeDelta': 10.0, - 'name': 'Japan', - 'longitude': 138.252924, - 'latitudeDelta': 10.0, + latitude: 36.204824, + longitudeDelta: 10.0, + name: 'Japan', + longitude: 138.252924, + latitudeDelta: 10.0, }, { - 'latitude': 49.214439, - 'longitudeDelta': 10.0, - 'name': 'Jersey', - 'longitude': -2.13125, - 'latitudeDelta': 10.0, + latitude: 49.214439, + longitudeDelta: 10.0, + name: 'Jersey', + longitude: -2.13125, + latitudeDelta: 10.0, }, { - 'latitude': 30.585164, - 'longitudeDelta': 10.0, - 'name': 'Jordan', - 'longitude': 36.238414, - 'latitudeDelta': 10.0, + latitude: 30.585164, + longitudeDelta: 10.0, + name: 'Jordan', + longitude: 36.238414, + latitudeDelta: 10.0, }, { - 'latitude': 48.019573, - 'longitudeDelta': 10.0, - 'name': 'Kazakhstan', - 'longitude': 66.923684, - 'latitudeDelta': 10.0, + latitude: 48.019573, + longitudeDelta: 10.0, + name: 'Kazakhstan', + longitude: 66.923684, + latitudeDelta: 10.0, }, { - 'latitude': -0.023559, - 'longitudeDelta': 10.0, - 'name': 'Kenya', - 'longitude': 37.906193, - 'latitudeDelta': 10.0, + latitude: -0.023559, + longitudeDelta: 10.0, + name: 'Kenya', + longitude: 37.906193, + latitudeDelta: 10.0, }, { - 'latitude': -3.370417, - 'longitudeDelta': 10.0, - 'name': 'Kiribati', - 'longitude': -168.734039, - 'latitudeDelta': 10.0, + latitude: -3.370417, + longitudeDelta: 10.0, + name: 'Kiribati', + longitude: -168.734039, + latitudeDelta: 10.0, }, { - 'latitude': 42.602636, - 'longitudeDelta': 10.0, - 'name': 'Kosovo', - 'longitude': 20.902977, - 'latitudeDelta': 10.0, + latitude: 42.602636, + longitudeDelta: 10.0, + name: 'Kosovo', + longitude: 20.902977, + latitudeDelta: 10.0, }, { - 'latitude': 29.31166, - 'longitudeDelta': 10.0, - 'name': 'Kuwait', - 'longitude': 47.481766, - 'latitudeDelta': 10.0, + latitude: 29.31166, + longitudeDelta: 10.0, + name: 'Kuwait', + longitude: 47.481766, + latitudeDelta: 10.0, }, { - 'latitude': 41.20438, - 'longitudeDelta': 10.0, - 'name': 'Kyrgyzstan', - 'longitude': 74.766098, - 'latitudeDelta': 10.0, + latitude: 41.20438, + longitudeDelta: 10.0, + name: 'Kyrgyzstan', + longitude: 74.766098, + latitudeDelta: 10.0, }, { - 'latitude': 19.85627, - 'longitudeDelta': 10.0, - 'name': 'Laos', - 'longitude': 102.495496, - 'latitudeDelta': 10.0, + latitude: 19.85627, + longitudeDelta: 10.0, + name: 'Laos', + longitude: 102.495496, + latitudeDelta: 10.0, }, { - 'latitude': 56.879635, - 'longitudeDelta': 10.0, - 'name': 'Latvia', - 'longitude': 24.603189, - 'latitudeDelta': 10.0, + latitude: 56.879635, + longitudeDelta: 10.0, + name: 'Latvia', + longitude: 24.603189, + latitudeDelta: 10.0, }, { - 'latitude': 33.854721, - 'longitudeDelta': 10.0, - 'name': 'Lebanon', - 'longitude': 35.862285, - 'latitudeDelta': 10.0, + latitude: 33.854721, + longitudeDelta: 10.0, + name: 'Lebanon', + longitude: 35.862285, + latitudeDelta: 10.0, }, { - 'latitude': -29.609988, - 'longitudeDelta': 10.0, - 'name': 'Lesotho', - 'longitude': 28.233608, - 'latitudeDelta': 10.0, + latitude: -29.609988, + longitudeDelta: 10.0, + name: 'Lesotho', + longitude: 28.233608, + latitudeDelta: 10.0, }, { - 'latitude': 6.428055, - 'longitudeDelta': 10.0, - 'name': 'Liberia', - 'longitude': -9.429499, - 'latitudeDelta': 10.0, + latitude: 6.428055, + longitudeDelta: 10.0, + name: 'Liberia', + longitude: -9.429499, + latitudeDelta: 10.0, }, { - 'latitude': 26.3351, - 'longitudeDelta': 10.0, - 'name': 'Libya', - 'longitude': 17.228331, - 'latitudeDelta': 10.0, + latitude: 26.3351, + longitudeDelta: 10.0, + name: 'Libya', + longitude: 17.228331, + latitudeDelta: 10.0, }, { - 'latitude': 47.166, - 'longitudeDelta': 10.0, - 'name': 'Liechtenstein', - 'longitude': 9.555373, - 'latitudeDelta': 10.0, + latitude: 47.166, + longitudeDelta: 10.0, + name: 'Liechtenstein', + longitude: 9.555373, + latitudeDelta: 10.0, }, { - 'latitude': 55.169438, - 'longitudeDelta': 10.0, - 'name': 'Lithuania', - 'longitude': 23.881275, - 'latitudeDelta': 10.0, + latitude: 55.169438, + longitudeDelta: 10.0, + name: 'Lithuania', + longitude: 23.881275, + latitudeDelta: 10.0, }, { - 'latitude': 49.815273, - 'longitudeDelta': 10.0, - 'name': 'Luxembourg', - 'longitude': 6.129583, - 'latitudeDelta': 10.0, + latitude: 49.815273, + longitudeDelta: 10.0, + name: 'Luxembourg', + longitude: 6.129583, + latitudeDelta: 10.0, }, { - 'latitude': 22.198745, - 'longitudeDelta': 10.0, - 'name': 'Macau', - 'longitude': 113.543873, - 'latitudeDelta': 10.0, + latitude: 22.198745, + longitudeDelta: 10.0, + name: 'Macau', + longitude: 113.543873, + latitudeDelta: 10.0, }, { - 'latitude': 41.608635, - 'longitudeDelta': 10.0, - 'name': 'Macedonia [FYROM]', - 'longitude': 21.745275, - 'latitudeDelta': 10.0, + latitude: 41.608635, + longitudeDelta: 10.0, + name: 'Macedonia [FYROM]', + longitude: 21.745275, + latitudeDelta: 10.0, }, { - 'latitude': -18.766947, - 'longitudeDelta': 10.0, - 'name': 'Madagascar', - 'longitude': 46.869107, - 'latitudeDelta': 10.0, + latitude: -18.766947, + longitudeDelta: 10.0, + name: 'Madagascar', + longitude: 46.869107, + latitudeDelta: 10.0, }, { - 'latitude': -13.254308, - 'longitudeDelta': 10.0, - 'name': 'Malawi', - 'longitude': 34.301525, - 'latitudeDelta': 10.0, + latitude: -13.254308, + longitudeDelta: 10.0, + name: 'Malawi', + longitude: 34.301525, + latitudeDelta: 10.0, }, { - 'latitude': 4.210484, - 'longitudeDelta': 10.0, - 'name': 'Malaysia', - 'longitude': 101.975766, - 'latitudeDelta': 10.0, + latitude: 4.210484, + longitudeDelta: 10.0, + name: 'Malaysia', + longitude: 101.975766, + latitudeDelta: 10.0, }, { - 'latitude': 3.202778, - 'longitudeDelta': 10.0, - 'name': 'Maldives', - 'longitude': 73.22068, - 'latitudeDelta': 10.0, + latitude: 3.202778, + longitudeDelta: 10.0, + name: 'Maldives', + longitude: 73.22068, + latitudeDelta: 10.0, }, { - 'latitude': 17.570692, - 'longitudeDelta': 10.0, - 'name': 'Mali', - 'longitude': -3.996166, - 'latitudeDelta': 10.0, + latitude: 17.570692, + longitudeDelta: 10.0, + name: 'Mali', + longitude: -3.996166, + latitudeDelta: 10.0, }, { - 'latitude': 35.937496, - 'longitudeDelta': 10.0, - 'name': 'Malta', - 'longitude': 14.375416, - 'latitudeDelta': 10.0, + latitude: 35.937496, + longitudeDelta: 10.0, + name: 'Malta', + longitude: 14.375416, + latitudeDelta: 10.0, }, { - 'latitude': 7.131474, - 'longitudeDelta': 10.0, - 'name': 'Marshall Islands', - 'longitude': 171.184478, - 'latitudeDelta': 10.0, + latitude: 7.131474, + longitudeDelta: 10.0, + name: 'Marshall Islands', + longitude: 171.184478, + latitudeDelta: 10.0, }, { - 'latitude': 14.641528, - 'longitudeDelta': 10.0, - 'name': 'Martinique', - 'longitude': -61.024174, - 'latitudeDelta': 10.0, + latitude: 14.641528, + longitudeDelta: 10.0, + name: 'Martinique', + longitude: -61.024174, + latitudeDelta: 10.0, }, { - 'latitude': 21.00789, - 'longitudeDelta': 10.0, - 'name': 'Mauritania', - 'longitude': -10.940835, - 'latitudeDelta': 10.0, + latitude: 21.00789, + longitudeDelta: 10.0, + name: 'Mauritania', + longitude: -10.940835, + latitudeDelta: 10.0, }, { - 'latitude': -20.348404, - 'longitudeDelta': 10.0, - 'name': 'Mauritius', - 'longitude': 57.552152, - 'latitudeDelta': 10.0, + latitude: -20.348404, + longitudeDelta: 10.0, + name: 'Mauritius', + longitude: 57.552152, + latitudeDelta: 10.0, }, { - 'latitude': -12.8275, - 'longitudeDelta': 10.0, - 'name': 'Mayotte', - 'longitude': 45.166244, - 'latitudeDelta': 10.0, + latitude: -12.8275, + longitudeDelta: 10.0, + name: 'Mayotte', + longitude: 45.166244, + latitudeDelta: 10.0, }, { - 'latitude': 23.634501, - 'longitudeDelta': 10.0, - 'name': 'Mexico', - 'longitude': -102.552784, - 'latitudeDelta': 10.0, + latitude: 23.634501, + longitudeDelta: 10.0, + name: 'Mexico', + longitude: -102.552784, + latitudeDelta: 10.0, }, { - 'latitude': 7.425554, - 'longitudeDelta': 10.0, - 'name': 'Micronesia', - 'longitude': 150.550812, - 'latitudeDelta': 10.0, + latitude: 7.425554, + longitudeDelta: 10.0, + name: 'Micronesia', + longitude: 150.550812, + latitudeDelta: 10.0, }, { - 'latitude': 47.411631, - 'longitudeDelta': 10.0, - 'name': 'Moldova', - 'longitude': 28.369885, - 'latitudeDelta': 10.0, + latitude: 47.411631, + longitudeDelta: 10.0, + name: 'Moldova', + longitude: 28.369885, + latitudeDelta: 10.0, }, { - 'latitude': 43.750298, - 'longitudeDelta': 10.0, - 'name': 'Monaco', - 'longitude': 7.412841, - 'latitudeDelta': 10.0, + latitude: 43.750298, + longitudeDelta: 10.0, + name: 'Monaco', + longitude: 7.412841, + latitudeDelta: 10.0, }, { - 'latitude': 46.862496, - 'longitudeDelta': 10.0, - 'name': 'Mongolia', - 'longitude': 103.846656, - 'latitudeDelta': 10.0, + latitude: 46.862496, + longitudeDelta: 10.0, + name: 'Mongolia', + longitude: 103.846656, + latitudeDelta: 10.0, }, { - 'latitude': 42.708678, - 'longitudeDelta': 10.0, - 'name': 'Montenegro', - 'longitude': 19.37439, - 'latitudeDelta': 10.0, + latitude: 42.708678, + longitudeDelta: 10.0, + name: 'Montenegro', + longitude: 19.37439, + latitudeDelta: 10.0, }, { - 'latitude': 16.742498, - 'longitudeDelta': 10.0, - 'name': 'Montserrat', - 'longitude': -62.187366, - 'latitudeDelta': 10.0, + latitude: 16.742498, + longitudeDelta: 10.0, + name: 'Montserrat', + longitude: -62.187366, + latitudeDelta: 10.0, }, { - 'latitude': 31.791702, - 'longitudeDelta': 10.0, - 'name': 'Morocco', - 'longitude': -7.09262, - 'latitudeDelta': 10.0, + latitude: 31.791702, + longitudeDelta: 10.0, + name: 'Morocco', + longitude: -7.09262, + latitudeDelta: 10.0, }, { - 'latitude': -18.665695, - 'longitudeDelta': 10.0, - 'name': 'Mozambique', - 'longitude': 35.529562, - 'latitudeDelta': 10.0, + latitude: -18.665695, + longitudeDelta: 10.0, + name: 'Mozambique', + longitude: 35.529562, + latitudeDelta: 10.0, }, { - 'latitude': 21.913965, - 'longitudeDelta': 10.0, - 'name': 'Myanmar [Burma]', - 'longitude': 95.956223, - 'latitudeDelta': 10.0, + latitude: 21.913965, + longitudeDelta: 10.0, + name: 'Myanmar [Burma]', + longitude: 95.956223, + latitudeDelta: 10.0, }, { - 'latitude': -22.95764, - 'longitudeDelta': 10.0, - 'name': 'Namibia', - 'longitude': 18.49041, - 'latitudeDelta': 10.0, + latitude: -22.95764, + longitudeDelta: 10.0, + name: 'Namibia', + longitude: 18.49041, + latitudeDelta: 10.0, }, { - 'latitude': -0.522778, - 'longitudeDelta': 10.0, - 'name': 'Nauru', - 'longitude': 166.931503, - 'latitudeDelta': 10.0, + latitude: -0.522778, + longitudeDelta: 10.0, + name: 'Nauru', + longitude: 166.931503, + latitudeDelta: 10.0, }, { - 'latitude': 28.394857, - 'longitudeDelta': 10.0, - 'name': 'Nepal', - 'longitude': 84.124008, - 'latitudeDelta': 10.0, + latitude: 28.394857, + longitudeDelta: 10.0, + name: 'Nepal', + longitude: 84.124008, + latitudeDelta: 10.0, }, { - 'latitude': 52.132633, - 'longitudeDelta': 10.0, - 'name': 'Netherlands', - 'longitude': 5.291266, - 'latitudeDelta': 10.0, + latitude: 52.132633, + longitudeDelta: 10.0, + name: 'Netherlands', + longitude: 5.291266, + latitudeDelta: 10.0, }, { - 'latitude': 12.226079, - 'longitudeDelta': 10.0, - 'name': 'Netherlands Antilles', - 'longitude': -69.060087, - 'latitudeDelta': 10.0, + latitude: 12.226079, + longitudeDelta: 10.0, + name: 'Netherlands Antilles', + longitude: -69.060087, + latitudeDelta: 10.0, }, { - 'latitude': -20.904305, - 'longitudeDelta': 10.0, - 'name': 'New Caledonia', - 'longitude': 165.618042, - 'latitudeDelta': 10.0, + latitude: -20.904305, + longitudeDelta: 10.0, + name: 'New Caledonia', + longitude: 165.618042, + latitudeDelta: 10.0, }, { - 'latitude': -40.900557, - 'longitudeDelta': 10.0, - 'name': 'New Zealand', - 'longitude': 174.885971, - 'latitudeDelta': 10.0, + latitude: -40.900557, + longitudeDelta: 10.0, + name: 'New Zealand', + longitude: 174.885971, + latitudeDelta: 10.0, }, { - 'latitude': 12.865416, - 'longitudeDelta': 10.0, - 'name': 'Nicaragua', - 'longitude': -85.207229, - 'latitudeDelta': 10.0, + latitude: 12.865416, + longitudeDelta: 10.0, + name: 'Nicaragua', + longitude: -85.207229, + latitudeDelta: 10.0, }, { - 'latitude': 17.607789, - 'longitudeDelta': 10.0, - 'name': 'Niger', - 'longitude': 8.081666, - 'latitudeDelta': 10.0, + latitude: 17.607789, + longitudeDelta: 10.0, + name: 'Niger', + longitude: 8.081666, + latitudeDelta: 10.0, }, { - 'latitude': 9.081999, - 'longitudeDelta': 10.0, - 'name': 'Nigeria', - 'longitude': 8.675277, - 'latitudeDelta': 10.0, + latitude: 9.081999, + longitudeDelta: 10.0, + name: 'Nigeria', + longitude: 8.675277, + latitudeDelta: 10.0, }, { - 'latitude': -19.054445, - 'longitudeDelta': 10.0, - 'name': 'Niue', - 'longitude': -169.867233, - 'latitudeDelta': 10.0, + latitude: -19.054445, + longitudeDelta: 10.0, + name: 'Niue', + longitude: -169.867233, + latitudeDelta: 10.0, }, { - 'latitude': -29.040835, - 'longitudeDelta': 10.0, - 'name': 'Norfolk Island', - 'longitude': 167.954712, - 'latitudeDelta': 10.0, + latitude: -29.040835, + longitudeDelta: 10.0, + name: 'Norfolk Island', + longitude: 167.954712, + latitudeDelta: 10.0, }, { - 'latitude': 40.339852, - 'longitudeDelta': 10.0, - 'name': 'North Korea', - 'longitude': 127.510093, - 'latitudeDelta': 10.0, + latitude: 40.339852, + longitudeDelta: 10.0, + name: 'North Korea', + longitude: 127.510093, + latitudeDelta: 10.0, }, { - 'latitude': 17.33083, - 'longitudeDelta': 10.0, - 'name': 'Northern Mariana Islands', - 'longitude': 145.38469, - 'latitudeDelta': 10.0, + latitude: 17.33083, + longitudeDelta: 10.0, + name: 'Northern Mariana Islands', + longitude: 145.38469, + latitudeDelta: 10.0, }, { - 'latitude': 60.472024, - 'longitudeDelta': 10.0, - 'name': 'Norway', - 'longitude': 8.468946, - 'latitudeDelta': 10.0, + latitude: 60.472024, + longitudeDelta: 10.0, + name: 'Norway', + longitude: 8.468946, + latitudeDelta: 10.0, }, { - 'latitude': 21.512583, - 'longitudeDelta': 10.0, - 'name': 'Oman', - 'longitude': 55.923255, - 'latitudeDelta': 10.0, + latitude: 21.512583, + longitudeDelta: 10.0, + name: 'Oman', + longitude: 55.923255, + latitudeDelta: 10.0, }, { - 'latitude': 30.375321, - 'longitudeDelta': 10.0, - 'name': 'Pakistan', - 'longitude': 69.345116, - 'latitudeDelta': 10.0, + latitude: 30.375321, + longitudeDelta: 10.0, + name: 'Pakistan', + longitude: 69.345116, + latitudeDelta: 10.0, }, { - 'latitude': 7.51498, - 'longitudeDelta': 10.0, - 'name': 'Palau', - 'longitude': 134.58252, - 'latitudeDelta': 10.0, + latitude: 7.51498, + longitudeDelta: 10.0, + name: 'Palau', + longitude: 134.58252, + latitudeDelta: 10.0, }, { - 'latitude': 31.952162, - 'longitudeDelta': 10.0, - 'name': 'Palestinian Territories', - 'longitude': 35.233154, - 'latitudeDelta': 10.0, + latitude: 31.952162, + longitudeDelta: 10.0, + name: 'Palestinian Territories', + longitude: 35.233154, + latitudeDelta: 10.0, }, { - 'latitude': 8.537981, - 'longitudeDelta': 10.0, - 'name': 'Panama', - 'longitude': -80.782127, - 'latitudeDelta': 10.0, + latitude: 8.537981, + longitudeDelta: 10.0, + name: 'Panama', + longitude: -80.782127, + latitudeDelta: 10.0, }, { - 'latitude': -6.314993, - 'longitudeDelta': 10.0, - 'name': 'Papua New Guinea', - 'longitude': 143.95555, - 'latitudeDelta': 10.0, + latitude: -6.314993, + longitudeDelta: 10.0, + name: 'Papua New Guinea', + longitude: 143.95555, + latitudeDelta: 10.0, }, { - 'latitude': -23.442503, - 'longitudeDelta': 10.0, - 'name': 'Paraguay', - 'longitude': -58.443832, - 'latitudeDelta': 10.0, + latitude: -23.442503, + longitudeDelta: 10.0, + name: 'Paraguay', + longitude: -58.443832, + latitudeDelta: 10.0, }, { - 'latitude': -9.189967, - 'longitudeDelta': 10.0, - 'name': 'Peru', - 'longitude': -75.015152, - 'latitudeDelta': 10.0, + latitude: -9.189967, + longitudeDelta: 10.0, + name: 'Peru', + longitude: -75.015152, + latitudeDelta: 10.0, }, { - 'latitude': 12.879721, - 'longitudeDelta': 10.0, - 'name': 'Philippines', - 'longitude': 121.774017, - 'latitudeDelta': 10.0, + latitude: 12.879721, + longitudeDelta: 10.0, + name: 'Philippines', + longitude: 121.774017, + latitudeDelta: 10.0, }, { - 'latitude': -24.703615, - 'longitudeDelta': 10.0, - 'name': 'Pitcairn Islands', - 'longitude': -127.439308, - 'latitudeDelta': 10.0, + latitude: -24.703615, + longitudeDelta: 10.0, + name: 'Pitcairn Islands', + longitude: -127.439308, + latitudeDelta: 10.0, }, { - 'latitude': 51.919438, - 'longitudeDelta': 10.0, - 'name': 'Poland', - 'longitude': 19.145136, - 'latitudeDelta': 10.0, + latitude: 51.919438, + longitudeDelta: 10.0, + name: 'Poland', + longitude: 19.145136, + latitudeDelta: 10.0, }, { - 'latitude': 39.399872, - 'longitudeDelta': 10.0, - 'name': 'Portugal', - 'longitude': -8.224454, - 'latitudeDelta': 10.0, + latitude: 39.399872, + longitudeDelta: 10.0, + name: 'Portugal', + longitude: -8.224454, + latitudeDelta: 10.0, }, { - 'latitude': 18.220833, - 'longitudeDelta': 10.0, - 'name': 'Puerto Rico', - 'longitude': -66.590149, - 'latitudeDelta': 10.0, + latitude: 18.220833, + longitudeDelta: 10.0, + name: 'Puerto Rico', + longitude: -66.590149, + latitudeDelta: 10.0, }, { - 'latitude': 25.354826, - 'longitudeDelta': 10.0, - 'name': 'Qatar', - 'longitude': 51.183884, - 'latitudeDelta': 10.0, + latitude: 25.354826, + longitudeDelta: 10.0, + name: 'Qatar', + longitude: 51.183884, + latitudeDelta: 10.0, }, { - 'latitude': 45.943161, - 'longitudeDelta': 10.0, - 'name': 'Romania', - 'longitude': 24.96676, - 'latitudeDelta': 10.0, + latitude: 45.943161, + longitudeDelta: 10.0, + name: 'Romania', + longitude: 24.96676, + latitudeDelta: 10.0, }, { - 'latitude': 61.52401, - 'longitudeDelta': 10.0, - 'name': 'Russia', - 'longitude': 105.318756, - 'latitudeDelta': 10.0, + latitude: 61.52401, + longitudeDelta: 10.0, + name: 'Russia', + longitude: 105.318756, + latitudeDelta: 10.0, }, { - 'latitude': -1.940278, - 'longitudeDelta': 10.0, - 'name': 'Rwanda', - 'longitude': 29.873888, - 'latitudeDelta': 10.0, + latitude: -1.940278, + longitudeDelta: 10.0, + name: 'Rwanda', + longitude: 29.873888, + latitudeDelta: 10.0, }, { - 'latitude': -21.115141, - 'longitudeDelta': 10.0, - 'name': 'R\u00e9union', - 'longitude': 55.536384, - 'latitudeDelta': 10.0, + latitude: -21.115141, + longitudeDelta: 10.0, + name: 'R\u00e9union', + longitude: 55.536384, + latitudeDelta: 10.0, }, { - 'latitude': -24.143474, - 'longitudeDelta': 10.0, - 'name': 'Saint Helena', - 'longitude': -10.030696, - 'latitudeDelta': 10.0, + latitude: -24.143474, + longitudeDelta: 10.0, + name: 'Saint Helena', + longitude: -10.030696, + latitudeDelta: 10.0, }, { - 'latitude': 17.357822, - 'longitudeDelta': 10.0, - 'name': 'Saint Kitts and Nevis', - 'longitude': -62.782998, - 'latitudeDelta': 10.0, + latitude: 17.357822, + longitudeDelta: 10.0, + name: 'Saint Kitts and Nevis', + longitude: -62.782998, + latitudeDelta: 10.0, }, { - 'latitude': 13.909444, - 'longitudeDelta': 10.0, - 'name': 'Saint Lucia', - 'longitude': -60.978893, - 'latitudeDelta': 10.0, + latitude: 13.909444, + longitudeDelta: 10.0, + name: 'Saint Lucia', + longitude: -60.978893, + latitudeDelta: 10.0, }, { - 'latitude': 46.941936, - 'longitudeDelta': 10.0, - 'name': 'Saint Pierre and Miquelon', - 'longitude': -56.27111, - 'latitudeDelta': 10.0, + latitude: 46.941936, + longitudeDelta: 10.0, + name: 'Saint Pierre and Miquelon', + longitude: -56.27111, + latitudeDelta: 10.0, }, { - 'latitude': 12.984305, - 'longitudeDelta': 10.0, - 'name': 'Saint Vincent and the Grenadines', - 'longitude': -61.287228, - 'latitudeDelta': 10.0, + latitude: 12.984305, + longitudeDelta: 10.0, + name: 'Saint Vincent and the Grenadines', + longitude: -61.287228, + latitudeDelta: 10.0, }, { - 'latitude': -13.759029, - 'longitudeDelta': 10.0, - 'name': 'Samoa', - 'longitude': -172.104629, - 'latitudeDelta': 10.0, + latitude: -13.759029, + longitudeDelta: 10.0, + name: 'Samoa', + longitude: -172.104629, + latitudeDelta: 10.0, }, { - 'latitude': 43.94236, - 'longitudeDelta': 10.0, - 'name': 'San Marino', - 'longitude': 12.457777, - 'latitudeDelta': 10.0, + latitude: 43.94236, + longitudeDelta: 10.0, + name: 'San Marino', + longitude: 12.457777, + latitudeDelta: 10.0, }, { - 'latitude': 23.885942, - 'longitudeDelta': 10.0, - 'name': 'Saudi Arabia', - 'longitude': 45.079162, - 'latitudeDelta': 10.0, + latitude: 23.885942, + longitudeDelta: 10.0, + name: 'Saudi Arabia', + longitude: 45.079162, + latitudeDelta: 10.0, }, { - 'latitude': 14.497401, - 'longitudeDelta': 10.0, - 'name': 'Senegal', - 'longitude': -14.452362, - 'latitudeDelta': 10.0, + latitude: 14.497401, + longitudeDelta: 10.0, + name: 'Senegal', + longitude: -14.452362, + latitudeDelta: 10.0, }, { - 'latitude': 44.016521, - 'longitudeDelta': 10.0, - 'name': 'Serbia', - 'longitude': 21.005859, - 'latitudeDelta': 10.0, + latitude: 44.016521, + longitudeDelta: 10.0, + name: 'Serbia', + longitude: 21.005859, + latitudeDelta: 10.0, }, { - 'latitude': -4.679574, - 'longitudeDelta': 10.0, - 'name': 'Seychelles', - 'longitude': 55.491977, - 'latitudeDelta': 10.0, + latitude: -4.679574, + longitudeDelta: 10.0, + name: 'Seychelles', + longitude: 55.491977, + latitudeDelta: 10.0, }, { - 'latitude': 8.460555, - 'longitudeDelta': 10.0, - 'name': 'Sierra Leone', - 'longitude': -11.779889, - 'latitudeDelta': 10.0, + latitude: 8.460555, + longitudeDelta: 10.0, + name: 'Sierra Leone', + longitude: -11.779889, + latitudeDelta: 10.0, }, { - 'latitude': 1.352083, - 'longitudeDelta': 10.0, - 'name': 'Singapore', - 'longitude': 103.819836, - 'latitudeDelta': 10.0, + latitude: 1.352083, + longitudeDelta: 10.0, + name: 'Singapore', + longitude: 103.819836, + latitudeDelta: 10.0, }, { - 'latitude': 48.669026, - 'longitudeDelta': 10.0, - 'name': 'Slovakia', - 'longitude': 19.699024, - 'latitudeDelta': 10.0, + latitude: 48.669026, + longitudeDelta: 10.0, + name: 'Slovakia', + longitude: 19.699024, + latitudeDelta: 10.0, }, { - 'latitude': 46.151241, - 'longitudeDelta': 10.0, - 'name': 'Slovenia', - 'longitude': 14.995463, - 'latitudeDelta': 10.0, + latitude: 46.151241, + longitudeDelta: 10.0, + name: 'Slovenia', + longitude: 14.995463, + latitudeDelta: 10.0, }, { - 'latitude': -9.64571, - 'longitudeDelta': 10.0, - 'name': 'Solomon Islands', - 'longitude': 160.156194, - 'latitudeDelta': 10.0, + latitude: -9.64571, + longitudeDelta: 10.0, + name: 'Solomon Islands', + longitude: 160.156194, + latitudeDelta: 10.0, }, { - 'latitude': 5.152149, - 'longitudeDelta': 10.0, - 'name': 'Somalia', - 'longitude': 46.199616, - 'latitudeDelta': 10.0, + latitude: 5.152149, + longitudeDelta: 10.0, + name: 'Somalia', + longitude: 46.199616, + latitudeDelta: 10.0, }, { - 'latitude': -30.559482, - 'longitudeDelta': 10.0, - 'name': 'South Africa', - 'longitude': 22.937506, - 'latitudeDelta': 10.0, + latitude: -30.559482, + longitudeDelta: 10.0, + name: 'South Africa', + longitude: 22.937506, + latitudeDelta: 10.0, }, { - 'latitude': -54.429579, - 'longitudeDelta': 10.0, - 'name': 'South Georgia and the South Sandwich Islands', - 'longitude': -36.587909, - 'latitudeDelta': 10.0, + latitude: -54.429579, + longitudeDelta: 10.0, + name: 'South Georgia and the South Sandwich Islands', + longitude: -36.587909, + latitudeDelta: 10.0, }, { - 'latitude': 35.907757, - 'longitudeDelta': 10.0, - 'name': 'South Korea', - 'longitude': 127.766922, - 'latitudeDelta': 10.0, + latitude: 35.907757, + longitudeDelta: 10.0, + name: 'South Korea', + longitude: 127.766922, + latitudeDelta: 10.0, }, { - 'latitude': 40.463667, - 'longitudeDelta': 10.0, - 'name': 'Spain', - 'longitude': -3.74922, - 'latitudeDelta': 10.0, + latitude: 40.463667, + longitudeDelta: 10.0, + name: 'Spain', + longitude: -3.74922, + latitudeDelta: 10.0, }, { - 'latitude': 7.873054, - 'longitudeDelta': 10.0, - 'name': 'Sri Lanka', - 'longitude': 80.771797, - 'latitudeDelta': 10.0, + latitude: 7.873054, + longitudeDelta: 10.0, + name: 'Sri Lanka', + longitude: 80.771797, + latitudeDelta: 10.0, }, { - 'latitude': 12.862807, - 'longitudeDelta': 10.0, - 'name': 'Sudan', - 'longitude': 30.217636, - 'latitudeDelta': 10.0, + latitude: 12.862807, + longitudeDelta: 10.0, + name: 'Sudan', + longitude: 30.217636, + latitudeDelta: 10.0, }, { - 'latitude': 3.919305, - 'longitudeDelta': 10.0, - 'name': 'Suriname', - 'longitude': -56.027783, - 'latitudeDelta': 10.0, + latitude: 3.919305, + longitudeDelta: 10.0, + name: 'Suriname', + longitude: -56.027783, + latitudeDelta: 10.0, }, { - 'latitude': 77.553604, - 'longitudeDelta': 10.0, - 'name': 'Svalbard and Jan Mayen', - 'longitude': 23.670272, - 'latitudeDelta': 10.0, + latitude: 77.553604, + longitudeDelta: 10.0, + name: 'Svalbard and Jan Mayen', + longitude: 23.670272, + latitudeDelta: 10.0, }, { - 'latitude': -26.522503, - 'longitudeDelta': 10.0, - 'name': 'Swaziland', - 'longitude': 31.465866, - 'latitudeDelta': 10.0, + latitude: -26.522503, + longitudeDelta: 10.0, + name: 'Swaziland', + longitude: 31.465866, + latitudeDelta: 10.0, }, { - 'latitude': 60.128161, - 'longitudeDelta': 10.0, - 'name': 'Sweden', - 'longitude': 18.643501, - 'latitudeDelta': 10.0, + latitude: 60.128161, + longitudeDelta: 10.0, + name: 'Sweden', + longitude: 18.643501, + latitudeDelta: 10.0, }, { - 'latitude': 46.818188, - 'longitudeDelta': 10.0, - 'name': 'Switzerland', - 'longitude': 8.227512, - 'latitudeDelta': 10.0, + latitude: 46.818188, + longitudeDelta: 10.0, + name: 'Switzerland', + longitude: 8.227512, + latitudeDelta: 10.0, }, { - 'latitude': 34.802075, - 'longitudeDelta': 10.0, - 'name': 'Syria', - 'longitude': 38.996815, - 'latitudeDelta': 10.0, + latitude: 34.802075, + longitudeDelta: 10.0, + name: 'Syria', + longitude: 38.996815, + latitudeDelta: 10.0, }, { - 'latitude': 0.18636, - 'longitudeDelta': 10.0, - 'name': 'S\u00e3o Tom\u00e9 and Pr\u00edncipe', - 'longitude': 6.613081, - 'latitudeDelta': 10.0, + latitude: 0.18636, + longitudeDelta: 10.0, + name: 'S\u00e3o Tom\u00e9 and Pr\u00edncipe', + longitude: 6.613081, + latitudeDelta: 10.0, }, { - 'latitude': 23.69781, - 'longitudeDelta': 10.0, - 'name': 'Taiwan', - 'longitude': 120.960515, - 'latitudeDelta': 10.0, + latitude: 23.69781, + longitudeDelta: 10.0, + name: 'Taiwan', + longitude: 120.960515, + latitudeDelta: 10.0, }, { - 'latitude': 38.861034, - 'longitudeDelta': 10.0, - 'name': 'Tajikistan', - 'longitude': 71.276093, - 'latitudeDelta': 10.0, + latitude: 38.861034, + longitudeDelta: 10.0, + name: 'Tajikistan', + longitude: 71.276093, + latitudeDelta: 10.0, }, { - 'latitude': -6.369028, - 'longitudeDelta': 10.0, - 'name': 'Tanzania', - 'longitude': 34.888822, - 'latitudeDelta': 10.0, + latitude: -6.369028, + longitudeDelta: 10.0, + name: 'Tanzania', + longitude: 34.888822, + latitudeDelta: 10.0, }, { - 'latitude': 15.870032, - 'longitudeDelta': 10.0, - 'name': 'Thailand', - 'longitude': 100.992541, - 'latitudeDelta': 10.0, + latitude: 15.870032, + longitudeDelta: 10.0, + name: 'Thailand', + longitude: 100.992541, + latitudeDelta: 10.0, }, { - 'latitude': -8.874217, - 'longitudeDelta': 10.0, - 'name': 'Timor-Leste', - 'longitude': 125.727539, - 'latitudeDelta': 10.0, + latitude: -8.874217, + longitudeDelta: 10.0, + name: 'Timor-Leste', + longitude: 125.727539, + latitudeDelta: 10.0, }, { - 'latitude': 8.619543, - 'longitudeDelta': 10.0, - 'name': 'Togo', - 'longitude': 0.824782, - 'latitudeDelta': 10.0, + latitude: 8.619543, + longitudeDelta: 10.0, + name: 'Togo', + longitude: 0.824782, + latitudeDelta: 10.0, }, { - 'latitude': -8.967363, - 'longitudeDelta': 10.0, - 'name': 'Tokelau', - 'longitude': -171.855881, - 'latitudeDelta': 10.0, + latitude: -8.967363, + longitudeDelta: 10.0, + name: 'Tokelau', + longitude: -171.855881, + latitudeDelta: 10.0, }, { - 'latitude': -21.178986, - 'longitudeDelta': 10.0, - 'name': 'Tonga', - 'longitude': -175.198242, - 'latitudeDelta': 10.0, + latitude: -21.178986, + longitudeDelta: 10.0, + name: 'Tonga', + longitude: -175.198242, + latitudeDelta: 10.0, }, { - 'latitude': 10.691803, - 'longitudeDelta': 10.0, - 'name': 'Trinidad and Tobago', - 'longitude': -61.222503, - 'latitudeDelta': 10.0, + latitude: 10.691803, + longitudeDelta: 10.0, + name: 'Trinidad and Tobago', + longitude: -61.222503, + latitudeDelta: 10.0, }, { - 'latitude': 33.886917, - 'longitudeDelta': 10.0, - 'name': 'Tunisia', - 'longitude': 9.537499, - 'latitudeDelta': 10.0, + latitude: 33.886917, + longitudeDelta: 10.0, + name: 'Tunisia', + longitude: 9.537499, + latitudeDelta: 10.0, }, { - 'latitude': 38.963745, - 'longitudeDelta': 10.0, - 'name': 'Turkey', - 'longitude': 35.243322, - 'latitudeDelta': 10.0, + latitude: 38.963745, + longitudeDelta: 10.0, + name: 'Turkey', + longitude: 35.243322, + latitudeDelta: 10.0, }, { - 'latitude': 38.969719, - 'longitudeDelta': 10.0, - 'name': 'Turkmenistan', - 'longitude': 59.556278, - 'latitudeDelta': 10.0, + latitude: 38.969719, + longitudeDelta: 10.0, + name: 'Turkmenistan', + longitude: 59.556278, + latitudeDelta: 10.0, }, { - 'latitude': 21.694025, - 'longitudeDelta': 10.0, - 'name': 'Turks and Caicos Islands', - 'longitude': -71.797928, - 'latitudeDelta': 10.0, + latitude: 21.694025, + longitudeDelta: 10.0, + name: 'Turks and Caicos Islands', + longitude: -71.797928, + latitudeDelta: 10.0, }, { - 'latitude': -7.109535, - 'longitudeDelta': 10.0, - 'name': 'Tuvalu', - 'longitude': 177.64933, - 'latitudeDelta': 10.0, + latitude: -7.109535, + longitudeDelta: 10.0, + name: 'Tuvalu', + longitude: 177.64933, + latitudeDelta: 10.0, }, { - 'latitude': 18.335765, - 'longitudeDelta': 10.0, - 'name': 'U.S. Virgin Islands', - 'longitude': -64.896335, - 'latitudeDelta': 10.0, + latitude: 18.335765, + longitudeDelta: 10.0, + name: 'U.S. Virgin Islands', + longitude: -64.896335, + latitudeDelta: 10.0, }, { - 'latitude': 1.373333, - 'longitudeDelta': 10.0, - 'name': 'Uganda', - 'longitude': 32.290275, - 'latitudeDelta': 10.0, + latitude: 1.373333, + longitudeDelta: 10.0, + name: 'Uganda', + longitude: 32.290275, + latitudeDelta: 10.0, }, { - 'latitude': 48.379433, - 'longitudeDelta': 10.0, - 'name': 'Ukraine', - 'longitude': 31.16558, - 'latitudeDelta': 10.0, + latitude: 48.379433, + longitudeDelta: 10.0, + name: 'Ukraine', + longitude: 31.16558, + latitudeDelta: 10.0, }, { - 'latitude': 23.424076, - 'longitudeDelta': 10.0, - 'name': 'United Arab Emirates', - 'longitude': 53.847818, - 'latitudeDelta': 10.0, + latitude: 23.424076, + longitudeDelta: 10.0, + name: 'United Arab Emirates', + longitude: 53.847818, + latitudeDelta: 10.0, }, { - 'latitude': 55.378051, - 'longitudeDelta': 10.0, - 'name': 'United Kingdom', - 'longitude': -3.435973, - 'latitudeDelta': 10.0, + latitude: 55.378051, + longitudeDelta: 10.0, + name: 'United Kingdom', + longitude: -3.435973, + latitudeDelta: 10.0, }, { - 'latitude': 37.09024, - 'longitudeDelta': 10.0, - 'name': 'United States', - 'longitude': -95.712891, - 'latitudeDelta': 10.0, + latitude: 37.09024, + longitudeDelta: 10.0, + name: 'United States', + longitude: -95.712891, + latitudeDelta: 10.0, }, { - 'latitude': -32.522779, - 'longitudeDelta': 10.0, - 'name': 'Uruguay', - 'longitude': -55.765835, - 'latitudeDelta': 10.0, + latitude: -32.522779, + longitudeDelta: 10.0, + name: 'Uruguay', + longitude: -55.765835, + latitudeDelta: 10.0, }, { - 'latitude': 41.377491, - 'longitudeDelta': 10.0, - 'name': 'Uzbekistan', - 'longitude': 64.585262, - 'latitudeDelta': 10.0, + latitude: 41.377491, + longitudeDelta: 10.0, + name: 'Uzbekistan', + longitude: 64.585262, + latitudeDelta: 10.0, }, { - 'latitude': -15.376706, - 'longitudeDelta': 10.0, - 'name': 'Vanuatu', - 'longitude': 166.959158, - 'latitudeDelta': 10.0, + latitude: -15.376706, + longitudeDelta: 10.0, + name: 'Vanuatu', + longitude: 166.959158, + latitudeDelta: 10.0, }, { - 'latitude': 41.902916, - 'longitudeDelta': 10.0, - 'name': 'Vatican City', - 'longitude': 12.453389, - 'latitudeDelta': 10.0, + latitude: 41.902916, + longitudeDelta: 10.0, + name: 'Vatican City', + longitude: 12.453389, + latitudeDelta: 10.0, }, { - 'latitude': 6.42375, - 'longitudeDelta': 10.0, - 'name': 'Venezuela', - 'longitude': -66.58973, - 'latitudeDelta': 10.0, + latitude: 6.42375, + longitudeDelta: 10.0, + name: 'Venezuela', + longitude: -66.58973, + latitudeDelta: 10.0, }, { - 'latitude': 14.058324, - 'longitudeDelta': 10.0, - 'name': 'Vietnam', - 'longitude': 108.277199, - 'latitudeDelta': 10.0, + latitude: 14.058324, + longitudeDelta: 10.0, + name: 'Vietnam', + longitude: 108.277199, + latitudeDelta: 10.0, }, { - 'latitude': -13.768752, - 'longitudeDelta': 10.0, - 'name': 'Wallis and Futuna', - 'longitude': -177.156097, - 'latitudeDelta': 10.0, + latitude: -13.768752, + longitudeDelta: 10.0, + name: 'Wallis and Futuna', + longitude: -177.156097, + latitudeDelta: 10.0, }, { - 'latitude': 24.215527, - 'longitudeDelta': 10.0, - 'name': 'Western Sahara', - 'longitude': -12.885834, - 'latitudeDelta': 10.0, + latitude: 24.215527, + longitudeDelta: 10.0, + name: 'Western Sahara', + longitude: -12.885834, + latitudeDelta: 10.0, }, { - 'latitude': 15.552727, - 'longitudeDelta': 10.0, - 'name': 'Yemen', - 'longitude': 48.516388, - 'latitudeDelta': 10.0, + latitude: 15.552727, + longitudeDelta: 10.0, + name: 'Yemen', + longitude: 48.516388, + latitudeDelta: 10.0, }, { - 'latitude': -13.133897, - 'longitudeDelta': 10.0, - 'name': 'Zambia', - 'longitude': 27.849332, - 'latitudeDelta': 10.0, + latitude: -13.133897, + longitudeDelta: 10.0, + name: 'Zambia', + longitude: 27.849332, + latitudeDelta: 10.0, }, { - 'latitude': -19.015438, - 'longitudeDelta': 10.0, - 'name': 'Zimbabwe', - 'longitude': 29.154857, - 'latitudeDelta': 10.0, + latitude: -19.015438, + longitudeDelta: 10.0, + name: 'Zimbabwe', + longitude: 29.154857, + latitudeDelta: 10.0, }, ]; From 7aff2f4ba0850ab17c58b1f0f4f906e49c893aa9 Mon Sep 17 00:00:00 2001 From: Chris Knepper Date: Thu, 25 Aug 2016 17:01:27 -0400 Subject: [PATCH 0013/1148] -Support using react-native in peer node_modules folder instead of outdated version from Maven -Update argument signature of RegionChangeEvent constructor to current react-native signature -Temporarily define maven url override in both build.gradle files until we restructure this to remove the lib folder --- android/build.gradle | 6 +++++- android/lib/build.gradle | 13 ++++++++++++- .../android/react/maps/RegionChangeEvent.java | 2 +- 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/android/build.gradle b/android/build.gradle index bfa064b43..eae2dc465 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -11,7 +11,11 @@ buildscript { allprojects { repositories { + mavenLocal() jcenter() - maven { url "$projectDir/../../node_modules/react-native/android" } + maven { + // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm + url "$projectDir/../../react-native/android" + } } } \ No newline at end of file diff --git a/android/lib/build.gradle b/android/lib/build.gradle index 1a4908efa..72e074c44 100644 --- a/android/lib/build.gradle +++ b/android/lib/build.gradle @@ -15,8 +15,19 @@ android { } } +allprojects { + repositories { + mavenLocal() + jcenter() + maven { + // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm + url "$projectDir/../../../react-native/android" + } + } +} + dependencies { - compile 'com.facebook.react:react-native:+' + compile 'com.facebook.react:react-native:0.32.0' compile "com.google.android.gms:play-services-base:8.4.0" compile 'com.google.android.gms:play-services-maps:8.4.0' } diff --git a/android/lib/src/main/java/com/airbnb/android/react/maps/RegionChangeEvent.java b/android/lib/src/main/java/com/airbnb/android/react/maps/RegionChangeEvent.java index 4f3194160..28a3b322b 100644 --- a/android/lib/src/main/java/com/airbnb/android/react/maps/RegionChangeEvent.java +++ b/android/lib/src/main/java/com/airbnb/android/react/maps/RegionChangeEvent.java @@ -13,7 +13,7 @@ public class RegionChangeEvent extends Event { private final boolean continuous; public RegionChangeEvent(int id, LatLngBounds bounds, LatLng center, boolean continuous) { - super(id, System.currentTimeMillis()); + super(id); this.bounds = bounds; this.center = center; this.continuous = continuous; From 6d6829253d6c8129aad9d55d048aa57700724232 Mon Sep 17 00:00:00 2001 From: Chris Knepper Date: Thu, 25 Aug 2016 21:19:20 -0400 Subject: [PATCH 0014/1148] -Restructure plugin to allow for easier inclusion from source in react-native projects (for Android) --- android/build.gradle | 34 +- android/gradle-maven-push.gradle | 114 +++ android/gradle.properties | 33 +- android/src/main/AndroidManifest.xml | 6 + .../android/react/maps/AirMapCallout.java | 23 + .../react/maps/AirMapCalloutManager.java | 59 ++ .../android/react/maps/AirMapCircle.java | 100 +++ .../react/maps/AirMapCircleManager.java | 72 ++ .../android/react/maps/AirMapFeature.java | 18 + .../android/react/maps/AirMapManager.java | 290 +++++++ .../android/react/maps/AirMapMarker.java | 410 ++++++++++ .../react/maps/AirMapMarkerManager.java | 196 +++++ .../android/react/maps/AirMapPolygon.java | 111 +++ .../react/maps/AirMapPolygonManager.java | 70 ++ .../android/react/maps/AirMapPolyline.java | 101 +++ .../react/maps/AirMapPolylineManager.java | 65 ++ .../airbnb/android/react/maps/AirMapView.java | 744 ++++++++++++++++++ .../android/react/maps/LatLngBoundsUtils.java | 47 ++ .../android/react/maps/MapsPackage.java | 46 ++ .../android/react/maps/RegionChangeEvent.java | 47 ++ .../react/maps/SizeReportingShadowNode.java | 31 + 21 files changed, 2599 insertions(+), 18 deletions(-) create mode 100644 android/gradle-maven-push.gradle create mode 100644 android/src/main/AndroidManifest.xml create mode 100644 android/src/main/java/com/airbnb/android/react/maps/AirMapCallout.java create mode 100644 android/src/main/java/com/airbnb/android/react/maps/AirMapCalloutManager.java create mode 100644 android/src/main/java/com/airbnb/android/react/maps/AirMapCircle.java create mode 100644 android/src/main/java/com/airbnb/android/react/maps/AirMapCircleManager.java create mode 100644 android/src/main/java/com/airbnb/android/react/maps/AirMapFeature.java create mode 100644 android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java create mode 100644 android/src/main/java/com/airbnb/android/react/maps/AirMapMarker.java create mode 100644 android/src/main/java/com/airbnb/android/react/maps/AirMapMarkerManager.java create mode 100644 android/src/main/java/com/airbnb/android/react/maps/AirMapPolygon.java create mode 100644 android/src/main/java/com/airbnb/android/react/maps/AirMapPolygonManager.java create mode 100644 android/src/main/java/com/airbnb/android/react/maps/AirMapPolyline.java create mode 100644 android/src/main/java/com/airbnb/android/react/maps/AirMapPolylineManager.java create mode 100644 android/src/main/java/com/airbnb/android/react/maps/AirMapView.java create mode 100644 android/src/main/java/com/airbnb/android/react/maps/LatLngBoundsUtils.java create mode 100644 android/src/main/java/com/airbnb/android/react/maps/MapsPackage.java create mode 100644 android/src/main/java/com/airbnb/android/react/maps/RegionChangeEvent.java create mode 100644 android/src/main/java/com/airbnb/android/react/maps/SizeReportingShadowNode.java diff --git a/android/build.gradle b/android/build.gradle index eae2dc465..f2e0a1f43 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -1,8 +1,15 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. +apply plugin: 'com.android.library' +apply from: 'gradle-maven-push.gradle' + buildscript { repositories { - jcenter() + mavenLocal() + jcenter() + maven { + url "$projectDir/../../../react-native/android" + } } dependencies { classpath 'com.android.tools.build:gradle:2.1.0' @@ -14,8 +21,29 @@ allprojects { mavenLocal() jcenter() maven { - // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm + // Refer to the local install of react-native in the node_modules folder + // react-native should be installed since it's a peer dependency url "$projectDir/../../react-native/android" } } -} \ No newline at end of file +} + +android { + compileSdkVersion 23 + buildToolsVersion "23.0.3" + + defaultConfig { + minSdkVersion 16 + targetSdkVersion 23 + } + + lintOptions { + disable 'InvalidPackage' + } +} + +dependencies { + compile 'com.facebook.react:react-native:0.32.0' + compile "com.google.android.gms:play-services-base:8.4.0" + compile 'com.google.android.gms:play-services-maps:8.4.0' +} diff --git a/android/gradle-maven-push.gradle b/android/gradle-maven-push.gradle new file mode 100644 index 000000000..84bf6163c --- /dev/null +++ b/android/gradle-maven-push.gradle @@ -0,0 +1,114 @@ +/* + * Copyright 2013 Chris Banes + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +apply plugin: 'maven' +apply plugin: 'signing' + +def isReleaseBuild() { + return VERSION_NAME.contains("SNAPSHOT") == false +} + +def getReleaseRepositoryUrl() { + return hasProperty('RELEASE_REPOSITORY_URL') ? RELEASE_REPOSITORY_URL + : "https://oss.sonatype.org/service/local/staging/deploy/maven2/" +} + +def getSnapshotRepositoryUrl() { + return hasProperty('SNAPSHOT_REPOSITORY_URL') ? SNAPSHOT_REPOSITORY_URL + : "https://oss.sonatype.org/content/repositories/snapshots/" +} + +def getRepositoryUsername() { + return hasProperty('NEXUS_USERNAME') ? NEXUS_USERNAME : "" +} + +def getRepositoryPassword() { + return hasProperty('NEXUS_PASSWORD') ? NEXUS_PASSWORD : "" +} + +afterEvaluate { project -> + uploadArchives { + repositories { + mavenDeployer { + beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) } + + pom.groupId = GROUP + pom.artifactId = POM_ARTIFACT_ID + pom.version = VERSION_NAME + + repository(url: getReleaseRepositoryUrl()) { + authentication(userName: getRepositoryUsername(), password: getRepositoryPassword()) + } + snapshotRepository(url: getSnapshotRepositoryUrl()) { + authentication(userName: getRepositoryUsername(), password: getRepositoryPassword()) + } + + pom.project { + name POM_NAME + packaging POM_PACKAGING + description POM_DESCRIPTION + url POM_URL + + scm { + url POM_SCM_URL + connection POM_SCM_CONNECTION + developerConnection POM_SCM_DEV_CONNECTION + } + + licenses { + license { + name POM_LICENSE_NAME + url POM_LICENSE_URL + distribution POM_LICENSE_DIST + } + } + + developers { + developer { + id POM_DEVELOPER_ID + name POM_DEVELOPER_NAME + } + } + } + } + } + } + + signing { + required { isReleaseBuild() && gradle.taskGraph.hasTask("uploadArchives") } + sign configurations.archives + } + + task androidJavadocs(type: Javadoc) { + source = android.sourceSets.main.java.srcDirs + classpath += project.files(android.getBootClasspath().join(File.pathSeparator)) + } + + task androidJavadocsJar(type: Jar, dependsOn: androidJavadocs) { + classifier = 'javadoc' + from androidJavadocs.destinationDir + } + + task androidSourcesJar(type: Jar) { + classifier = 'sources' + from android.sourceSets.main.java.sourceFiles + } + + artifacts { + archives androidSourcesJar + archives androidJavadocsJar + } +} \ No newline at end of file diff --git a/android/gradle.properties b/android/gradle.properties index 5533295e2..c86911511 100644 --- a/android/gradle.properties +++ b/android/gradle.properties @@ -1,15 +1,18 @@ -## Project-wide Gradle settings. -# -# For more details on how to configure your build environment visit -# http://www.gradle.org/docs/current/userguide/build_environment.html -# -# Specifies the JVM arguments used for the daemon process. -# The setting is particularly useful for tweaking memory settings. -# Default value: -Xmx10248m -XX:MaxPermSize=256m -# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 -# -# When configured, Gradle will run in incubating parallel mode. -# This option should only be used with decoupled projects. More details, visit -# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects -# org.gradle.parallel=true -#Thu May 12 17:26:12 PDT 2016 +VERSION_CODE=2 +VERSION_NAME=0.7.1 +GROUP=com.airbnb.android + +POM_DESCRIPTION=React Native Map view component for Android +POM_URL=https://github.com/lelandrichardson/react-native-maps/tree/new-scv +POM_SCM_URL=https://github.com/lelandrichardson/react-native-maps/tree/new-scv +POM_SCM_CONNECTION=scm:git@github.com:lelandrichardson/react-native-maps.git +POM_SCM_DEV_CONNECTION=scm:git@github.com:lelandrichardson/react-native-maps.git +POM_LICENSE_NAME=MIT +POM_LICENSE_URL=https://github.com/lelandrichardson/react-native-maps/blob/master/LICENSE +POM_LICENSE_DIST=repo +POM_DEVELOPER_ID=lelandrichardson +POM_DEVELOPER_NAME=Leland Richardson + +POM_NAME=ReactNative Maps library +POM_ARTIFACT_ID=react-native-maps +POM_PACKAGING=aar diff --git a/android/src/main/AndroidManifest.xml b/android/src/main/AndroidManifest.xml new file mode 100644 index 000000000..e07e0af89 --- /dev/null +++ b/android/src/main/AndroidManifest.xml @@ -0,0 +1,6 @@ + + + + + diff --git a/android/src/main/java/com/airbnb/android/react/maps/AirMapCallout.java b/android/src/main/java/com/airbnb/android/react/maps/AirMapCallout.java new file mode 100644 index 000000000..c434c9c12 --- /dev/null +++ b/android/src/main/java/com/airbnb/android/react/maps/AirMapCallout.java @@ -0,0 +1,23 @@ +package com.airbnb.android.react.maps; + +import android.content.Context; + +import com.facebook.react.views.view.ReactViewGroup; + +public class AirMapCallout extends ReactViewGroup { + private boolean tooltip = false; + public int width; + public int height; + + public AirMapCallout(Context context) { + super(context); + } + + public void setTooltip(boolean tooltip) { + this.tooltip = tooltip; + } + + public boolean getTooltip() { + return this.tooltip; + } +} diff --git a/android/src/main/java/com/airbnb/android/react/maps/AirMapCalloutManager.java b/android/src/main/java/com/airbnb/android/react/maps/AirMapCalloutManager.java new file mode 100644 index 000000000..5c21fadd3 --- /dev/null +++ b/android/src/main/java/com/airbnb/android/react/maps/AirMapCalloutManager.java @@ -0,0 +1,59 @@ +package com.airbnb.android.react.maps; + +import com.facebook.react.common.MapBuilder; +import com.facebook.react.uimanager.LayoutShadowNode; +import com.facebook.react.uimanager.ThemedReactContext; +import com.facebook.react.uimanager.ViewGroupManager; +import com.facebook.react.uimanager.annotations.ReactProp; + +import java.util.Map; + +import javax.annotation.Nullable; + +public class AirMapCalloutManager extends ViewGroupManager { + + @Override + public String getName() { + return "AIRMapCallout"; + } + + @Override + public AirMapCallout createViewInstance(ThemedReactContext context) { + return new AirMapCallout(context); + } + + @ReactProp(name = "tooltip", defaultBoolean = false) + public void setTooltip(AirMapCallout view, boolean tooltip) { + view.setTooltip(tooltip); + } + + @Override + public + @Nullable + Map getExportedCustomDirectEventTypeConstants() { + return MapBuilder.of( + "onPress", MapBuilder.of("registrationName", "onPress") + ); + } + + @Override + public LayoutShadowNode createShadowNodeInstance() { + // we use a custom shadow node that emits the width/height of the view + // after layout with the updateExtraData method. Without this, we can't generate + // a bitmap of the appropriate width/height of the rendered view. + return new SizeReportingShadowNode(); + } + + @Override + public void updateExtraData(AirMapCallout view, Object extraData) { + // This method is called from the shadow node with the width/height of the rendered + // marker view. + //noinspection unchecked + Map data = (Map) extraData; + float width = data.get("width"); + float height = data.get("height"); + view.width = (int) width; + view.height = (int) height; + } + +} diff --git a/android/src/main/java/com/airbnb/android/react/maps/AirMapCircle.java b/android/src/main/java/com/airbnb/android/react/maps/AirMapCircle.java new file mode 100644 index 000000000..e428b04f6 --- /dev/null +++ b/android/src/main/java/com/airbnb/android/react/maps/AirMapCircle.java @@ -0,0 +1,100 @@ +package com.airbnb.android.react.maps; + +import android.content.Context; + +import com.google.android.gms.maps.GoogleMap; +import com.google.android.gms.maps.model.Circle; +import com.google.android.gms.maps.model.CircleOptions; +import com.google.android.gms.maps.model.LatLng; + +public class AirMapCircle extends AirMapFeature { + + private CircleOptions circleOptions; + private Circle circle; + + private LatLng center; + private double radius; + private int strokeColor; + private int fillColor; + private float strokeWidth; + private float zIndex; + + public AirMapCircle(Context context) { + super(context); + } + + public void setCenter(LatLng center) { + this.center = center; + if (circle != null) { + circle.setCenter(this.center); + } + } + + public void setRadius(double radius) { + this.radius = radius; + if (circle != null) { + circle.setRadius(this.radius); + } + } + + public void setFillColor(int color) { + this.fillColor = color; + if (circle != null) { + circle.setFillColor(color); + } + } + + public void setStrokeColor(int color) { + this.strokeColor = color; + if (circle != null) { + circle.setStrokeColor(color); + } + } + + public void setStrokeWidth(float width) { + this.strokeWidth = width; + if (circle != null) { + circle.setStrokeWidth(width); + } + } + + public void setZIndex(float zIndex) { + this.zIndex = zIndex; + if (circle != null) { + circle.setZIndex(zIndex); + } + } + + public CircleOptions getCircleOptions() { + if (circleOptions == null) { + circleOptions = createCircleOptions(); + } + return circleOptions; + } + + private CircleOptions createCircleOptions() { + CircleOptions options = new CircleOptions(); + options.center(center); + options.radius(radius); + options.fillColor(fillColor); + options.strokeColor(strokeColor); + options.strokeWidth(strokeWidth); + options.zIndex(zIndex); + return options; + } + + @Override + public Object getFeature() { + return circle; + } + + @Override + public void addToMap(GoogleMap map) { + circle = map.addCircle(getCircleOptions()); + } + + @Override + public void removeFromMap(GoogleMap map) { + circle.remove(); + } +} diff --git a/android/src/main/java/com/airbnb/android/react/maps/AirMapCircleManager.java b/android/src/main/java/com/airbnb/android/react/maps/AirMapCircleManager.java new file mode 100644 index 000000000..c0eaf8f14 --- /dev/null +++ b/android/src/main/java/com/airbnb/android/react/maps/AirMapCircleManager.java @@ -0,0 +1,72 @@ +package com.airbnb.android.react.maps; + +import android.content.Context; +import android.graphics.Color; +import android.os.Build; +import android.util.DisplayMetrics; +import android.view.WindowManager; + +import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.bridge.ReadableMap; +import com.facebook.react.uimanager.ThemedReactContext; +import com.facebook.react.uimanager.ViewGroupManager; +import com.facebook.react.uimanager.annotations.ReactProp; +import com.google.android.gms.maps.model.LatLng; + +public class AirMapCircleManager extends ViewGroupManager { + private final DisplayMetrics metrics; + + public AirMapCircleManager(ReactApplicationContext reactContext) { + super(); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { + metrics = new DisplayMetrics(); + ((WindowManager) reactContext.getSystemService(Context.WINDOW_SERVICE)) + .getDefaultDisplay() + .getRealMetrics(metrics); + } else { + metrics = reactContext.getResources().getDisplayMetrics(); + } + } + + @Override + public String getName() { + return "AIRMapCircle"; + } + + @Override + public AirMapCircle createViewInstance(ThemedReactContext context) { + return new AirMapCircle(context); + } + + @ReactProp(name = "center") + public void setCenter(AirMapCircle view, ReadableMap center) { + view.setCenter(new LatLng(center.getDouble("latitude"), center.getDouble("longitude"))); + } + + @ReactProp(name = "radius", defaultDouble = 0) + public void setRadius(AirMapCircle view, double radius) { + view.setRadius(radius); + } + + @ReactProp(name = "strokeWidth", defaultFloat = 1f) + public void setStrokeWidth(AirMapCircle view, float widthInPoints) { + float widthInScreenPx = metrics.density * widthInPoints; // done for parity with iOS + view.setStrokeWidth(widthInScreenPx); + } + + @ReactProp(name = "fillColor", defaultInt = Color.RED, customType = "Color") + public void setFillColor(AirMapCircle view, int color) { + view.setFillColor(color); + } + + @ReactProp(name = "strokeColor", defaultInt = Color.RED, customType = "Color") + public void setStrokeColor(AirMapCircle view, int color) { + view.setStrokeColor(color); + } + + @ReactProp(name = "zIndex", defaultFloat = 1.0f) + public void setZIndex(AirMapCircle view, float zIndex) { + view.setZIndex(zIndex); + } + +} diff --git a/android/src/main/java/com/airbnb/android/react/maps/AirMapFeature.java b/android/src/main/java/com/airbnb/android/react/maps/AirMapFeature.java new file mode 100644 index 000000000..1c15ade5f --- /dev/null +++ b/android/src/main/java/com/airbnb/android/react/maps/AirMapFeature.java @@ -0,0 +1,18 @@ +package com.airbnb.android.react.maps; + +import android.content.Context; + +import com.facebook.react.views.view.ReactViewGroup; +import com.google.android.gms.maps.GoogleMap; + +public abstract class AirMapFeature extends ReactViewGroup { + public AirMapFeature(Context context) { + super(context); + } + + public abstract void addToMap(GoogleMap map); + + public abstract void removeFromMap(GoogleMap map); + + public abstract Object getFeature(); +} diff --git a/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java b/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java new file mode 100644 index 000000000..5ca02097b --- /dev/null +++ b/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java @@ -0,0 +1,290 @@ +package com.airbnb.android.react.maps; + +import android.view.View; +import android.content.Context; + +import com.facebook.react.bridge.Arguments; +import com.facebook.react.bridge.ReactContext; +import com.facebook.react.bridge.ReadableArray; +import com.facebook.react.bridge.ReadableMap; +import com.facebook.react.bridge.WritableMap; +import com.facebook.react.common.MapBuilder; +import com.facebook.react.modules.core.DeviceEventManagerModule; +import com.facebook.react.uimanager.LayoutShadowNode; +import com.facebook.react.uimanager.ThemedReactContext; +import com.facebook.react.uimanager.ViewGroupManager; +import com.facebook.react.uimanager.annotations.ReactProp; +import com.facebook.react.uimanager.events.RCTEventEmitter; +import com.google.android.gms.maps.GoogleMap; +import com.google.android.gms.maps.MapsInitializer; +import com.google.android.gms.maps.model.LatLng; +import com.google.android.gms.maps.model.LatLngBounds; + +import java.util.Map; + +import javax.annotation.Nullable; + +public class AirMapManager extends ViewGroupManager { + + private static final String REACT_CLASS = "AIRMap"; + private static final int ANIMATE_TO_REGION = 1; + private static final int ANIMATE_TO_COORDINATE = 2; + private static final int FIT_TO_ELEMENTS = 3; + private static final int FIT_TO_SUPPLIED_MARKERS = 4; + + private final Map MAP_TYPES = MapBuilder.of( + "standard", GoogleMap.MAP_TYPE_NORMAL, + "satellite", GoogleMap.MAP_TYPE_SATELLITE, + "hybrid", GoogleMap.MAP_TYPE_HYBRID, + "terrain", GoogleMap.MAP_TYPE_TERRAIN + ); + + private ReactContext reactContext; + + private final Context appContext; + + public AirMapManager(Context context) { + this.appContext = context; + } + + @Override + public String getName() { + return REACT_CLASS; + } + + @Override + protected AirMapView createViewInstance(ThemedReactContext context) { + reactContext = context; + + try { + MapsInitializer.initialize(this.appContext); + } catch (RuntimeException e) { + e.printStackTrace(); + emitMapError("Map initialize error", "map_init_error"); + } + + return new AirMapView(context, this.appContext, this); + } + + @Override + public void onDropViewInstance(AirMapView view) { + view.doDestroy(); + super.onDropViewInstance(view); + } + + private void emitMapError(String message, String type) { + WritableMap error = Arguments.createMap(); + error.putString("message", message); + error.putString("type", type); + + reactContext + .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class) + .emit("onError", error); + } + + @ReactProp(name = "region") + public void setRegion(AirMapView view, ReadableMap region) { + view.setRegion(region); + } + + @ReactProp(name = "mapType") + public void setMapType(AirMapView view, @Nullable String mapType) { + int typeId = MAP_TYPES.get(mapType); + view.map.setMapType(typeId); + } + + @ReactProp(name = "showsUserLocation", defaultBoolean = false) + public void setShowsUserLocation(AirMapView view, boolean showUserLocation) { + view.setShowsUserLocation(showUserLocation); + } + + @ReactProp(name = "showsMyLocationButton", defaultBoolean = true) + public void setShowsMyLocationButton(AirMapView view, boolean showMyLocationButton) { + view.setShowsMyLocationButton(showMyLocationButton); + } + + @ReactProp(name = "toolbarEnabled", defaultBoolean = true) + public void setToolbarEnabled(AirMapView view, boolean toolbarEnabled) { + view.setToolbarEnabled(toolbarEnabled); + } + + // This is a private prop to improve performance of panDrag by disabling it when the callback is not set + @ReactProp(name = "handlePanDrag", defaultBoolean = false) + public void setHandlePanDrag(AirMapView view, boolean handlePanDrag) { + view.setHandlePanDrag(handlePanDrag); + } + + @ReactProp(name = "showsTraffic", defaultBoolean = false) + public void setShowTraffic(AirMapView view, boolean showTraffic) { + view.map.setTrafficEnabled(showTraffic); + } + + @ReactProp(name = "showsBuildings", defaultBoolean = false) + public void setShowBuildings(AirMapView view, boolean showBuildings) { + view.map.setBuildingsEnabled(showBuildings); + } + + @ReactProp(name = "showsIndoors", defaultBoolean = false) + public void setShowIndoors(AirMapView view, boolean showIndoors) { + view.map.setIndoorEnabled(showIndoors); + } + + @ReactProp(name = "showsCompass", defaultBoolean = false) + public void setShowsCompass(AirMapView view, boolean showsCompass) { + view.map.getUiSettings().setCompassEnabled(showsCompass); + } + + @ReactProp(name = "scrollEnabled", defaultBoolean = false) + public void setScrollEnabled(AirMapView view, boolean scrollEnabled) { + view.map.getUiSettings().setScrollGesturesEnabled(scrollEnabled); + } + + @ReactProp(name = "zoomEnabled", defaultBoolean = false) + public void setZoomEnabled(AirMapView view, boolean zoomEnabled) { + view.map.getUiSettings().setZoomGesturesEnabled(zoomEnabled); + } + + @ReactProp(name = "rotateEnabled", defaultBoolean = false) + public void setRotateEnabled(AirMapView view, boolean rotateEnabled) { + view.map.getUiSettings().setRotateGesturesEnabled(rotateEnabled); + } + + @ReactProp(name="cacheEnabled", defaultBoolean = false) + public void setCacheEnabled(AirMapView view, boolean cacheEnabled) { + view.setCacheEnabled(cacheEnabled); + } + + @ReactProp(name="loadingEnabled", defaultBoolean = false) + public void setLoadingEnabled(AirMapView view, boolean loadingEnabled) { + view.enableMapLoading(loadingEnabled); + } + + @ReactProp(name="loadingBackgroundColor", customType="Color") + public void setLoadingBackgroundColor(AirMapView view, @Nullable Integer loadingBackgroundColor) { + view.setLoadingBackgroundColor(loadingBackgroundColor); + } + + @ReactProp(name="loadingIndicatorColor", customType="Color") + public void setLoadingIndicatorColor(AirMapView view, @Nullable Integer loadingIndicatorColor) { + view.setLoadingIndicatorColor(loadingIndicatorColor); + } + + @ReactProp(name = "pitchEnabled", defaultBoolean = false) + public void setPitchEnabled(AirMapView view, boolean pitchEnabled) { + view.map.getUiSettings().setTiltGesturesEnabled(pitchEnabled); + } + + @Override + public void receiveCommand(AirMapView view, int commandId, @Nullable ReadableArray args) { + Integer duration; + Double lat; + Double lng; + Double lngDelta; + Double latDelta; + ReadableMap region; + + switch (commandId) { + case ANIMATE_TO_REGION: + region = args.getMap(0); + duration = args.getInt(1); + lng = region.getDouble("longitude"); + lat = region.getDouble("latitude"); + lngDelta = region.getDouble("longitudeDelta"); + latDelta = region.getDouble("latitudeDelta"); + LatLngBounds bounds = new LatLngBounds( + new LatLng(lat - latDelta / 2, lng - lngDelta / 2), // southwest + new LatLng(lat + latDelta / 2, lng + lngDelta / 2) // northeast + ); + view.animateToRegion(bounds, duration); + break; + + case ANIMATE_TO_COORDINATE: + region = args.getMap(0); + duration = args.getInt(1); + lng = region.getDouble("longitude"); + lat = region.getDouble("latitude"); + view.animateToCoordinate(new LatLng(lat, lng), duration); + break; + + case FIT_TO_ELEMENTS: + view.fitToElements(args.getBoolean(0)); + break; + + case FIT_TO_SUPPLIED_MARKERS: + view.fitToSuppliedMarkers(args.getArray(0), args.getBoolean(1)); + break; + } + } + + @Override + @Nullable + public Map getExportedCustomDirectEventTypeConstants() { + Map> map = MapBuilder.of( + "onMapReady", MapBuilder.of("registrationName", "onMapReady"), + "onPress", MapBuilder.of("registrationName", "onPress"), + "onLongPress", MapBuilder.of("registrationName", "onLongPress"), + "onMarkerPress", MapBuilder.of("registrationName", "onMarkerPress"), + "onMarkerSelect", MapBuilder.of("registrationName", "onMarkerSelect"), + "onMarkerDeselect", MapBuilder.of("registrationName", "onMarkerDeselect"), + "onCalloutPress", MapBuilder.of("registrationName", "onCalloutPress") + ); + + map.putAll(MapBuilder.of( + "onMarkerDragStart", MapBuilder.of("registrationName", "onMarkerDragStart"), + "onMarkerDrag", MapBuilder.of("registrationName", "onMarkerDrag"), + "onMarkerDragEnd", MapBuilder.of("registrationName", "onMarkerDragEnd"), + "onPanDrag", MapBuilder.of("registrationName", "onPanDrag") + )); + + return map; + } + + @Override + @Nullable + public Map getCommandsMap() { + return MapBuilder.of( + "animateToRegion", ANIMATE_TO_REGION, + "animateToCoordinate", ANIMATE_TO_COORDINATE, + "fitToElements", FIT_TO_ELEMENTS, + "fitToSuppliedMarkers", FIT_TO_SUPPLIED_MARKERS + ); + } + + @Override + public LayoutShadowNode createShadowNodeInstance() { + // A custom shadow node is needed in order to pass back the width/height of the map to the + // view manager so that it can start applying camera moves with bounds. + return new SizeReportingShadowNode(); + } + + @Override + public void addView(AirMapView parent, View child, int index) { + parent.addFeature(child, index); + } + + @Override + public int getChildCount(AirMapView view) { + return view.getFeatureCount(); + } + + @Override + public View getChildAt(AirMapView view, int index) { + return view.getFeatureAt(index); + } + + @Override + public void removeViewAt(AirMapView parent, int index) { + parent.removeFeatureAt(index); + } + + @Override + public void updateExtraData(AirMapView view, Object extraData) { + view.updateExtraData(extraData); + } + + void pushEvent(View view, String name, WritableMap data) { + reactContext.getJSModule(RCTEventEmitter.class) + .receiveEvent(view.getId(), name, data); + } + +} diff --git a/android/src/main/java/com/airbnb/android/react/maps/AirMapMarker.java b/android/src/main/java/com/airbnb/android/react/maps/AirMapMarker.java new file mode 100644 index 000000000..8623812c2 --- /dev/null +++ b/android/src/main/java/com/airbnb/android/react/maps/AirMapMarker.java @@ -0,0 +1,410 @@ +package com.airbnb.android.react.maps; + +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.drawable.Animatable; +import android.net.Uri; +import android.view.View; +import android.widget.LinearLayout; + +import com.facebook.common.references.CloseableReference; +import com.facebook.datasource.DataSource; +import com.facebook.drawee.backends.pipeline.Fresco; +import com.facebook.drawee.controller.BaseControllerListener; +import com.facebook.drawee.controller.ControllerListener; +import com.facebook.drawee.drawable.ScalingUtils; +import com.facebook.drawee.generic.GenericDraweeHierarchy; +import com.facebook.drawee.generic.GenericDraweeHierarchyBuilder; +import com.facebook.drawee.interfaces.DraweeController; +import com.facebook.drawee.view.DraweeHolder; +import com.facebook.imagepipeline.core.ImagePipeline; +import com.facebook.imagepipeline.image.CloseableImage; +import com.facebook.imagepipeline.image.CloseableStaticBitmap; +import com.facebook.imagepipeline.image.ImageInfo; +import com.facebook.imagepipeline.request.ImageRequest; +import com.facebook.imagepipeline.request.ImageRequestBuilder; +import com.facebook.react.bridge.ReadableMap; +import com.google.android.gms.maps.GoogleMap; +import com.google.android.gms.maps.model.BitmapDescriptor; +import com.google.android.gms.maps.model.BitmapDescriptorFactory; +import com.google.android.gms.maps.model.LatLng; +import com.google.android.gms.maps.model.Marker; +import com.google.android.gms.maps.model.MarkerOptions; + +import javax.annotation.Nullable; + +public class AirMapMarker extends AirMapFeature { + + private MarkerOptions markerOptions; + private Marker marker; + private int width; + private int height; + private String identifier; + + private LatLng position; + private String title; + private String snippet; + + private boolean anchorIsSet; + private float anchorX; + private float anchorY; + + private AirMapCallout calloutView; + private View wrappedCalloutView; + private final Context context; + + private float markerHue = 0.0f; // should be between 0 and 360 + private BitmapDescriptor iconBitmapDescriptor; + private Bitmap iconBitmap; + + private float rotation = 0.0f; + private boolean flat = false; + private boolean draggable = false; + + private float calloutAnchorX; + private float calloutAnchorY; + private boolean calloutAnchorIsSet; + + private boolean hasCustomMarkerView = false; + + private final DraweeHolder logoHolder; + private DataSource> dataSource; + private final ControllerListener mLogoControllerListener = + new BaseControllerListener() { + @Override + public void onFinalImageSet( + String id, + @Nullable final ImageInfo imageInfo, + @Nullable Animatable animatable) { + CloseableReference imageReference = null; + try { + imageReference = dataSource.getResult(); + if (imageReference != null) { + CloseableImage image = imageReference.get(); + if (image != null && image instanceof CloseableStaticBitmap) { + CloseableStaticBitmap closeableStaticBitmap = (CloseableStaticBitmap) image; + Bitmap bitmap = closeableStaticBitmap.getUnderlyingBitmap(); + if (bitmap != null) { + bitmap = bitmap.copy(Bitmap.Config.ARGB_8888, true); + iconBitmap = bitmap; + iconBitmapDescriptor = BitmapDescriptorFactory.fromBitmap(bitmap); + } + } + } + } finally { + dataSource.close(); + if (imageReference != null) { + CloseableReference.closeSafely(imageReference); + } + } + update(); + } + }; + + public AirMapMarker(Context context) { + super(context); + this.context = context; + logoHolder = DraweeHolder.create(createDraweeHierarchy(), context); + logoHolder.onAttach(); + } + + private GenericDraweeHierarchy createDraweeHierarchy() { + return new GenericDraweeHierarchyBuilder(getResources()) + .setActualImageScaleType(ScalingUtils.ScaleType.FIT_CENTER) + .setFadeDuration(0) + .build(); + } + + public void setCoordinate(ReadableMap coordinate) { + position = new LatLng(coordinate.getDouble("latitude"), coordinate.getDouble("longitude")); + if (marker != null) { + marker.setPosition(position); + } + update(); + } + + public void setIdentifier(String identifier) { + this.identifier = identifier; + update(); + } + + public String getIdentifier() { + return this.identifier; + } + + public void setTitle(String title) { + this.title = title; + if (marker != null) { + marker.setTitle(title); + } + update(); + } + + public void setSnippet(String snippet) { + this.snippet = snippet; + if (marker != null) { + marker.setSnippet(snippet); + } + update(); + } + + public void setRotation(float rotation) { + this.rotation = rotation; + if (marker != null) { + marker.setRotation(rotation); + } + update(); + } + + public void setFlat(boolean flat) { + this.flat = flat; + if (marker != null) { + marker.setFlat(flat); + } + update(); + } + + public void setDraggable(boolean draggable) { + this.draggable = draggable; + if (marker != null) { + marker.setDraggable(draggable); + } + update(); + } + + public void setMarkerHue(float markerHue) { + this.markerHue = markerHue; + update(); + } + + public void setAnchor(double x, double y) { + anchorIsSet = true; + anchorX = (float) x; + anchorY = (float) y; + if (marker != null) { + marker.setAnchor(anchorX, anchorY); + } + update(); + } + + public void setCalloutAnchor(double x, double y) { + calloutAnchorIsSet = true; + calloutAnchorX = (float) x; + calloutAnchorY = (float) y; + if (marker != null) { + marker.setInfoWindowAnchor(calloutAnchorX, calloutAnchorY); + } + update(); + } + + public void setImage(String uri) { + if (uri == null) { + iconBitmapDescriptor = null; + update(); + } else if (uri.startsWith("http://") || uri.startsWith("https://") || + uri.startsWith("file://")) { + ImageRequest imageRequest = ImageRequestBuilder + .newBuilderWithSource(Uri.parse(uri)) + .build(); + + ImagePipeline imagePipeline = Fresco.getImagePipeline(); + dataSource = imagePipeline.fetchDecodedImage(imageRequest, this); + DraweeController controller = Fresco.newDraweeControllerBuilder() + .setImageRequest(imageRequest) + .setControllerListener(mLogoControllerListener) + .setOldController(logoHolder.getController()) + .build(); + logoHolder.setController(controller); + } else { + iconBitmapDescriptor = getBitmapDescriptorByName(uri); + update(); + } + } + + public MarkerOptions getMarkerOptions() { + if (markerOptions == null) { + markerOptions = createMarkerOptions(); + } + return markerOptions; + } + + @Override + public void addView(View child, int index) { + super.addView(child, index); + // if children are added, it means we are rendering a custom marker + if (!(child instanceof AirMapCallout)) { + hasCustomMarkerView = true; + } + update(); + } + + @Override + public Object getFeature() { + return marker; + } + + @Override + public void addToMap(GoogleMap map) { + marker = map.addMarker(getMarkerOptions()); + } + + @Override + public void removeFromMap(GoogleMap map) { + marker.remove(); + marker = null; + } + + private BitmapDescriptor getIcon() { + if (hasCustomMarkerView) { + // creating a bitmap from an arbitrary view + if (iconBitmapDescriptor != null) { + Bitmap viewBitmap = createDrawable(); + int width = Math.max(iconBitmap.getWidth(), viewBitmap.getWidth()); + int height = Math.max(iconBitmap.getHeight(), viewBitmap.getHeight()); + Bitmap combinedBitmap = Bitmap.createBitmap(width, height, iconBitmap.getConfig()); + Canvas canvas = new Canvas(combinedBitmap); + canvas.drawBitmap(iconBitmap, 0, 0, null); + canvas.drawBitmap(viewBitmap, 0, 0, null); + return BitmapDescriptorFactory.fromBitmap(combinedBitmap); + } else { + return BitmapDescriptorFactory.fromBitmap(createDrawable()); + } + } else if (iconBitmapDescriptor != null) { + // use local image as a marker + return iconBitmapDescriptor; + } else { + // render the default marker pin + return BitmapDescriptorFactory.defaultMarker(this.markerHue); + } + } + + private MarkerOptions createMarkerOptions() { + MarkerOptions options = new MarkerOptions().position(position); + if (anchorIsSet) options.anchor(anchorX, anchorY); + if (calloutAnchorIsSet) options.infoWindowAnchor(calloutAnchorX, calloutAnchorY); + options.title(title); + options.snippet(snippet); + options.rotation(rotation); + options.flat(flat); + options.draggable(draggable); + options.icon(getIcon()); + return options; + } + + public void update() { + if (marker == null) { + return; + } + + marker.setIcon(getIcon()); + + if (anchorIsSet) { + marker.setAnchor(anchorX, anchorY); + } else { + marker.setAnchor(0.5f, 1.0f); + } + + if (calloutAnchorIsSet) { + marker.setInfoWindowAnchor(calloutAnchorX, calloutAnchorY); + } else { + marker.setInfoWindowAnchor(0.5f, 0); + } + } + + public void update(int width, int height) { + this.width = width; + this.height = height; + update(); + } + + private Bitmap createDrawable() { + int width = this.width <= 0 ? 100 : this.width; + int height = this.height <= 0 ? 100 : this.height; + this.buildDrawingCache(); + Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); + + Canvas canvas = new Canvas(bitmap); + this.draw(canvas); + + return bitmap; + } + + public void setCalloutView(AirMapCallout view) { + this.calloutView = view; + } + + public AirMapCallout getCalloutView() { + return this.calloutView; + } + + public View getCallout() { + if (this.calloutView == null) return null; + + if (this.wrappedCalloutView == null) { + this.wrapCalloutView(); + } + + if (this.calloutView.getTooltip()) { + return this.wrappedCalloutView; + } else { + return null; + } + } + + public View getInfoContents() { + if (this.calloutView == null) return null; + + if (this.wrappedCalloutView == null) { + this.wrapCalloutView(); + } + + if (this.calloutView.getTooltip()) { + return null; + } else { + return this.wrappedCalloutView; + } + } + + private void wrapCalloutView() { + // some hackery is needed to get the arbitrary infowindow view to render centered, and + // with only the width/height that it needs. + if (this.calloutView == null || this.calloutView.getChildCount() == 0) { + return; + } + + LinearLayout LL = new LinearLayout(context); + LL.setOrientation(LinearLayout.VERTICAL); + LL.setLayoutParams(new LinearLayout.LayoutParams( + this.calloutView.width, + this.calloutView.height, + 0f + )); + + + LinearLayout LL2 = new LinearLayout(context); + LL2.setOrientation(LinearLayout.HORIZONTAL); + LL2.setLayoutParams(new LinearLayout.LayoutParams( + this.calloutView.width, + this.calloutView.height, + 0f + )); + + LL.addView(LL2); + LL2.addView(this.calloutView); + + this.wrappedCalloutView = LL; + } + + private int getDrawableResourceByName(String name) { + return getResources().getIdentifier( + name, + "drawable", + getContext().getPackageName()); + } + + private BitmapDescriptor getBitmapDescriptorByName(String name) { + return BitmapDescriptorFactory.fromResource(getDrawableResourceByName(name)); + } + +} diff --git a/android/src/main/java/com/airbnb/android/react/maps/AirMapMarkerManager.java b/android/src/main/java/com/airbnb/android/react/maps/AirMapMarkerManager.java new file mode 100644 index 000000000..52a0e6fc7 --- /dev/null +++ b/android/src/main/java/com/airbnb/android/react/maps/AirMapMarkerManager.java @@ -0,0 +1,196 @@ +package com.airbnb.android.react.maps; + +import android.graphics.Color; +import android.view.View; + +import com.facebook.react.bridge.ReadableArray; +import com.facebook.react.bridge.ReadableMap; +import com.facebook.react.common.MapBuilder; +import com.facebook.react.uimanager.LayoutShadowNode; +import com.facebook.react.uimanager.ThemedReactContext; +import com.facebook.react.uimanager.ViewGroupManager; +import com.facebook.react.uimanager.annotations.ReactProp; +import com.google.android.gms.maps.model.Marker; + +import java.util.HashMap; +import java.util.Map; + +import javax.annotation.Nullable; + +public class AirMapMarkerManager extends ViewGroupManager { + + public static final int SHOW_INFO_WINDOW = 1; + public static final int HIDE_INFO_WINDOW = 2; + + public AirMapMarkerManager() { + } + + @Override + public String getName() { + return "AIRMapMarker"; + } + + @Override + public AirMapMarker createViewInstance(ThemedReactContext context) { + return new AirMapMarker(context); + } + + @ReactProp(name = "coordinate") + public void setCoordinate(AirMapMarker view, ReadableMap map) { + view.setCoordinate(map); + } + + @ReactProp(name = "title") + public void setTitle(AirMapMarker view, String title) { + view.setTitle(title); + } + + @ReactProp(name = "identifier") + public void setIdentifier(AirMapMarker view, String identifier) { + view.setIdentifier(identifier); + } + + @ReactProp(name = "description") + public void setDescription(AirMapMarker view, String description) { + view.setSnippet(description); + } + + // NOTE(lmr): + // android uses normalized coordinate systems for this, and is provided through the + // `anchor` property and `calloutAnchor` instead. Perhaps some work could be done + // to normalize iOS and android to use just one of the systems. +// @ReactProp(name = "centerOffset") +// public void setCenterOffset(AirMapMarker view, ReadableMap map) { +// +// } +// +// @ReactProp(name = "calloutOffset") +// public void setCalloutOffset(AirMapMarker view, ReadableMap map) { +// +// } + + @ReactProp(name = "anchor") + public void setAnchor(AirMapMarker view, ReadableMap map) { + // should default to (0.5, 1) (bottom middle) + double x = map != null && map.hasKey("x") ? map.getDouble("x") : 0.5; + double y = map != null && map.hasKey("y") ? map.getDouble("y") : 1.0; + view.setAnchor(x, y); + } + + @ReactProp(name = "calloutAnchor") + public void setCalloutAnchor(AirMapMarker view, ReadableMap map) { + // should default to (0.5, 0) (top middle) + double x = map != null && map.hasKey("x") ? map.getDouble("x") : 0.5; + double y = map != null && map.hasKey("y") ? map.getDouble("y") : 0.0; + view.setCalloutAnchor(x, y); + } + + @ReactProp(name = "image") + public void setImage(AirMapMarker view, @Nullable String source) { + view.setImage(source); + } +// public void setImage(AirMapMarker view, ReadableMap image) { +// view.setImage(image); +// } + + @ReactProp(name = "pinColor", defaultInt = Color.RED, customType = "Color") + public void setPinColor(AirMapMarker view, int pinColor) { + float[] hsv = new float[3]; + Color.colorToHSV(pinColor, hsv); + // NOTE: android only supports a hue + view.setMarkerHue(hsv[0]); + } + + @ReactProp(name = "rotation", defaultFloat = 0.0f) + public void setMarkerRotation(AirMapMarker view, float rotation) { + view.setRotation(rotation); + } + + @ReactProp(name = "flat", defaultBoolean = false) + public void setFlat(AirMapMarker view, boolean flat) { + view.setFlat(flat); + } + + @ReactProp(name = "draggable", defaultBoolean = false) + public void setDraggable(AirMapMarker view, boolean draggable) { + view.setDraggable(draggable); + } + + @Override + public void addView(AirMapMarker parent, View child, int index) { + // if an component is a child, then it is a callout view, NOT part of the + // marker. + if (child instanceof AirMapCallout) { + parent.setCalloutView((AirMapCallout) child); + } else { + super.addView(parent, child, index); + parent.update(); + } + } + + @Override + public void removeViewAt(AirMapMarker parent, int index) { + super.removeViewAt(parent, index); + parent.update(); + } + + @Override + @Nullable + public Map getCommandsMap() { + return MapBuilder.of( + "showCallout", SHOW_INFO_WINDOW, + "hideCallout", HIDE_INFO_WINDOW + ); + } + + @Override + public void receiveCommand(AirMapMarker view, int commandId, @Nullable ReadableArray args) { + switch (commandId) { + case SHOW_INFO_WINDOW: + ((Marker) view.getFeature()).showInfoWindow(); + break; + + case HIDE_INFO_WINDOW: + ((Marker) view.getFeature()).hideInfoWindow(); + break; + } + } + + @Override + @Nullable + public Map getExportedCustomDirectEventTypeConstants() { + Map map = MapBuilder.of( + "onPress", MapBuilder.of("registrationName", "onPress"), + "onCalloutPress", MapBuilder.of("registrationName", "onCalloutPress"), + "onDragStart", MapBuilder.of("registrationName", "onDragStart"), + "onDrag", MapBuilder.of("registrationName", "onDrag"), + "onDragEnd", MapBuilder.of("registrationName", "onDragEnd") + ); + + map.putAll(MapBuilder.of( + "onDragStart", MapBuilder.of("registrationName", "onDragStart"), + "onDrag", MapBuilder.of("registrationName", "onDrag"), + "onDragEnd", MapBuilder.of("registrationName", "onDragEnd") + )); + + return map; + } + + @Override + public LayoutShadowNode createShadowNodeInstance() { + // we use a custom shadow node that emits the width/height of the view + // after layout with the updateExtraData method. Without this, we can't generate + // a bitmap of the appropriate width/height of the rendered view. + return new SizeReportingShadowNode(); + } + + @Override + public void updateExtraData(AirMapMarker view, Object extraData) { + // This method is called from the shadow node with the width/height of the rendered + // marker view. + HashMap data = (HashMap) extraData; + float width = data.get("width"); + float height = data.get("height"); + view.update((int) width, (int) height); + } +} diff --git a/android/src/main/java/com/airbnb/android/react/maps/AirMapPolygon.java b/android/src/main/java/com/airbnb/android/react/maps/AirMapPolygon.java new file mode 100644 index 000000000..166172795 --- /dev/null +++ b/android/src/main/java/com/airbnb/android/react/maps/AirMapPolygon.java @@ -0,0 +1,111 @@ +package com.airbnb.android.react.maps; + +import android.content.Context; + +import com.facebook.react.bridge.ReadableArray; +import com.facebook.react.bridge.ReadableMap; +import com.google.android.gms.maps.GoogleMap; +import com.google.android.gms.maps.model.LatLng; +import com.google.android.gms.maps.model.Polygon; +import com.google.android.gms.maps.model.PolygonOptions; + +import java.util.ArrayList; +import java.util.List; + +public class AirMapPolygon extends AirMapFeature { + + private PolygonOptions polygonOptions; + private Polygon polygon; + + private List coordinates; + private int strokeColor; + private int fillColor; + private float strokeWidth; + private boolean geodesic; + private float zIndex; + + public AirMapPolygon(Context context) { + super(context); + } + + public void setCoordinates(ReadableArray coordinates) { + // it's kind of a bummer that we can't run map() or anything on the ReadableArray + this.coordinates = new ArrayList<>(coordinates.size()); + for (int i = 0; i < coordinates.size(); i++) { + ReadableMap coordinate = coordinates.getMap(i); + this.coordinates.add(i, + new LatLng(coordinate.getDouble("latitude"), coordinate.getDouble("longitude"))); + } + if (polygon != null) { + polygon.setPoints(this.coordinates); + } + } + + public void setFillColor(int color) { + this.fillColor = color; + if (polygon != null) { + polygon.setFillColor(color); + } + } + + public void setStrokeColor(int color) { + this.strokeColor = color; + if (polygon != null) { + polygon.setStrokeColor(color); + } + } + + public void setStrokeWidth(float width) { + this.strokeWidth = width; + if (polygon != null) { + polygon.setStrokeWidth(width); + } + } + + public void setGeodesic(boolean geodesic) { + this.geodesic = geodesic; + if (polygon != null) { + polygon.setGeodesic(geodesic); + } + } + + public void setZIndex(float zIndex) { + this.zIndex = zIndex; + if (polygon != null) { + polygon.setZIndex(zIndex); + } + } + + public PolygonOptions getPolygonOptions() { + if (polygonOptions == null) { + polygonOptions = createPolygonOptions(); + } + return polygonOptions; + } + + private PolygonOptions createPolygonOptions() { + PolygonOptions options = new PolygonOptions(); + options.addAll(coordinates); + options.fillColor(fillColor); + options.strokeColor(strokeColor); + options.strokeWidth(strokeWidth); + options.geodesic(geodesic); + options.zIndex(zIndex); + return options; + } + + @Override + public Object getFeature() { + return polygon; + } + + @Override + public void addToMap(GoogleMap map) { + polygon = map.addPolygon(getPolygonOptions()); + } + + @Override + public void removeFromMap(GoogleMap map) { + polygon.remove(); + } +} diff --git a/android/src/main/java/com/airbnb/android/react/maps/AirMapPolygonManager.java b/android/src/main/java/com/airbnb/android/react/maps/AirMapPolygonManager.java new file mode 100644 index 000000000..f08ce0289 --- /dev/null +++ b/android/src/main/java/com/airbnb/android/react/maps/AirMapPolygonManager.java @@ -0,0 +1,70 @@ +package com.airbnb.android.react.maps; + +import android.content.Context; +import android.graphics.Color; +import android.os.Build; +import android.util.DisplayMetrics; +import android.view.WindowManager; + +import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.bridge.ReadableArray; +import com.facebook.react.uimanager.ThemedReactContext; +import com.facebook.react.uimanager.ViewGroupManager; +import com.facebook.react.uimanager.annotations.ReactProp; + +public class AirMapPolygonManager extends ViewGroupManager { + private final DisplayMetrics metrics; + + public AirMapPolygonManager(ReactApplicationContext reactContext) { + super(); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { + metrics = new DisplayMetrics(); + ((WindowManager) reactContext.getSystemService(Context.WINDOW_SERVICE)) + .getDefaultDisplay() + .getRealMetrics(metrics); + } else { + metrics = reactContext.getResources().getDisplayMetrics(); + } + } + + @Override + public String getName() { + return "AIRMapPolygon"; + } + + @Override + public AirMapPolygon createViewInstance(ThemedReactContext context) { + return new AirMapPolygon(context); + } + + @ReactProp(name = "coordinates") + public void setCoordinate(AirMapPolygon view, ReadableArray coordinates) { + view.setCoordinates(coordinates); + } + + @ReactProp(name = "strokeWidth", defaultFloat = 1f) + public void setStrokeWidth(AirMapPolygon view, float widthInPoints) { + float widthInScreenPx = metrics.density * widthInPoints; // done for parity with iOS + view.setStrokeWidth(widthInScreenPx); + } + + @ReactProp(name = "fillColor", defaultInt = Color.RED, customType = "Color") + public void setFillColor(AirMapPolygon view, int color) { + view.setFillColor(color); + } + + @ReactProp(name = "strokeColor", defaultInt = Color.RED, customType = "Color") + public void setStrokeColor(AirMapPolygon view, int color) { + view.setStrokeColor(color); + } + + @ReactProp(name = "geodesic", defaultBoolean = false) + public void setGeodesic(AirMapPolygon view, boolean geodesic) { + view.setGeodesic(geodesic); + } + + @ReactProp(name = "zIndex", defaultFloat = 1.0f) + public void setZIndex(AirMapPolygon view, float zIndex) { + view.setZIndex(zIndex); + } +} diff --git a/android/src/main/java/com/airbnb/android/react/maps/AirMapPolyline.java b/android/src/main/java/com/airbnb/android/react/maps/AirMapPolyline.java new file mode 100644 index 000000000..cf15dfadf --- /dev/null +++ b/android/src/main/java/com/airbnb/android/react/maps/AirMapPolyline.java @@ -0,0 +1,101 @@ +package com.airbnb.android.react.maps; + +import android.content.Context; + +import com.facebook.react.bridge.ReadableArray; +import com.facebook.react.bridge.ReadableMap; +import com.google.android.gms.maps.GoogleMap; +import com.google.android.gms.maps.model.LatLng; +import com.google.android.gms.maps.model.Polyline; +import com.google.android.gms.maps.model.PolylineOptions; + +import java.util.ArrayList; +import java.util.List; + +public class AirMapPolyline extends AirMapFeature { + + private PolylineOptions polylineOptions; + private Polyline polyline; + + private List coordinates; + private int color; + private float width; + private boolean geodesic; + private float zIndex; + + public AirMapPolyline(Context context) { + super(context); + } + + public void setCoordinates(ReadableArray coordinates) { + this.coordinates = new ArrayList<>(coordinates.size()); + for (int i = 0; i < coordinates.size(); i++) { + ReadableMap coordinate = coordinates.getMap(i); + this.coordinates.add(i, + new LatLng(coordinate.getDouble("latitude"), coordinate.getDouble("longitude"))); + } + if (polyline != null) { + polyline.setPoints(this.coordinates); + } + } + + public void setColor(int color) { + this.color = color; + if (polyline != null) { + polyline.setColor(color); + } + } + + public void setWidth(float width) { + this.width = width; + if (polyline != null) { + polyline.setWidth(width); + } + } + + public void setZIndex(float zIndex) { + this.zIndex = zIndex; + if (polyline != null) { + polyline.setZIndex(zIndex); + } + } + + public void setGeodesic(boolean geodesic) { + this.geodesic = geodesic; + if (polyline != null) { + polyline.setGeodesic(geodesic); + } + } + + public PolylineOptions getPolylineOptions() { + if (polylineOptions == null) { + polylineOptions = createPolylineOptions(); + } + return polylineOptions; + } + + private PolylineOptions createPolylineOptions() { + PolylineOptions options = new PolylineOptions(); + options.addAll(coordinates); + options.color(color); + options.width(width); + options.geodesic(geodesic); + options.zIndex(zIndex); + return options; + } + + @Override + public Object getFeature() { + return polyline; + } + + @Override + public void addToMap(GoogleMap map) { + polyline = map.addPolyline(getPolylineOptions()); + } + + @Override + public void removeFromMap(GoogleMap map) { + polyline.remove(); + } +} diff --git a/android/src/main/java/com/airbnb/android/react/maps/AirMapPolylineManager.java b/android/src/main/java/com/airbnb/android/react/maps/AirMapPolylineManager.java new file mode 100644 index 000000000..89edc861e --- /dev/null +++ b/android/src/main/java/com/airbnb/android/react/maps/AirMapPolylineManager.java @@ -0,0 +1,65 @@ +package com.airbnb.android.react.maps; + +import android.content.Context; +import android.graphics.Color; +import android.os.Build; +import android.util.DisplayMetrics; +import android.view.WindowManager; + +import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.bridge.ReadableArray; +import com.facebook.react.uimanager.ThemedReactContext; +import com.facebook.react.uimanager.ViewGroupManager; +import com.facebook.react.uimanager.annotations.ReactProp; + +public class AirMapPolylineManager extends ViewGroupManager { + private final DisplayMetrics metrics; + + public AirMapPolylineManager(ReactApplicationContext reactContext) { + super(); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { + metrics = new DisplayMetrics(); + ((WindowManager) reactContext.getSystemService(Context.WINDOW_SERVICE)) + .getDefaultDisplay() + .getRealMetrics(metrics); + } else { + metrics = reactContext.getResources().getDisplayMetrics(); + } + } + + @Override + public String getName() { + return "AIRMapPolyline"; + } + + @Override + public AirMapPolyline createViewInstance(ThemedReactContext context) { + return new AirMapPolyline(context); + } + + @ReactProp(name = "coordinates") + public void setCoordinate(AirMapPolyline view, ReadableArray coordinates) { + view.setCoordinates(coordinates); + } + + @ReactProp(name = "strokeWidth", defaultFloat = 1f) + public void setStrokeWidth(AirMapPolyline view, float widthInPoints) { + float widthInScreenPx = metrics.density * widthInPoints; // done for parity with iOS + view.setWidth(widthInScreenPx); + } + + @ReactProp(name = "strokeColor", defaultInt = Color.RED, customType = "Color") + public void setStrokeColor(AirMapPolyline view, int color) { + view.setColor(color); + } + + @ReactProp(name = "geodesic", defaultBoolean = false) + public void setGeodesic(AirMapPolyline view, boolean geodesic) { + view.setGeodesic(geodesic); + } + + @ReactProp(name = "zIndex", defaultFloat = 1.0f) + public void setZIndex(AirMapPolyline view, float zIndex) { + view.setZIndex(zIndex); + } +} diff --git a/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java b/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java new file mode 100644 index 000000000..b817f804f --- /dev/null +++ b/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java @@ -0,0 +1,744 @@ +package com.airbnb.android.react.maps; + +import android.content.pm.PackageManager; +import android.content.res.ColorStateList; +import android.graphics.Bitmap; +import android.graphics.Color; +import android.graphics.Point; +import android.graphics.PorterDuff; +import android.os.Handler; +import android.os.Build; +import android.support.v4.view.GestureDetectorCompat; +import android.support.v4.view.MotionEventCompat; +import android.view.GestureDetector; +import android.view.MotionEvent; +import android.view.ScaleGestureDetector; +import android.view.View; +import android.view.View.OnLayoutChangeListener; +import android.content.Context; + +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.ProgressBar; +import android.widget.RelativeLayout; +import android.widget.TextView; +import com.facebook.react.bridge.LifecycleEventListener; +import com.facebook.react.bridge.ReadableArray; +import com.facebook.react.bridge.ReadableMap; +import com.facebook.react.bridge.WritableMap; +import com.facebook.react.bridge.WritableNativeMap; +import com.facebook.react.uimanager.ThemedReactContext; +import com.facebook.react.uimanager.UIManagerModule; +import com.facebook.react.uimanager.events.EventDispatcher; +import com.google.android.gms.maps.CameraUpdate; +import com.google.android.gms.maps.CameraUpdateFactory; +import com.google.android.gms.maps.GoogleMap; +import com.google.android.gms.maps.MapView; +import com.google.android.gms.maps.OnMapReadyCallback; +import com.google.android.gms.maps.Projection; +import com.google.android.gms.maps.model.CameraPosition; +import com.google.android.gms.maps.model.Circle; +import com.google.android.gms.maps.model.LatLng; +import com.google.android.gms.maps.model.LatLngBounds; +import com.google.android.gms.maps.model.Marker; +import com.google.android.gms.maps.model.Polygon; +import com.google.android.gms.maps.model.Polyline; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static android.support.v4.content.PermissionChecker.checkSelfPermission; + +public class AirMapView extends MapView implements GoogleMap.InfoWindowAdapter, + GoogleMap.OnMarkerDragListener, OnMapReadyCallback { + public GoogleMap map; + + private ProgressBar mapLoadingProgressBar; + private RelativeLayout mapLoadingLayout; + private ImageView cacheImageView; + private Boolean isMapLoaded = false; + private Integer loadingBackgroundColor = null; + private Integer loadingIndicatorColor = null; + + private LatLngBounds boundsToMove; + private boolean showUserLocation = false; + private boolean isMonitoringRegion = false; + private boolean isTouchDown = false; + private boolean handlePanDrag = false; + private boolean cacheEnabled = false; + private boolean loadingEnabled = false; + + private static final String[] PERMISSIONS = new String[] { + "android.permission.ACCESS_FINE_LOCATION", "android.permission.ACCESS_COARSE_LOCATION"}; + + private final List features = new ArrayList<>(); + private final Map markerMap = new HashMap<>(); + private final Map polylineMap = new HashMap<>(); + private final Map polygonMap = new HashMap<>(); + private final Map circleMap = new HashMap<>(); + + private final ScaleGestureDetector scaleDetector; + private final GestureDetectorCompat gestureDetector; + private final AirMapManager manager; + private LifecycleEventListener lifecycleListener; + private OnLayoutChangeListener onLayoutChangeListener; + private boolean paused = false; + private ThemedReactContext context; + + final EventDispatcher eventDispatcher; + + public AirMapView(ThemedReactContext context, Context appContext, AirMapManager manager) { + super(appContext); + this.manager = manager; + this.context = context; + + super.onCreate(null); + super.onResume(); + super.getMapAsync(this); + + final AirMapView view = this; + scaleDetector = + new ScaleGestureDetector(context, new ScaleGestureDetector.SimpleOnScaleGestureListener() { +// @Override +// public boolean onScale(ScaleGestureDetector detector) { +// Log.d("AirMapView", "onScale"); +// return false; +// } + + @Override + public boolean onScaleBegin(ScaleGestureDetector detector) { + view.startMonitoringRegion(); + return true; // stop recording this gesture. let mapview handle it. + } + }); + + gestureDetector = + new GestureDetectorCompat(context, new GestureDetector.SimpleOnGestureListener() { + @Override + public boolean onDoubleTap(MotionEvent e) { + view.startMonitoringRegion(); + return false; + } + + @Override + public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, + float distanceY) { + if (handlePanDrag) { + onPanDrag(e2); + } + view.startMonitoringRegion(); + return false; + } + }); + + onLayoutChangeListener = new OnLayoutChangeListener() { + @Override public void onLayoutChange(View v, int left, int top, int right, int bottom, + int oldLeft, int oldTop, int oldRight, int oldBottom) { + if (!AirMapView.this.paused) { + AirMapView.this.cacheView(); + } + } + }; + this.addOnLayoutChangeListener(this.onLayoutChangeListener); + + eventDispatcher = context.getNativeModule(UIManagerModule.class).getEventDispatcher(); + } + + @Override + public void onMapReady(final GoogleMap map) { + this.map = map; + this.map.setInfoWindowAdapter(this); + this.map.setOnMarkerDragListener(this); + + manager.pushEvent(this, "onMapReady", new WritableNativeMap()); + + final AirMapView view = this; + + map.setOnMarkerClickListener(new GoogleMap.OnMarkerClickListener() { + @Override + public boolean onMarkerClick(Marker marker) { + WritableMap event; + + event = makeClickEventData(marker.getPosition()); + event.putString("action", "marker-press"); + manager.pushEvent(view, "onMarkerPress", event); + + event = makeClickEventData(marker.getPosition()); + event.putString("action", "marker-press"); + manager.pushEvent(markerMap.get(marker), "onPress", event); + + return false; // returning false opens the callout window, if possible + } + }); + + map.setOnInfoWindowClickListener(new GoogleMap.OnInfoWindowClickListener() { + @Override + public void onInfoWindowClick(Marker marker) { + WritableMap event; + + event = makeClickEventData(marker.getPosition()); + event.putString("action", "callout-press"); + manager.pushEvent(view, "onCalloutPress", event); + + event = makeClickEventData(marker.getPosition()); + event.putString("action", "callout-press"); + AirMapMarker markerView = markerMap.get(marker); + manager.pushEvent(markerView, "onCalloutPress", event); + + event = makeClickEventData(marker.getPosition()); + event.putString("action", "callout-press"); + AirMapCallout infoWindow = markerView.getCalloutView(); + if (infoWindow != null) manager.pushEvent(infoWindow, "onPress", event); + } + }); + + map.setOnMapClickListener(new GoogleMap.OnMapClickListener() { + @Override + public void onMapClick(LatLng point) { + WritableMap event = makeClickEventData(point); + event.putString("action", "press"); + manager.pushEvent(view, "onPress", event); + } + }); + + map.setOnMapLongClickListener(new GoogleMap.OnMapLongClickListener() { + @Override + public void onMapLongClick(LatLng point) { + WritableMap event = makeClickEventData(point); + event.putString("action", "long-press"); + manager.pushEvent(view, "onLongPress", makeClickEventData(point)); + } + }); + + map.setOnCameraChangeListener(new GoogleMap.OnCameraChangeListener() { + @Override + public void onCameraChange(CameraPosition position) { + LatLngBounds bounds = map.getProjection().getVisibleRegion().latLngBounds; + LatLng center = position.target; + lastBoundsEmitted = bounds; + eventDispatcher.dispatchEvent(new RegionChangeEvent(getId(), bounds, center, isTouchDown)); + view.stopMonitoringRegion(); + } + }); + + map.setOnMapLoadedCallback(new GoogleMap.OnMapLoadedCallback() { + @Override public void onMapLoaded() { + isMapLoaded = true; + AirMapView.this.cacheView(); + } + }); + + // We need to be sure to disable location-tracking when app enters background, in-case some + // other module + // has acquired a wake-lock and is controlling location-updates, otherwise, location-manager + // will be left + // updating location constantly, killing the battery, even though some other location-mgmt + // module may + // desire to shut-down location-services. + lifecycleListener = new LifecycleEventListener() { + @Override + public void onHostResume() { + if (hasPermissions()) { + //noinspection MissingPermission + map.setMyLocationEnabled(showUserLocation); + } + synchronized (AirMapView.this) { + AirMapView.this.onResume(); + paused = false; + } + } + + @Override + public void onHostPause() { + if (hasPermissions()) { + //noinspection MissingPermission + map.setMyLocationEnabled(false); + } + synchronized (AirMapView.this) { + AirMapView.this.onPause(); + paused = true; + } + } + + @Override + public void onHostDestroy() { + AirMapView.this.doDestroy(); + } + }; + + context.addLifecycleEventListener(lifecycleListener); + } + + private boolean hasPermissions() { + return checkSelfPermission(getContext(), PERMISSIONS[0]) == PackageManager.PERMISSION_GRANTED || + checkSelfPermission(getContext(), PERMISSIONS[1]) == PackageManager.PERMISSION_GRANTED; + } + + /* + onDestroy is final method so I can't override it. + */ + public synchronized void doDestroy() { + if (lifecycleListener != null) { + context.removeLifecycleEventListener(lifecycleListener); + lifecycleListener = null; + } + if (!paused) { + onPause(); + } + onDestroy(); + } + + public void setRegion(ReadableMap region) { + if (region == null) return; + + Double lng = region.getDouble("longitude"); + Double lat = region.getDouble("latitude"); + Double lngDelta = region.getDouble("longitudeDelta"); + Double latDelta = region.getDouble("latitudeDelta"); + LatLngBounds bounds = new LatLngBounds( + new LatLng(lat - latDelta / 2, lng - lngDelta / 2), // southwest + new LatLng(lat + latDelta / 2, lng + lngDelta / 2) // northeast + ); + if (super.getHeight() <= 0 || super.getWidth() <= 0) { + // in this case, our map has not been laid out yet, so we save the bounds in a local + // variable, and make a guess of zoomLevel 10. Not to worry, though: as soon as layout + // occurs, we will move the camera to the saved bounds. Note that if we tried to move + // to the bounds now, it would trigger an exception. + map.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(lat, lng), 10)); + boundsToMove = bounds; + } else { + map.moveCamera(CameraUpdateFactory.newLatLngBounds(bounds, 0)); + boundsToMove = null; + } + } + + public void setShowsUserLocation(boolean showUserLocation) { + this.showUserLocation = showUserLocation; // hold onto this for lifecycle handling + if (hasPermissions()) { + //noinspection MissingPermission + map.setMyLocationEnabled(showUserLocation); + } + } + + public void setShowsMyLocationButton(boolean showMyLocationButton) { + if (hasPermissions()) { + map.getUiSettings().setMyLocationButtonEnabled(showMyLocationButton); + } + } + + public void setToolbarEnabled(boolean toolbarEnabled) { + if (hasPermissions()) { + map.getUiSettings().setMapToolbarEnabled(toolbarEnabled); + } + } + + public void setCacheEnabled(boolean cacheEnabled) { + this.cacheEnabled = cacheEnabled; + this.cacheView(); + } + + public void enableMapLoading(boolean loadingEnabled) { + if (loadingEnabled && !this.isMapLoaded) { + this.getMapLoadingLayoutView().setVisibility(View.VISIBLE); + } + } + + public void setLoadingBackgroundColor(Integer loadingBackgroundColor) { + this.loadingBackgroundColor = loadingBackgroundColor; + + if (this.mapLoadingLayout != null) { + if (loadingBackgroundColor == null) { + this.mapLoadingLayout.setBackgroundColor(Color.WHITE); + } else { + this.mapLoadingLayout.setBackgroundColor(this.loadingBackgroundColor); + } + } + } + + public void setLoadingIndicatorColor(Integer loadingIndicatorColor) { + this.loadingIndicatorColor = loadingIndicatorColor; + if (this.mapLoadingProgressBar != null) { + Integer color = loadingIndicatorColor; + if (color == null) { + color = Color.parseColor("#606060"); + } + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + ColorStateList progressTintList = ColorStateList.valueOf(loadingIndicatorColor); + ColorStateList secondaryProgressTintList = ColorStateList.valueOf(loadingIndicatorColor); + ColorStateList indeterminateTintList = ColorStateList.valueOf(loadingIndicatorColor); + + this.mapLoadingProgressBar.setProgressTintList(progressTintList); + this.mapLoadingProgressBar.setSecondaryProgressTintList(secondaryProgressTintList); + this.mapLoadingProgressBar.setIndeterminateTintList(indeterminateTintList); + } else { + PorterDuff.Mode mode = PorterDuff.Mode.SRC_IN; + if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.GINGERBREAD_MR1) { + mode = PorterDuff.Mode.MULTIPLY; + } + if (this.mapLoadingProgressBar.getIndeterminateDrawable() != null) + this.mapLoadingProgressBar.getIndeterminateDrawable().setColorFilter(color, mode); + if (this.mapLoadingProgressBar.getProgressDrawable() != null) + this.mapLoadingProgressBar.getProgressDrawable().setColorFilter(color, mode); + } + } + } + + public void setHandlePanDrag(boolean handlePanDrag) { + this.handlePanDrag = handlePanDrag; + } + + public void addFeature(View child, int index) { + // Our desired API is to pass up annotations/overlays as children to the mapview component. + // This is where we intercept them and do the appropriate underlying mapview action. + if (child instanceof AirMapMarker) { + AirMapMarker annotation = (AirMapMarker) child; + annotation.addToMap(map); + features.add(index, annotation); + Marker marker = (Marker) annotation.getFeature(); + markerMap.put(marker, annotation); + } else if (child instanceof AirMapPolyline) { + AirMapPolyline polylineView = (AirMapPolyline) child; + polylineView.addToMap(map); + features.add(index, polylineView); + Polyline polyline = (Polyline) polylineView.getFeature(); + polylineMap.put(polyline, polylineView); + } else if (child instanceof AirMapPolygon) { + AirMapPolygon polygonView = (AirMapPolygon) child; + polygonView.addToMap(map); + features.add(index, polygonView); + Polygon polygon = (Polygon) polygonView.getFeature(); + polygonMap.put(polygon, polygonView); + } else if (child instanceof AirMapCircle) { + AirMapCircle circleView = (AirMapCircle) child; + circleView.addToMap(map); + features.add(index, circleView); + Circle circle = (Circle) circleView.getFeature(); + circleMap.put(circle, circleView); + } else { + // TODO(lmr): throw? User shouldn't be adding non-feature children. + } + } + + public int getFeatureCount() { + return features.size(); + } + + public View getFeatureAt(int index) { + return features.get(index); + } + + public void removeFeatureAt(int index) { + AirMapFeature feature = features.remove(index); + + + if (feature instanceof AirMapMarker) { + markerMap.remove(feature.getFeature()); + } else if (feature instanceof AirMapPolyline) { + polylineMap.remove(feature.getFeature()); + } else if (feature instanceof AirMapPolygon) { + polygonMap.remove(feature.getFeature()); + } else if (feature instanceof AirMapCircle) { + circleMap.remove(feature.getFeature()); + } + feature.removeFromMap(map); + } + + public WritableMap makeClickEventData(LatLng point) { + WritableMap event = new WritableNativeMap(); + + WritableMap coordinate = new WritableNativeMap(); + coordinate.putDouble("latitude", point.latitude); + coordinate.putDouble("longitude", point.longitude); + event.putMap("coordinate", coordinate); + + Projection projection = map.getProjection(); + Point screenPoint = projection.toScreenLocation(point); + + WritableMap position = new WritableNativeMap(); + position.putDouble("x", screenPoint.x); + position.putDouble("y", screenPoint.y); + event.putMap("position", position); + + return event; + } + + public void updateExtraData(Object extraData) { + // if boundsToMove is not null, we now have the MapView's width/height, so we can apply + // a proper camera move + if (boundsToMove != null) { + HashMap data = (HashMap) extraData; + float width = data.get("width"); + float height = data.get("height"); + map.moveCamera( + CameraUpdateFactory.newLatLngBounds( + boundsToMove, + (int) width, + (int) height, + 0 + ) + ); + boundsToMove = null; + } + } + + public void animateToRegion(LatLngBounds bounds, int duration) { + startMonitoringRegion(); + map.animateCamera(CameraUpdateFactory.newLatLngBounds(bounds, 0), duration, null); + } + + public void animateToCoordinate(LatLng coordinate, int duration) { + startMonitoringRegion(); + map.animateCamera(CameraUpdateFactory.newLatLng(coordinate), duration, null); + } + + public void fitToElements(boolean animated) { + LatLngBounds.Builder builder = new LatLngBounds.Builder(); + for (AirMapFeature feature : features) { + if (feature instanceof AirMapMarker) { + Marker marker = (Marker) feature.getFeature(); + builder.include(marker.getPosition()); + } + // TODO(lmr): may want to include shapes / etc. + } + LatLngBounds bounds = builder.build(); + CameraUpdate cu = CameraUpdateFactory.newLatLngBounds(bounds, 50); + if (animated) { + startMonitoringRegion(); + map.animateCamera(cu); + } else { + map.moveCamera(cu); + } + } + + public void fitToSuppliedMarkers(ReadableArray markerIDsArray, boolean animated) { + LatLngBounds.Builder builder = new LatLngBounds.Builder(); + + String[] markerIDs = new String[markerIDsArray.size()]; + for (int i = 0; i < markerIDsArray.size(); i++) { + markerIDs[i] = markerIDsArray.getString(i); + } + + boolean addedPosition = false; + + List markerIDList = Arrays.asList(markerIDs); + + for (AirMapFeature feature : features) { + if (feature instanceof AirMapMarker) { + String identifier = ((AirMapMarker)feature).getIdentifier(); + Marker marker = (Marker)feature.getFeature(); + if (markerIDList.contains(identifier)) { + builder.include(marker.getPosition()); + addedPosition = true; + } + } + } + + if (addedPosition) { + LatLngBounds bounds = builder.build(); + CameraUpdate cu = CameraUpdateFactory.newLatLngBounds(bounds, 50); + if (animated) { + startMonitoringRegion(); + map.animateCamera(cu); + } else { + map.moveCamera(cu); + } + } + } + + // InfoWindowAdapter interface + + @Override + public View getInfoWindow(Marker marker) { + AirMapMarker markerView = markerMap.get(marker); + return markerView.getCallout(); + } + + @Override + public View getInfoContents(Marker marker) { + AirMapMarker markerView = markerMap.get(marker); + return markerView.getInfoContents(); + } + + @Override + public boolean dispatchTouchEvent(MotionEvent ev) { + scaleDetector.onTouchEvent(ev); + gestureDetector.onTouchEvent(ev); + + int action = MotionEventCompat.getActionMasked(ev); + + switch (action) { + case (MotionEvent.ACTION_DOWN): + this.getParent().requestDisallowInterceptTouchEvent(true); + isTouchDown = true; + break; + case (MotionEvent.ACTION_MOVE): + startMonitoringRegion(); + break; + case (MotionEvent.ACTION_UP): + this.getParent().requestDisallowInterceptTouchEvent(false); + isTouchDown = false; + break; + } + super.dispatchTouchEvent(ev); + return true; + } + + // Timer Implementation + + public void startMonitoringRegion() { + if (isMonitoringRegion) return; + timerHandler.postDelayed(timerRunnable, 100); + isMonitoringRegion = true; + } + + public void stopMonitoringRegion() { + if (!isMonitoringRegion) return; + timerHandler.removeCallbacks(timerRunnable); + isMonitoringRegion = false; + } + + private LatLngBounds lastBoundsEmitted; + + Handler timerHandler = new Handler(); + Runnable timerRunnable = new Runnable() { + + @Override + public void run() { + + LatLngBounds bounds = map.getProjection().getVisibleRegion().latLngBounds; + if (lastBoundsEmitted == null || + LatLngBoundsUtils.BoundsAreDifferent(bounds, lastBoundsEmitted)) { + LatLng center = map.getCameraPosition().target; + lastBoundsEmitted = bounds; + eventDispatcher.dispatchEvent(new RegionChangeEvent(getId(), bounds, center, true)); + } + + timerHandler.postDelayed(this, 100); + } + }; + + @Override + public void onMarkerDragStart(Marker marker) { + WritableMap event = makeClickEventData(marker.getPosition()); + manager.pushEvent(this, "onMarkerDragStart", event); + + AirMapMarker markerView = markerMap.get(marker); + event = makeClickEventData(marker.getPosition()); + manager.pushEvent(markerView, "onDragStart", event); + } + + @Override + public void onMarkerDrag(Marker marker) { + WritableMap event = makeClickEventData(marker.getPosition()); + manager.pushEvent(this, "onMarkerDrag", event); + + AirMapMarker markerView = markerMap.get(marker); + event = makeClickEventData(marker.getPosition()); + manager.pushEvent(markerView, "onDrag", event); + } + + @Override + public void onMarkerDragEnd(Marker marker) { + WritableMap event = makeClickEventData(marker.getPosition()); + manager.pushEvent(this, "onMarkerDragEnd", event); + + AirMapMarker markerView = markerMap.get(marker); + event = makeClickEventData(marker.getPosition()); + manager.pushEvent(markerView, "onDragEnd", event); + } + + private ProgressBar getMapLoadingProgressBar() { + if (this.mapLoadingProgressBar == null) { + this.mapLoadingProgressBar = new ProgressBar(getContext()); + this.mapLoadingProgressBar.setIndeterminate(true); + } + if (this.loadingIndicatorColor != null) { + this.setLoadingIndicatorColor(this.loadingIndicatorColor); + } + return this.mapLoadingProgressBar; + } + + private RelativeLayout getMapLoadingLayoutView() { + if (this.mapLoadingLayout == null) { + this.mapLoadingLayout = new RelativeLayout(getContext()); + this.mapLoadingLayout.setBackgroundColor(Color.LTGRAY); + this.addView(this.mapLoadingLayout, + new ViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.FILL_PARENT)); + + RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT); + params.addRule(RelativeLayout.CENTER_IN_PARENT); + this.mapLoadingLayout.addView(this.getMapLoadingProgressBar(), params); + + this.mapLoadingLayout.setVisibility(View.INVISIBLE); + } + this.setLoadingBackgroundColor(this.loadingBackgroundColor); + return this.mapLoadingLayout; + } + + private ImageView getCacheImageView() { + if (this.cacheImageView == null) { + this.cacheImageView = new ImageView(getContext()); + this.addView(this.cacheImageView, + new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); + this.cacheImageView.setVisibility(View.INVISIBLE); + } + return this.cacheImageView; + } + + private void removeCacheImageView() { + if (this.cacheImageView != null) { + ((ViewGroup)this.cacheImageView.getParent()).removeView(this.cacheImageView); + this.cacheImageView = null; + } + } + + private void removeMapLoadingProgressBar() { + if (this.mapLoadingProgressBar != null) { + ((ViewGroup)this.mapLoadingProgressBar.getParent()).removeView(this.mapLoadingProgressBar); + this.mapLoadingProgressBar = null; + } + } + + private void removeMapLoadingLayoutView() { + this.removeMapLoadingProgressBar(); + if (this.mapLoadingLayout != null) { + ((ViewGroup)this.mapLoadingLayout.getParent()).removeView(this.mapLoadingLayout); + this.mapLoadingLayout = null; + } + } + + private void cacheView() { + if (this.cacheEnabled) { + final ImageView cacheImageView = this.getCacheImageView(); + final RelativeLayout mapLoadingLayout = this.getMapLoadingLayoutView(); + cacheImageView.setVisibility(View.INVISIBLE); + mapLoadingLayout.setVisibility(View.VISIBLE); + if (this.isMapLoaded) { + this.map.snapshot(new GoogleMap.SnapshotReadyCallback() { + @Override public void onSnapshotReady(Bitmap bitmap) { + cacheImageView.setImageBitmap(bitmap); + cacheImageView.setVisibility(View.VISIBLE); + mapLoadingLayout.setVisibility(View.INVISIBLE); + } + }); + } + } + else { + this.removeCacheImageView(); + if (this.isMapLoaded) { + this.removeMapLoadingLayoutView(); + } + } + } + + public void onPanDrag(MotionEvent ev) { + Point point = new Point((int) ev.getX(), (int) ev.getY()); + LatLng coords = this.map.getProjection().fromScreenLocation(point); + WritableMap event = makeClickEventData(coords); + manager.pushEvent(this, "onPanDrag", event); + } +} diff --git a/android/src/main/java/com/airbnb/android/react/maps/LatLngBoundsUtils.java b/android/src/main/java/com/airbnb/android/react/maps/LatLngBoundsUtils.java new file mode 100644 index 000000000..ed1058c88 --- /dev/null +++ b/android/src/main/java/com/airbnb/android/react/maps/LatLngBoundsUtils.java @@ -0,0 +1,47 @@ +package com.airbnb.android.react.maps; + +import com.google.android.gms.maps.model.LatLng; +import com.google.android.gms.maps.model.LatLngBounds; + +public class LatLngBoundsUtils { + public static boolean BoundsAreDifferent(LatLngBounds a, LatLngBounds b) { + LatLng centerA = a.getCenter(); + double latA = centerA.latitude; + double lngA = centerA.longitude; + double latDeltaA = a.northeast.latitude - a.southwest.latitude; + double lngDeltaA = a.northeast.longitude - a.southwest.longitude; + + LatLng centerB = b.getCenter(); + double latB = centerB.latitude; + double lngB = centerB.longitude; + double latDeltaB = b.northeast.latitude - b.southwest.latitude; + double lngDeltaB = b.northeast.longitude - b.southwest.longitude; + + double latEps = LatitudeEpsilon(a, b); + double lngEps = LongitudeEpsilon(a, b); + + return + different(latA, latB, latEps) || + different(lngA, lngB, lngEps) || + different(latDeltaA, latDeltaB, latEps) || + different(lngDeltaA, lngDeltaB, lngEps); + } + + private static boolean different(double a, double b, double epsilon) { + return Math.abs(a - b) > epsilon; + } + + private static double LatitudeEpsilon(LatLngBounds a, LatLngBounds b) { + double sizeA = a.northeast.latitude - a.southwest.latitude; // something mod 180? + double sizeB = b.northeast.latitude - b.southwest.latitude; // something mod 180? + double size = Math.min(Math.abs(sizeA), Math.abs(sizeB)); + return size / 2560; + } + + private static double LongitudeEpsilon(LatLngBounds a, LatLngBounds b) { + double sizeA = a.northeast.longitude - a.southwest.longitude; + double sizeB = b.northeast.longitude - b.southwest.longitude; + double size = Math.min(Math.abs(sizeA), Math.abs(sizeB)); + return size / 2560; + } +} diff --git a/android/src/main/java/com/airbnb/android/react/maps/MapsPackage.java b/android/src/main/java/com/airbnb/android/react/maps/MapsPackage.java new file mode 100644 index 000000000..f352d924e --- /dev/null +++ b/android/src/main/java/com/airbnb/android/react/maps/MapsPackage.java @@ -0,0 +1,46 @@ +package com.airbnb.android.react.maps; + +import android.app.Activity; + +import com.facebook.react.ReactPackage; +import com.facebook.react.bridge.JavaScriptModule; +import com.facebook.react.bridge.NativeModule; +import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.uimanager.ViewManager; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +public class MapsPackage implements ReactPackage { + public MapsPackage(Activity activity) { } // backwards compatability + public MapsPackage() { } + + @Override + public List createNativeModules(ReactApplicationContext reactContext) { + return Collections.emptyList(); + } + + @Override + public List> createJSModules() { + return Collections.emptyList(); + } + + @Override + public List createViewManagers(ReactApplicationContext reactContext) { + AirMapCalloutManager calloutManager = new AirMapCalloutManager(); + AirMapMarkerManager annotationManager = new AirMapMarkerManager(); + AirMapPolylineManager polylineManager = new AirMapPolylineManager(reactContext); + AirMapPolygonManager polygonManager = new AirMapPolygonManager(reactContext); + AirMapCircleManager circleManager = new AirMapCircleManager(reactContext); + AirMapManager mapManager = new AirMapManager(reactContext.getBaseContext()); + + return Arrays.asList( + calloutManager, + annotationManager, + polylineManager, + polygonManager, + circleManager, + mapManager); + } +} diff --git a/android/src/main/java/com/airbnb/android/react/maps/RegionChangeEvent.java b/android/src/main/java/com/airbnb/android/react/maps/RegionChangeEvent.java new file mode 100644 index 000000000..28a3b322b --- /dev/null +++ b/android/src/main/java/com/airbnb/android/react/maps/RegionChangeEvent.java @@ -0,0 +1,47 @@ +package com.airbnb.android.react.maps; + +import com.facebook.react.bridge.WritableMap; +import com.facebook.react.bridge.WritableNativeMap; +import com.facebook.react.uimanager.events.Event; +import com.facebook.react.uimanager.events.RCTEventEmitter; +import com.google.android.gms.maps.model.LatLng; +import com.google.android.gms.maps.model.LatLngBounds; + +public class RegionChangeEvent extends Event { + private final LatLngBounds bounds; + private final LatLng center; + private final boolean continuous; + + public RegionChangeEvent(int id, LatLngBounds bounds, LatLng center, boolean continuous) { + super(id); + this.bounds = bounds; + this.center = center; + this.continuous = continuous; + } + + @Override + public String getEventName() { + return "topChange"; + } + + @Override + public boolean canCoalesce() { + return false; + } + + @Override + public void dispatch(RCTEventEmitter rctEventEmitter) { + + WritableMap event = new WritableNativeMap(); + event.putBoolean("continuous", continuous); + + WritableMap region = new WritableNativeMap(); + region.putDouble("latitude", center.latitude); + region.putDouble("longitude", center.longitude); + region.putDouble("latitudeDelta", bounds.northeast.latitude - bounds.southwest.latitude); + region.putDouble("longitudeDelta", bounds.northeast.longitude - bounds.southwest.longitude); + event.putMap("region", region); + + rctEventEmitter.receiveEvent(getViewTag(), getEventName(), event); + } +} diff --git a/android/src/main/java/com/airbnb/android/react/maps/SizeReportingShadowNode.java b/android/src/main/java/com/airbnb/android/react/maps/SizeReportingShadowNode.java new file mode 100644 index 000000000..40ace480f --- /dev/null +++ b/android/src/main/java/com/airbnb/android/react/maps/SizeReportingShadowNode.java @@ -0,0 +1,31 @@ +/** + * Copyright (c) 2015-present, Facebook, Inc. + * All rights reserved. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ + +package com.airbnb.android.react.maps; + +import com.facebook.react.uimanager.LayoutShadowNode; +import com.facebook.react.uimanager.UIViewOperationQueue; + +import java.util.HashMap; +import java.util.Map; + +// Custom LayoutShadowNode implementation used in conjunction with the AirMapManager +// which sends the width/height of the view after layout occurs. +public class SizeReportingShadowNode extends LayoutShadowNode { + + @Override + public void onCollectExtraUpdates(UIViewOperationQueue uiViewOperationQueue) { + super.onCollectExtraUpdates(uiViewOperationQueue); + + Map data = new HashMap<>(); + data.put("width", getLayoutWidth()); + data.put("height", getLayoutHeight()); + + uiViewOperationQueue.enqueueUpdateExtraData(getReactTag(), data); + } +} From 9e4a03bd5ab815f4870b330ea3b4599d812c9d5d Mon Sep 17 00:00:00 2001 From: Chris Knepper Date: Thu, 25 Aug 2016 21:22:01 -0400 Subject: [PATCH 0015/1148] -Update requirements and structure in package.json -Consistent maven URLs --- android/build.gradle | 2 +- package.json | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/android/build.gradle b/android/build.gradle index f2e0a1f43..3e22dc951 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -8,7 +8,7 @@ buildscript { mavenLocal() jcenter() maven { - url "$projectDir/../../../react-native/android" + url "$projectDir/../../react-native/android" } } dependencies { diff --git a/package.json b/package.json index 00a4591f2..6a16afb51 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "description": "React Native Mapview component for iOS + Android", "main": "index.js", "author": "Leland Richardson ", - "version": "0.7.1", + "version": "0.8.0", "scripts": { "start": "react-native start" }, @@ -22,15 +22,15 @@ ], "peerDependencies": { "react": ">=15.2.0", - "react-native": ">=0.30.0" + "react-native": ">=0.32.0" }, "devDependencies": { "react": "15.2.0", - "react-native": "^0.29.2" + "react-native": "^0.32.0" }, "rnpm": { "android": { - "sourceDir": "./android/lib" + "sourceDir": "./android" } } } From e77765d91ece5f36073907fe25725770a6972dd7 Mon Sep 17 00:00:00 2001 From: Chris Knepper Date: Thu, 25 Aug 2016 21:24:59 -0400 Subject: [PATCH 0016/1148] -Delete old lib files --- android/lib/build.gradle | 33 - android/lib/gradle-maven-push.gradle | 114 --- android/lib/gradle.properties | 18 - android/lib/src/main/AndroidManifest.xml | 6 - .../android/react/maps/AirMapCallout.java | 23 - .../react/maps/AirMapCalloutManager.java | 59 -- .../android/react/maps/AirMapCircle.java | 100 --- .../react/maps/AirMapCircleManager.java | 72 -- .../android/react/maps/AirMapFeature.java | 18 - .../android/react/maps/AirMapManager.java | 290 ------- .../android/react/maps/AirMapMarker.java | 410 ---------- .../react/maps/AirMapMarkerManager.java | 196 ----- .../android/react/maps/AirMapPolygon.java | 111 --- .../react/maps/AirMapPolygonManager.java | 70 -- .../android/react/maps/AirMapPolyline.java | 101 --- .../react/maps/AirMapPolylineManager.java | 65 -- .../airbnb/android/react/maps/AirMapView.java | 744 ------------------ .../android/react/maps/LatLngBoundsUtils.java | 47 -- .../android/react/maps/MapsPackage.java | 46 -- .../android/react/maps/RegionChangeEvent.java | 47 -- .../react/maps/SizeReportingShadowNode.java | 31 - 21 files changed, 2601 deletions(-) delete mode 100644 android/lib/build.gradle delete mode 100644 android/lib/gradle-maven-push.gradle delete mode 100644 android/lib/gradle.properties delete mode 100644 android/lib/src/main/AndroidManifest.xml delete mode 100644 android/lib/src/main/java/com/airbnb/android/react/maps/AirMapCallout.java delete mode 100644 android/lib/src/main/java/com/airbnb/android/react/maps/AirMapCalloutManager.java delete mode 100644 android/lib/src/main/java/com/airbnb/android/react/maps/AirMapCircle.java delete mode 100644 android/lib/src/main/java/com/airbnb/android/react/maps/AirMapCircleManager.java delete mode 100644 android/lib/src/main/java/com/airbnb/android/react/maps/AirMapFeature.java delete mode 100644 android/lib/src/main/java/com/airbnb/android/react/maps/AirMapManager.java delete mode 100644 android/lib/src/main/java/com/airbnb/android/react/maps/AirMapMarker.java delete mode 100644 android/lib/src/main/java/com/airbnb/android/react/maps/AirMapMarkerManager.java delete mode 100644 android/lib/src/main/java/com/airbnb/android/react/maps/AirMapPolygon.java delete mode 100644 android/lib/src/main/java/com/airbnb/android/react/maps/AirMapPolygonManager.java delete mode 100644 android/lib/src/main/java/com/airbnb/android/react/maps/AirMapPolyline.java delete mode 100644 android/lib/src/main/java/com/airbnb/android/react/maps/AirMapPolylineManager.java delete mode 100644 android/lib/src/main/java/com/airbnb/android/react/maps/AirMapView.java delete mode 100644 android/lib/src/main/java/com/airbnb/android/react/maps/LatLngBoundsUtils.java delete mode 100644 android/lib/src/main/java/com/airbnb/android/react/maps/MapsPackage.java delete mode 100644 android/lib/src/main/java/com/airbnb/android/react/maps/RegionChangeEvent.java delete mode 100644 android/lib/src/main/java/com/airbnb/android/react/maps/SizeReportingShadowNode.java diff --git a/android/lib/build.gradle b/android/lib/build.gradle deleted file mode 100644 index 72e074c44..000000000 --- a/android/lib/build.gradle +++ /dev/null @@ -1,33 +0,0 @@ -apply plugin: 'com.android.library' -apply from: 'gradle-maven-push.gradle' - -android { - compileSdkVersion 23 - buildToolsVersion "23.0.3" - - defaultConfig { - minSdkVersion 16 - targetSdkVersion 23 - } - - lintOptions { - disable 'InvalidPackage' - } -} - -allprojects { - repositories { - mavenLocal() - jcenter() - maven { - // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm - url "$projectDir/../../../react-native/android" - } - } -} - -dependencies { - compile 'com.facebook.react:react-native:0.32.0' - compile "com.google.android.gms:play-services-base:8.4.0" - compile 'com.google.android.gms:play-services-maps:8.4.0' -} diff --git a/android/lib/gradle-maven-push.gradle b/android/lib/gradle-maven-push.gradle deleted file mode 100644 index 84bf6163c..000000000 --- a/android/lib/gradle-maven-push.gradle +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright 2013 Chris Banes - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -apply plugin: 'maven' -apply plugin: 'signing' - -def isReleaseBuild() { - return VERSION_NAME.contains("SNAPSHOT") == false -} - -def getReleaseRepositoryUrl() { - return hasProperty('RELEASE_REPOSITORY_URL') ? RELEASE_REPOSITORY_URL - : "https://oss.sonatype.org/service/local/staging/deploy/maven2/" -} - -def getSnapshotRepositoryUrl() { - return hasProperty('SNAPSHOT_REPOSITORY_URL') ? SNAPSHOT_REPOSITORY_URL - : "https://oss.sonatype.org/content/repositories/snapshots/" -} - -def getRepositoryUsername() { - return hasProperty('NEXUS_USERNAME') ? NEXUS_USERNAME : "" -} - -def getRepositoryPassword() { - return hasProperty('NEXUS_PASSWORD') ? NEXUS_PASSWORD : "" -} - -afterEvaluate { project -> - uploadArchives { - repositories { - mavenDeployer { - beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) } - - pom.groupId = GROUP - pom.artifactId = POM_ARTIFACT_ID - pom.version = VERSION_NAME - - repository(url: getReleaseRepositoryUrl()) { - authentication(userName: getRepositoryUsername(), password: getRepositoryPassword()) - } - snapshotRepository(url: getSnapshotRepositoryUrl()) { - authentication(userName: getRepositoryUsername(), password: getRepositoryPassword()) - } - - pom.project { - name POM_NAME - packaging POM_PACKAGING - description POM_DESCRIPTION - url POM_URL - - scm { - url POM_SCM_URL - connection POM_SCM_CONNECTION - developerConnection POM_SCM_DEV_CONNECTION - } - - licenses { - license { - name POM_LICENSE_NAME - url POM_LICENSE_URL - distribution POM_LICENSE_DIST - } - } - - developers { - developer { - id POM_DEVELOPER_ID - name POM_DEVELOPER_NAME - } - } - } - } - } - } - - signing { - required { isReleaseBuild() && gradle.taskGraph.hasTask("uploadArchives") } - sign configurations.archives - } - - task androidJavadocs(type: Javadoc) { - source = android.sourceSets.main.java.srcDirs - classpath += project.files(android.getBootClasspath().join(File.pathSeparator)) - } - - task androidJavadocsJar(type: Jar, dependsOn: androidJavadocs) { - classifier = 'javadoc' - from androidJavadocs.destinationDir - } - - task androidSourcesJar(type: Jar) { - classifier = 'sources' - from android.sourceSets.main.java.sourceFiles - } - - artifacts { - archives androidSourcesJar - archives androidJavadocsJar - } -} \ No newline at end of file diff --git a/android/lib/gradle.properties b/android/lib/gradle.properties deleted file mode 100644 index c86911511..000000000 --- a/android/lib/gradle.properties +++ /dev/null @@ -1,18 +0,0 @@ -VERSION_CODE=2 -VERSION_NAME=0.7.1 -GROUP=com.airbnb.android - -POM_DESCRIPTION=React Native Map view component for Android -POM_URL=https://github.com/lelandrichardson/react-native-maps/tree/new-scv -POM_SCM_URL=https://github.com/lelandrichardson/react-native-maps/tree/new-scv -POM_SCM_CONNECTION=scm:git@github.com:lelandrichardson/react-native-maps.git -POM_SCM_DEV_CONNECTION=scm:git@github.com:lelandrichardson/react-native-maps.git -POM_LICENSE_NAME=MIT -POM_LICENSE_URL=https://github.com/lelandrichardson/react-native-maps/blob/master/LICENSE -POM_LICENSE_DIST=repo -POM_DEVELOPER_ID=lelandrichardson -POM_DEVELOPER_NAME=Leland Richardson - -POM_NAME=ReactNative Maps library -POM_ARTIFACT_ID=react-native-maps -POM_PACKAGING=aar diff --git a/android/lib/src/main/AndroidManifest.xml b/android/lib/src/main/AndroidManifest.xml deleted file mode 100644 index e07e0af89..000000000 --- a/android/lib/src/main/AndroidManifest.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - diff --git a/android/lib/src/main/java/com/airbnb/android/react/maps/AirMapCallout.java b/android/lib/src/main/java/com/airbnb/android/react/maps/AirMapCallout.java deleted file mode 100644 index c434c9c12..000000000 --- a/android/lib/src/main/java/com/airbnb/android/react/maps/AirMapCallout.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.airbnb.android.react.maps; - -import android.content.Context; - -import com.facebook.react.views.view.ReactViewGroup; - -public class AirMapCallout extends ReactViewGroup { - private boolean tooltip = false; - public int width; - public int height; - - public AirMapCallout(Context context) { - super(context); - } - - public void setTooltip(boolean tooltip) { - this.tooltip = tooltip; - } - - public boolean getTooltip() { - return this.tooltip; - } -} diff --git a/android/lib/src/main/java/com/airbnb/android/react/maps/AirMapCalloutManager.java b/android/lib/src/main/java/com/airbnb/android/react/maps/AirMapCalloutManager.java deleted file mode 100644 index 5c21fadd3..000000000 --- a/android/lib/src/main/java/com/airbnb/android/react/maps/AirMapCalloutManager.java +++ /dev/null @@ -1,59 +0,0 @@ -package com.airbnb.android.react.maps; - -import com.facebook.react.common.MapBuilder; -import com.facebook.react.uimanager.LayoutShadowNode; -import com.facebook.react.uimanager.ThemedReactContext; -import com.facebook.react.uimanager.ViewGroupManager; -import com.facebook.react.uimanager.annotations.ReactProp; - -import java.util.Map; - -import javax.annotation.Nullable; - -public class AirMapCalloutManager extends ViewGroupManager { - - @Override - public String getName() { - return "AIRMapCallout"; - } - - @Override - public AirMapCallout createViewInstance(ThemedReactContext context) { - return new AirMapCallout(context); - } - - @ReactProp(name = "tooltip", defaultBoolean = false) - public void setTooltip(AirMapCallout view, boolean tooltip) { - view.setTooltip(tooltip); - } - - @Override - public - @Nullable - Map getExportedCustomDirectEventTypeConstants() { - return MapBuilder.of( - "onPress", MapBuilder.of("registrationName", "onPress") - ); - } - - @Override - public LayoutShadowNode createShadowNodeInstance() { - // we use a custom shadow node that emits the width/height of the view - // after layout with the updateExtraData method. Without this, we can't generate - // a bitmap of the appropriate width/height of the rendered view. - return new SizeReportingShadowNode(); - } - - @Override - public void updateExtraData(AirMapCallout view, Object extraData) { - // This method is called from the shadow node with the width/height of the rendered - // marker view. - //noinspection unchecked - Map data = (Map) extraData; - float width = data.get("width"); - float height = data.get("height"); - view.width = (int) width; - view.height = (int) height; - } - -} diff --git a/android/lib/src/main/java/com/airbnb/android/react/maps/AirMapCircle.java b/android/lib/src/main/java/com/airbnb/android/react/maps/AirMapCircle.java deleted file mode 100644 index e428b04f6..000000000 --- a/android/lib/src/main/java/com/airbnb/android/react/maps/AirMapCircle.java +++ /dev/null @@ -1,100 +0,0 @@ -package com.airbnb.android.react.maps; - -import android.content.Context; - -import com.google.android.gms.maps.GoogleMap; -import com.google.android.gms.maps.model.Circle; -import com.google.android.gms.maps.model.CircleOptions; -import com.google.android.gms.maps.model.LatLng; - -public class AirMapCircle extends AirMapFeature { - - private CircleOptions circleOptions; - private Circle circle; - - private LatLng center; - private double radius; - private int strokeColor; - private int fillColor; - private float strokeWidth; - private float zIndex; - - public AirMapCircle(Context context) { - super(context); - } - - public void setCenter(LatLng center) { - this.center = center; - if (circle != null) { - circle.setCenter(this.center); - } - } - - public void setRadius(double radius) { - this.radius = radius; - if (circle != null) { - circle.setRadius(this.radius); - } - } - - public void setFillColor(int color) { - this.fillColor = color; - if (circle != null) { - circle.setFillColor(color); - } - } - - public void setStrokeColor(int color) { - this.strokeColor = color; - if (circle != null) { - circle.setStrokeColor(color); - } - } - - public void setStrokeWidth(float width) { - this.strokeWidth = width; - if (circle != null) { - circle.setStrokeWidth(width); - } - } - - public void setZIndex(float zIndex) { - this.zIndex = zIndex; - if (circle != null) { - circle.setZIndex(zIndex); - } - } - - public CircleOptions getCircleOptions() { - if (circleOptions == null) { - circleOptions = createCircleOptions(); - } - return circleOptions; - } - - private CircleOptions createCircleOptions() { - CircleOptions options = new CircleOptions(); - options.center(center); - options.radius(radius); - options.fillColor(fillColor); - options.strokeColor(strokeColor); - options.strokeWidth(strokeWidth); - options.zIndex(zIndex); - return options; - } - - @Override - public Object getFeature() { - return circle; - } - - @Override - public void addToMap(GoogleMap map) { - circle = map.addCircle(getCircleOptions()); - } - - @Override - public void removeFromMap(GoogleMap map) { - circle.remove(); - } -} diff --git a/android/lib/src/main/java/com/airbnb/android/react/maps/AirMapCircleManager.java b/android/lib/src/main/java/com/airbnb/android/react/maps/AirMapCircleManager.java deleted file mode 100644 index c0eaf8f14..000000000 --- a/android/lib/src/main/java/com/airbnb/android/react/maps/AirMapCircleManager.java +++ /dev/null @@ -1,72 +0,0 @@ -package com.airbnb.android.react.maps; - -import android.content.Context; -import android.graphics.Color; -import android.os.Build; -import android.util.DisplayMetrics; -import android.view.WindowManager; - -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.ReadableMap; -import com.facebook.react.uimanager.ThemedReactContext; -import com.facebook.react.uimanager.ViewGroupManager; -import com.facebook.react.uimanager.annotations.ReactProp; -import com.google.android.gms.maps.model.LatLng; - -public class AirMapCircleManager extends ViewGroupManager { - private final DisplayMetrics metrics; - - public AirMapCircleManager(ReactApplicationContext reactContext) { - super(); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { - metrics = new DisplayMetrics(); - ((WindowManager) reactContext.getSystemService(Context.WINDOW_SERVICE)) - .getDefaultDisplay() - .getRealMetrics(metrics); - } else { - metrics = reactContext.getResources().getDisplayMetrics(); - } - } - - @Override - public String getName() { - return "AIRMapCircle"; - } - - @Override - public AirMapCircle createViewInstance(ThemedReactContext context) { - return new AirMapCircle(context); - } - - @ReactProp(name = "center") - public void setCenter(AirMapCircle view, ReadableMap center) { - view.setCenter(new LatLng(center.getDouble("latitude"), center.getDouble("longitude"))); - } - - @ReactProp(name = "radius", defaultDouble = 0) - public void setRadius(AirMapCircle view, double radius) { - view.setRadius(radius); - } - - @ReactProp(name = "strokeWidth", defaultFloat = 1f) - public void setStrokeWidth(AirMapCircle view, float widthInPoints) { - float widthInScreenPx = metrics.density * widthInPoints; // done for parity with iOS - view.setStrokeWidth(widthInScreenPx); - } - - @ReactProp(name = "fillColor", defaultInt = Color.RED, customType = "Color") - public void setFillColor(AirMapCircle view, int color) { - view.setFillColor(color); - } - - @ReactProp(name = "strokeColor", defaultInt = Color.RED, customType = "Color") - public void setStrokeColor(AirMapCircle view, int color) { - view.setStrokeColor(color); - } - - @ReactProp(name = "zIndex", defaultFloat = 1.0f) - public void setZIndex(AirMapCircle view, float zIndex) { - view.setZIndex(zIndex); - } - -} diff --git a/android/lib/src/main/java/com/airbnb/android/react/maps/AirMapFeature.java b/android/lib/src/main/java/com/airbnb/android/react/maps/AirMapFeature.java deleted file mode 100644 index 1c15ade5f..000000000 --- a/android/lib/src/main/java/com/airbnb/android/react/maps/AirMapFeature.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.airbnb.android.react.maps; - -import android.content.Context; - -import com.facebook.react.views.view.ReactViewGroup; -import com.google.android.gms.maps.GoogleMap; - -public abstract class AirMapFeature extends ReactViewGroup { - public AirMapFeature(Context context) { - super(context); - } - - public abstract void addToMap(GoogleMap map); - - public abstract void removeFromMap(GoogleMap map); - - public abstract Object getFeature(); -} diff --git a/android/lib/src/main/java/com/airbnb/android/react/maps/AirMapManager.java b/android/lib/src/main/java/com/airbnb/android/react/maps/AirMapManager.java deleted file mode 100644 index 5ca02097b..000000000 --- a/android/lib/src/main/java/com/airbnb/android/react/maps/AirMapManager.java +++ /dev/null @@ -1,290 +0,0 @@ -package com.airbnb.android.react.maps; - -import android.view.View; -import android.content.Context; - -import com.facebook.react.bridge.Arguments; -import com.facebook.react.bridge.ReactContext; -import com.facebook.react.bridge.ReadableArray; -import com.facebook.react.bridge.ReadableMap; -import com.facebook.react.bridge.WritableMap; -import com.facebook.react.common.MapBuilder; -import com.facebook.react.modules.core.DeviceEventManagerModule; -import com.facebook.react.uimanager.LayoutShadowNode; -import com.facebook.react.uimanager.ThemedReactContext; -import com.facebook.react.uimanager.ViewGroupManager; -import com.facebook.react.uimanager.annotations.ReactProp; -import com.facebook.react.uimanager.events.RCTEventEmitter; -import com.google.android.gms.maps.GoogleMap; -import com.google.android.gms.maps.MapsInitializer; -import com.google.android.gms.maps.model.LatLng; -import com.google.android.gms.maps.model.LatLngBounds; - -import java.util.Map; - -import javax.annotation.Nullable; - -public class AirMapManager extends ViewGroupManager { - - private static final String REACT_CLASS = "AIRMap"; - private static final int ANIMATE_TO_REGION = 1; - private static final int ANIMATE_TO_COORDINATE = 2; - private static final int FIT_TO_ELEMENTS = 3; - private static final int FIT_TO_SUPPLIED_MARKERS = 4; - - private final Map MAP_TYPES = MapBuilder.of( - "standard", GoogleMap.MAP_TYPE_NORMAL, - "satellite", GoogleMap.MAP_TYPE_SATELLITE, - "hybrid", GoogleMap.MAP_TYPE_HYBRID, - "terrain", GoogleMap.MAP_TYPE_TERRAIN - ); - - private ReactContext reactContext; - - private final Context appContext; - - public AirMapManager(Context context) { - this.appContext = context; - } - - @Override - public String getName() { - return REACT_CLASS; - } - - @Override - protected AirMapView createViewInstance(ThemedReactContext context) { - reactContext = context; - - try { - MapsInitializer.initialize(this.appContext); - } catch (RuntimeException e) { - e.printStackTrace(); - emitMapError("Map initialize error", "map_init_error"); - } - - return new AirMapView(context, this.appContext, this); - } - - @Override - public void onDropViewInstance(AirMapView view) { - view.doDestroy(); - super.onDropViewInstance(view); - } - - private void emitMapError(String message, String type) { - WritableMap error = Arguments.createMap(); - error.putString("message", message); - error.putString("type", type); - - reactContext - .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class) - .emit("onError", error); - } - - @ReactProp(name = "region") - public void setRegion(AirMapView view, ReadableMap region) { - view.setRegion(region); - } - - @ReactProp(name = "mapType") - public void setMapType(AirMapView view, @Nullable String mapType) { - int typeId = MAP_TYPES.get(mapType); - view.map.setMapType(typeId); - } - - @ReactProp(name = "showsUserLocation", defaultBoolean = false) - public void setShowsUserLocation(AirMapView view, boolean showUserLocation) { - view.setShowsUserLocation(showUserLocation); - } - - @ReactProp(name = "showsMyLocationButton", defaultBoolean = true) - public void setShowsMyLocationButton(AirMapView view, boolean showMyLocationButton) { - view.setShowsMyLocationButton(showMyLocationButton); - } - - @ReactProp(name = "toolbarEnabled", defaultBoolean = true) - public void setToolbarEnabled(AirMapView view, boolean toolbarEnabled) { - view.setToolbarEnabled(toolbarEnabled); - } - - // This is a private prop to improve performance of panDrag by disabling it when the callback is not set - @ReactProp(name = "handlePanDrag", defaultBoolean = false) - public void setHandlePanDrag(AirMapView view, boolean handlePanDrag) { - view.setHandlePanDrag(handlePanDrag); - } - - @ReactProp(name = "showsTraffic", defaultBoolean = false) - public void setShowTraffic(AirMapView view, boolean showTraffic) { - view.map.setTrafficEnabled(showTraffic); - } - - @ReactProp(name = "showsBuildings", defaultBoolean = false) - public void setShowBuildings(AirMapView view, boolean showBuildings) { - view.map.setBuildingsEnabled(showBuildings); - } - - @ReactProp(name = "showsIndoors", defaultBoolean = false) - public void setShowIndoors(AirMapView view, boolean showIndoors) { - view.map.setIndoorEnabled(showIndoors); - } - - @ReactProp(name = "showsCompass", defaultBoolean = false) - public void setShowsCompass(AirMapView view, boolean showsCompass) { - view.map.getUiSettings().setCompassEnabled(showsCompass); - } - - @ReactProp(name = "scrollEnabled", defaultBoolean = false) - public void setScrollEnabled(AirMapView view, boolean scrollEnabled) { - view.map.getUiSettings().setScrollGesturesEnabled(scrollEnabled); - } - - @ReactProp(name = "zoomEnabled", defaultBoolean = false) - public void setZoomEnabled(AirMapView view, boolean zoomEnabled) { - view.map.getUiSettings().setZoomGesturesEnabled(zoomEnabled); - } - - @ReactProp(name = "rotateEnabled", defaultBoolean = false) - public void setRotateEnabled(AirMapView view, boolean rotateEnabled) { - view.map.getUiSettings().setRotateGesturesEnabled(rotateEnabled); - } - - @ReactProp(name="cacheEnabled", defaultBoolean = false) - public void setCacheEnabled(AirMapView view, boolean cacheEnabled) { - view.setCacheEnabled(cacheEnabled); - } - - @ReactProp(name="loadingEnabled", defaultBoolean = false) - public void setLoadingEnabled(AirMapView view, boolean loadingEnabled) { - view.enableMapLoading(loadingEnabled); - } - - @ReactProp(name="loadingBackgroundColor", customType="Color") - public void setLoadingBackgroundColor(AirMapView view, @Nullable Integer loadingBackgroundColor) { - view.setLoadingBackgroundColor(loadingBackgroundColor); - } - - @ReactProp(name="loadingIndicatorColor", customType="Color") - public void setLoadingIndicatorColor(AirMapView view, @Nullable Integer loadingIndicatorColor) { - view.setLoadingIndicatorColor(loadingIndicatorColor); - } - - @ReactProp(name = "pitchEnabled", defaultBoolean = false) - public void setPitchEnabled(AirMapView view, boolean pitchEnabled) { - view.map.getUiSettings().setTiltGesturesEnabled(pitchEnabled); - } - - @Override - public void receiveCommand(AirMapView view, int commandId, @Nullable ReadableArray args) { - Integer duration; - Double lat; - Double lng; - Double lngDelta; - Double latDelta; - ReadableMap region; - - switch (commandId) { - case ANIMATE_TO_REGION: - region = args.getMap(0); - duration = args.getInt(1); - lng = region.getDouble("longitude"); - lat = region.getDouble("latitude"); - lngDelta = region.getDouble("longitudeDelta"); - latDelta = region.getDouble("latitudeDelta"); - LatLngBounds bounds = new LatLngBounds( - new LatLng(lat - latDelta / 2, lng - lngDelta / 2), // southwest - new LatLng(lat + latDelta / 2, lng + lngDelta / 2) // northeast - ); - view.animateToRegion(bounds, duration); - break; - - case ANIMATE_TO_COORDINATE: - region = args.getMap(0); - duration = args.getInt(1); - lng = region.getDouble("longitude"); - lat = region.getDouble("latitude"); - view.animateToCoordinate(new LatLng(lat, lng), duration); - break; - - case FIT_TO_ELEMENTS: - view.fitToElements(args.getBoolean(0)); - break; - - case FIT_TO_SUPPLIED_MARKERS: - view.fitToSuppliedMarkers(args.getArray(0), args.getBoolean(1)); - break; - } - } - - @Override - @Nullable - public Map getExportedCustomDirectEventTypeConstants() { - Map> map = MapBuilder.of( - "onMapReady", MapBuilder.of("registrationName", "onMapReady"), - "onPress", MapBuilder.of("registrationName", "onPress"), - "onLongPress", MapBuilder.of("registrationName", "onLongPress"), - "onMarkerPress", MapBuilder.of("registrationName", "onMarkerPress"), - "onMarkerSelect", MapBuilder.of("registrationName", "onMarkerSelect"), - "onMarkerDeselect", MapBuilder.of("registrationName", "onMarkerDeselect"), - "onCalloutPress", MapBuilder.of("registrationName", "onCalloutPress") - ); - - map.putAll(MapBuilder.of( - "onMarkerDragStart", MapBuilder.of("registrationName", "onMarkerDragStart"), - "onMarkerDrag", MapBuilder.of("registrationName", "onMarkerDrag"), - "onMarkerDragEnd", MapBuilder.of("registrationName", "onMarkerDragEnd"), - "onPanDrag", MapBuilder.of("registrationName", "onPanDrag") - )); - - return map; - } - - @Override - @Nullable - public Map getCommandsMap() { - return MapBuilder.of( - "animateToRegion", ANIMATE_TO_REGION, - "animateToCoordinate", ANIMATE_TO_COORDINATE, - "fitToElements", FIT_TO_ELEMENTS, - "fitToSuppliedMarkers", FIT_TO_SUPPLIED_MARKERS - ); - } - - @Override - public LayoutShadowNode createShadowNodeInstance() { - // A custom shadow node is needed in order to pass back the width/height of the map to the - // view manager so that it can start applying camera moves with bounds. - return new SizeReportingShadowNode(); - } - - @Override - public void addView(AirMapView parent, View child, int index) { - parent.addFeature(child, index); - } - - @Override - public int getChildCount(AirMapView view) { - return view.getFeatureCount(); - } - - @Override - public View getChildAt(AirMapView view, int index) { - return view.getFeatureAt(index); - } - - @Override - public void removeViewAt(AirMapView parent, int index) { - parent.removeFeatureAt(index); - } - - @Override - public void updateExtraData(AirMapView view, Object extraData) { - view.updateExtraData(extraData); - } - - void pushEvent(View view, String name, WritableMap data) { - reactContext.getJSModule(RCTEventEmitter.class) - .receiveEvent(view.getId(), name, data); - } - -} diff --git a/android/lib/src/main/java/com/airbnb/android/react/maps/AirMapMarker.java b/android/lib/src/main/java/com/airbnb/android/react/maps/AirMapMarker.java deleted file mode 100644 index 8623812c2..000000000 --- a/android/lib/src/main/java/com/airbnb/android/react/maps/AirMapMarker.java +++ /dev/null @@ -1,410 +0,0 @@ -package com.airbnb.android.react.maps; - -import android.content.Context; -import android.graphics.Bitmap; -import android.graphics.Canvas; -import android.graphics.drawable.Animatable; -import android.net.Uri; -import android.view.View; -import android.widget.LinearLayout; - -import com.facebook.common.references.CloseableReference; -import com.facebook.datasource.DataSource; -import com.facebook.drawee.backends.pipeline.Fresco; -import com.facebook.drawee.controller.BaseControllerListener; -import com.facebook.drawee.controller.ControllerListener; -import com.facebook.drawee.drawable.ScalingUtils; -import com.facebook.drawee.generic.GenericDraweeHierarchy; -import com.facebook.drawee.generic.GenericDraweeHierarchyBuilder; -import com.facebook.drawee.interfaces.DraweeController; -import com.facebook.drawee.view.DraweeHolder; -import com.facebook.imagepipeline.core.ImagePipeline; -import com.facebook.imagepipeline.image.CloseableImage; -import com.facebook.imagepipeline.image.CloseableStaticBitmap; -import com.facebook.imagepipeline.image.ImageInfo; -import com.facebook.imagepipeline.request.ImageRequest; -import com.facebook.imagepipeline.request.ImageRequestBuilder; -import com.facebook.react.bridge.ReadableMap; -import com.google.android.gms.maps.GoogleMap; -import com.google.android.gms.maps.model.BitmapDescriptor; -import com.google.android.gms.maps.model.BitmapDescriptorFactory; -import com.google.android.gms.maps.model.LatLng; -import com.google.android.gms.maps.model.Marker; -import com.google.android.gms.maps.model.MarkerOptions; - -import javax.annotation.Nullable; - -public class AirMapMarker extends AirMapFeature { - - private MarkerOptions markerOptions; - private Marker marker; - private int width; - private int height; - private String identifier; - - private LatLng position; - private String title; - private String snippet; - - private boolean anchorIsSet; - private float anchorX; - private float anchorY; - - private AirMapCallout calloutView; - private View wrappedCalloutView; - private final Context context; - - private float markerHue = 0.0f; // should be between 0 and 360 - private BitmapDescriptor iconBitmapDescriptor; - private Bitmap iconBitmap; - - private float rotation = 0.0f; - private boolean flat = false; - private boolean draggable = false; - - private float calloutAnchorX; - private float calloutAnchorY; - private boolean calloutAnchorIsSet; - - private boolean hasCustomMarkerView = false; - - private final DraweeHolder logoHolder; - private DataSource> dataSource; - private final ControllerListener mLogoControllerListener = - new BaseControllerListener() { - @Override - public void onFinalImageSet( - String id, - @Nullable final ImageInfo imageInfo, - @Nullable Animatable animatable) { - CloseableReference imageReference = null; - try { - imageReference = dataSource.getResult(); - if (imageReference != null) { - CloseableImage image = imageReference.get(); - if (image != null && image instanceof CloseableStaticBitmap) { - CloseableStaticBitmap closeableStaticBitmap = (CloseableStaticBitmap) image; - Bitmap bitmap = closeableStaticBitmap.getUnderlyingBitmap(); - if (bitmap != null) { - bitmap = bitmap.copy(Bitmap.Config.ARGB_8888, true); - iconBitmap = bitmap; - iconBitmapDescriptor = BitmapDescriptorFactory.fromBitmap(bitmap); - } - } - } - } finally { - dataSource.close(); - if (imageReference != null) { - CloseableReference.closeSafely(imageReference); - } - } - update(); - } - }; - - public AirMapMarker(Context context) { - super(context); - this.context = context; - logoHolder = DraweeHolder.create(createDraweeHierarchy(), context); - logoHolder.onAttach(); - } - - private GenericDraweeHierarchy createDraweeHierarchy() { - return new GenericDraweeHierarchyBuilder(getResources()) - .setActualImageScaleType(ScalingUtils.ScaleType.FIT_CENTER) - .setFadeDuration(0) - .build(); - } - - public void setCoordinate(ReadableMap coordinate) { - position = new LatLng(coordinate.getDouble("latitude"), coordinate.getDouble("longitude")); - if (marker != null) { - marker.setPosition(position); - } - update(); - } - - public void setIdentifier(String identifier) { - this.identifier = identifier; - update(); - } - - public String getIdentifier() { - return this.identifier; - } - - public void setTitle(String title) { - this.title = title; - if (marker != null) { - marker.setTitle(title); - } - update(); - } - - public void setSnippet(String snippet) { - this.snippet = snippet; - if (marker != null) { - marker.setSnippet(snippet); - } - update(); - } - - public void setRotation(float rotation) { - this.rotation = rotation; - if (marker != null) { - marker.setRotation(rotation); - } - update(); - } - - public void setFlat(boolean flat) { - this.flat = flat; - if (marker != null) { - marker.setFlat(flat); - } - update(); - } - - public void setDraggable(boolean draggable) { - this.draggable = draggable; - if (marker != null) { - marker.setDraggable(draggable); - } - update(); - } - - public void setMarkerHue(float markerHue) { - this.markerHue = markerHue; - update(); - } - - public void setAnchor(double x, double y) { - anchorIsSet = true; - anchorX = (float) x; - anchorY = (float) y; - if (marker != null) { - marker.setAnchor(anchorX, anchorY); - } - update(); - } - - public void setCalloutAnchor(double x, double y) { - calloutAnchorIsSet = true; - calloutAnchorX = (float) x; - calloutAnchorY = (float) y; - if (marker != null) { - marker.setInfoWindowAnchor(calloutAnchorX, calloutAnchorY); - } - update(); - } - - public void setImage(String uri) { - if (uri == null) { - iconBitmapDescriptor = null; - update(); - } else if (uri.startsWith("http://") || uri.startsWith("https://") || - uri.startsWith("file://")) { - ImageRequest imageRequest = ImageRequestBuilder - .newBuilderWithSource(Uri.parse(uri)) - .build(); - - ImagePipeline imagePipeline = Fresco.getImagePipeline(); - dataSource = imagePipeline.fetchDecodedImage(imageRequest, this); - DraweeController controller = Fresco.newDraweeControllerBuilder() - .setImageRequest(imageRequest) - .setControllerListener(mLogoControllerListener) - .setOldController(logoHolder.getController()) - .build(); - logoHolder.setController(controller); - } else { - iconBitmapDescriptor = getBitmapDescriptorByName(uri); - update(); - } - } - - public MarkerOptions getMarkerOptions() { - if (markerOptions == null) { - markerOptions = createMarkerOptions(); - } - return markerOptions; - } - - @Override - public void addView(View child, int index) { - super.addView(child, index); - // if children are added, it means we are rendering a custom marker - if (!(child instanceof AirMapCallout)) { - hasCustomMarkerView = true; - } - update(); - } - - @Override - public Object getFeature() { - return marker; - } - - @Override - public void addToMap(GoogleMap map) { - marker = map.addMarker(getMarkerOptions()); - } - - @Override - public void removeFromMap(GoogleMap map) { - marker.remove(); - marker = null; - } - - private BitmapDescriptor getIcon() { - if (hasCustomMarkerView) { - // creating a bitmap from an arbitrary view - if (iconBitmapDescriptor != null) { - Bitmap viewBitmap = createDrawable(); - int width = Math.max(iconBitmap.getWidth(), viewBitmap.getWidth()); - int height = Math.max(iconBitmap.getHeight(), viewBitmap.getHeight()); - Bitmap combinedBitmap = Bitmap.createBitmap(width, height, iconBitmap.getConfig()); - Canvas canvas = new Canvas(combinedBitmap); - canvas.drawBitmap(iconBitmap, 0, 0, null); - canvas.drawBitmap(viewBitmap, 0, 0, null); - return BitmapDescriptorFactory.fromBitmap(combinedBitmap); - } else { - return BitmapDescriptorFactory.fromBitmap(createDrawable()); - } - } else if (iconBitmapDescriptor != null) { - // use local image as a marker - return iconBitmapDescriptor; - } else { - // render the default marker pin - return BitmapDescriptorFactory.defaultMarker(this.markerHue); - } - } - - private MarkerOptions createMarkerOptions() { - MarkerOptions options = new MarkerOptions().position(position); - if (anchorIsSet) options.anchor(anchorX, anchorY); - if (calloutAnchorIsSet) options.infoWindowAnchor(calloutAnchorX, calloutAnchorY); - options.title(title); - options.snippet(snippet); - options.rotation(rotation); - options.flat(flat); - options.draggable(draggable); - options.icon(getIcon()); - return options; - } - - public void update() { - if (marker == null) { - return; - } - - marker.setIcon(getIcon()); - - if (anchorIsSet) { - marker.setAnchor(anchorX, anchorY); - } else { - marker.setAnchor(0.5f, 1.0f); - } - - if (calloutAnchorIsSet) { - marker.setInfoWindowAnchor(calloutAnchorX, calloutAnchorY); - } else { - marker.setInfoWindowAnchor(0.5f, 0); - } - } - - public void update(int width, int height) { - this.width = width; - this.height = height; - update(); - } - - private Bitmap createDrawable() { - int width = this.width <= 0 ? 100 : this.width; - int height = this.height <= 0 ? 100 : this.height; - this.buildDrawingCache(); - Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); - - Canvas canvas = new Canvas(bitmap); - this.draw(canvas); - - return bitmap; - } - - public void setCalloutView(AirMapCallout view) { - this.calloutView = view; - } - - public AirMapCallout getCalloutView() { - return this.calloutView; - } - - public View getCallout() { - if (this.calloutView == null) return null; - - if (this.wrappedCalloutView == null) { - this.wrapCalloutView(); - } - - if (this.calloutView.getTooltip()) { - return this.wrappedCalloutView; - } else { - return null; - } - } - - public View getInfoContents() { - if (this.calloutView == null) return null; - - if (this.wrappedCalloutView == null) { - this.wrapCalloutView(); - } - - if (this.calloutView.getTooltip()) { - return null; - } else { - return this.wrappedCalloutView; - } - } - - private void wrapCalloutView() { - // some hackery is needed to get the arbitrary infowindow view to render centered, and - // with only the width/height that it needs. - if (this.calloutView == null || this.calloutView.getChildCount() == 0) { - return; - } - - LinearLayout LL = new LinearLayout(context); - LL.setOrientation(LinearLayout.VERTICAL); - LL.setLayoutParams(new LinearLayout.LayoutParams( - this.calloutView.width, - this.calloutView.height, - 0f - )); - - - LinearLayout LL2 = new LinearLayout(context); - LL2.setOrientation(LinearLayout.HORIZONTAL); - LL2.setLayoutParams(new LinearLayout.LayoutParams( - this.calloutView.width, - this.calloutView.height, - 0f - )); - - LL.addView(LL2); - LL2.addView(this.calloutView); - - this.wrappedCalloutView = LL; - } - - private int getDrawableResourceByName(String name) { - return getResources().getIdentifier( - name, - "drawable", - getContext().getPackageName()); - } - - private BitmapDescriptor getBitmapDescriptorByName(String name) { - return BitmapDescriptorFactory.fromResource(getDrawableResourceByName(name)); - } - -} diff --git a/android/lib/src/main/java/com/airbnb/android/react/maps/AirMapMarkerManager.java b/android/lib/src/main/java/com/airbnb/android/react/maps/AirMapMarkerManager.java deleted file mode 100644 index 52a0e6fc7..000000000 --- a/android/lib/src/main/java/com/airbnb/android/react/maps/AirMapMarkerManager.java +++ /dev/null @@ -1,196 +0,0 @@ -package com.airbnb.android.react.maps; - -import android.graphics.Color; -import android.view.View; - -import com.facebook.react.bridge.ReadableArray; -import com.facebook.react.bridge.ReadableMap; -import com.facebook.react.common.MapBuilder; -import com.facebook.react.uimanager.LayoutShadowNode; -import com.facebook.react.uimanager.ThemedReactContext; -import com.facebook.react.uimanager.ViewGroupManager; -import com.facebook.react.uimanager.annotations.ReactProp; -import com.google.android.gms.maps.model.Marker; - -import java.util.HashMap; -import java.util.Map; - -import javax.annotation.Nullable; - -public class AirMapMarkerManager extends ViewGroupManager { - - public static final int SHOW_INFO_WINDOW = 1; - public static final int HIDE_INFO_WINDOW = 2; - - public AirMapMarkerManager() { - } - - @Override - public String getName() { - return "AIRMapMarker"; - } - - @Override - public AirMapMarker createViewInstance(ThemedReactContext context) { - return new AirMapMarker(context); - } - - @ReactProp(name = "coordinate") - public void setCoordinate(AirMapMarker view, ReadableMap map) { - view.setCoordinate(map); - } - - @ReactProp(name = "title") - public void setTitle(AirMapMarker view, String title) { - view.setTitle(title); - } - - @ReactProp(name = "identifier") - public void setIdentifier(AirMapMarker view, String identifier) { - view.setIdentifier(identifier); - } - - @ReactProp(name = "description") - public void setDescription(AirMapMarker view, String description) { - view.setSnippet(description); - } - - // NOTE(lmr): - // android uses normalized coordinate systems for this, and is provided through the - // `anchor` property and `calloutAnchor` instead. Perhaps some work could be done - // to normalize iOS and android to use just one of the systems. -// @ReactProp(name = "centerOffset") -// public void setCenterOffset(AirMapMarker view, ReadableMap map) { -// -// } -// -// @ReactProp(name = "calloutOffset") -// public void setCalloutOffset(AirMapMarker view, ReadableMap map) { -// -// } - - @ReactProp(name = "anchor") - public void setAnchor(AirMapMarker view, ReadableMap map) { - // should default to (0.5, 1) (bottom middle) - double x = map != null && map.hasKey("x") ? map.getDouble("x") : 0.5; - double y = map != null && map.hasKey("y") ? map.getDouble("y") : 1.0; - view.setAnchor(x, y); - } - - @ReactProp(name = "calloutAnchor") - public void setCalloutAnchor(AirMapMarker view, ReadableMap map) { - // should default to (0.5, 0) (top middle) - double x = map != null && map.hasKey("x") ? map.getDouble("x") : 0.5; - double y = map != null && map.hasKey("y") ? map.getDouble("y") : 0.0; - view.setCalloutAnchor(x, y); - } - - @ReactProp(name = "image") - public void setImage(AirMapMarker view, @Nullable String source) { - view.setImage(source); - } -// public void setImage(AirMapMarker view, ReadableMap image) { -// view.setImage(image); -// } - - @ReactProp(name = "pinColor", defaultInt = Color.RED, customType = "Color") - public void setPinColor(AirMapMarker view, int pinColor) { - float[] hsv = new float[3]; - Color.colorToHSV(pinColor, hsv); - // NOTE: android only supports a hue - view.setMarkerHue(hsv[0]); - } - - @ReactProp(name = "rotation", defaultFloat = 0.0f) - public void setMarkerRotation(AirMapMarker view, float rotation) { - view.setRotation(rotation); - } - - @ReactProp(name = "flat", defaultBoolean = false) - public void setFlat(AirMapMarker view, boolean flat) { - view.setFlat(flat); - } - - @ReactProp(name = "draggable", defaultBoolean = false) - public void setDraggable(AirMapMarker view, boolean draggable) { - view.setDraggable(draggable); - } - - @Override - public void addView(AirMapMarker parent, View child, int index) { - // if an component is a child, then it is a callout view, NOT part of the - // marker. - if (child instanceof AirMapCallout) { - parent.setCalloutView((AirMapCallout) child); - } else { - super.addView(parent, child, index); - parent.update(); - } - } - - @Override - public void removeViewAt(AirMapMarker parent, int index) { - super.removeViewAt(parent, index); - parent.update(); - } - - @Override - @Nullable - public Map getCommandsMap() { - return MapBuilder.of( - "showCallout", SHOW_INFO_WINDOW, - "hideCallout", HIDE_INFO_WINDOW - ); - } - - @Override - public void receiveCommand(AirMapMarker view, int commandId, @Nullable ReadableArray args) { - switch (commandId) { - case SHOW_INFO_WINDOW: - ((Marker) view.getFeature()).showInfoWindow(); - break; - - case HIDE_INFO_WINDOW: - ((Marker) view.getFeature()).hideInfoWindow(); - break; - } - } - - @Override - @Nullable - public Map getExportedCustomDirectEventTypeConstants() { - Map map = MapBuilder.of( - "onPress", MapBuilder.of("registrationName", "onPress"), - "onCalloutPress", MapBuilder.of("registrationName", "onCalloutPress"), - "onDragStart", MapBuilder.of("registrationName", "onDragStart"), - "onDrag", MapBuilder.of("registrationName", "onDrag"), - "onDragEnd", MapBuilder.of("registrationName", "onDragEnd") - ); - - map.putAll(MapBuilder.of( - "onDragStart", MapBuilder.of("registrationName", "onDragStart"), - "onDrag", MapBuilder.of("registrationName", "onDrag"), - "onDragEnd", MapBuilder.of("registrationName", "onDragEnd") - )); - - return map; - } - - @Override - public LayoutShadowNode createShadowNodeInstance() { - // we use a custom shadow node that emits the width/height of the view - // after layout with the updateExtraData method. Without this, we can't generate - // a bitmap of the appropriate width/height of the rendered view. - return new SizeReportingShadowNode(); - } - - @Override - public void updateExtraData(AirMapMarker view, Object extraData) { - // This method is called from the shadow node with the width/height of the rendered - // marker view. - HashMap data = (HashMap) extraData; - float width = data.get("width"); - float height = data.get("height"); - view.update((int) width, (int) height); - } -} diff --git a/android/lib/src/main/java/com/airbnb/android/react/maps/AirMapPolygon.java b/android/lib/src/main/java/com/airbnb/android/react/maps/AirMapPolygon.java deleted file mode 100644 index 166172795..000000000 --- a/android/lib/src/main/java/com/airbnb/android/react/maps/AirMapPolygon.java +++ /dev/null @@ -1,111 +0,0 @@ -package com.airbnb.android.react.maps; - -import android.content.Context; - -import com.facebook.react.bridge.ReadableArray; -import com.facebook.react.bridge.ReadableMap; -import com.google.android.gms.maps.GoogleMap; -import com.google.android.gms.maps.model.LatLng; -import com.google.android.gms.maps.model.Polygon; -import com.google.android.gms.maps.model.PolygonOptions; - -import java.util.ArrayList; -import java.util.List; - -public class AirMapPolygon extends AirMapFeature { - - private PolygonOptions polygonOptions; - private Polygon polygon; - - private List coordinates; - private int strokeColor; - private int fillColor; - private float strokeWidth; - private boolean geodesic; - private float zIndex; - - public AirMapPolygon(Context context) { - super(context); - } - - public void setCoordinates(ReadableArray coordinates) { - // it's kind of a bummer that we can't run map() or anything on the ReadableArray - this.coordinates = new ArrayList<>(coordinates.size()); - for (int i = 0; i < coordinates.size(); i++) { - ReadableMap coordinate = coordinates.getMap(i); - this.coordinates.add(i, - new LatLng(coordinate.getDouble("latitude"), coordinate.getDouble("longitude"))); - } - if (polygon != null) { - polygon.setPoints(this.coordinates); - } - } - - public void setFillColor(int color) { - this.fillColor = color; - if (polygon != null) { - polygon.setFillColor(color); - } - } - - public void setStrokeColor(int color) { - this.strokeColor = color; - if (polygon != null) { - polygon.setStrokeColor(color); - } - } - - public void setStrokeWidth(float width) { - this.strokeWidth = width; - if (polygon != null) { - polygon.setStrokeWidth(width); - } - } - - public void setGeodesic(boolean geodesic) { - this.geodesic = geodesic; - if (polygon != null) { - polygon.setGeodesic(geodesic); - } - } - - public void setZIndex(float zIndex) { - this.zIndex = zIndex; - if (polygon != null) { - polygon.setZIndex(zIndex); - } - } - - public PolygonOptions getPolygonOptions() { - if (polygonOptions == null) { - polygonOptions = createPolygonOptions(); - } - return polygonOptions; - } - - private PolygonOptions createPolygonOptions() { - PolygonOptions options = new PolygonOptions(); - options.addAll(coordinates); - options.fillColor(fillColor); - options.strokeColor(strokeColor); - options.strokeWidth(strokeWidth); - options.geodesic(geodesic); - options.zIndex(zIndex); - return options; - } - - @Override - public Object getFeature() { - return polygon; - } - - @Override - public void addToMap(GoogleMap map) { - polygon = map.addPolygon(getPolygonOptions()); - } - - @Override - public void removeFromMap(GoogleMap map) { - polygon.remove(); - } -} diff --git a/android/lib/src/main/java/com/airbnb/android/react/maps/AirMapPolygonManager.java b/android/lib/src/main/java/com/airbnb/android/react/maps/AirMapPolygonManager.java deleted file mode 100644 index f08ce0289..000000000 --- a/android/lib/src/main/java/com/airbnb/android/react/maps/AirMapPolygonManager.java +++ /dev/null @@ -1,70 +0,0 @@ -package com.airbnb.android.react.maps; - -import android.content.Context; -import android.graphics.Color; -import android.os.Build; -import android.util.DisplayMetrics; -import android.view.WindowManager; - -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.ReadableArray; -import com.facebook.react.uimanager.ThemedReactContext; -import com.facebook.react.uimanager.ViewGroupManager; -import com.facebook.react.uimanager.annotations.ReactProp; - -public class AirMapPolygonManager extends ViewGroupManager { - private final DisplayMetrics metrics; - - public AirMapPolygonManager(ReactApplicationContext reactContext) { - super(); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { - metrics = new DisplayMetrics(); - ((WindowManager) reactContext.getSystemService(Context.WINDOW_SERVICE)) - .getDefaultDisplay() - .getRealMetrics(metrics); - } else { - metrics = reactContext.getResources().getDisplayMetrics(); - } - } - - @Override - public String getName() { - return "AIRMapPolygon"; - } - - @Override - public AirMapPolygon createViewInstance(ThemedReactContext context) { - return new AirMapPolygon(context); - } - - @ReactProp(name = "coordinates") - public void setCoordinate(AirMapPolygon view, ReadableArray coordinates) { - view.setCoordinates(coordinates); - } - - @ReactProp(name = "strokeWidth", defaultFloat = 1f) - public void setStrokeWidth(AirMapPolygon view, float widthInPoints) { - float widthInScreenPx = metrics.density * widthInPoints; // done for parity with iOS - view.setStrokeWidth(widthInScreenPx); - } - - @ReactProp(name = "fillColor", defaultInt = Color.RED, customType = "Color") - public void setFillColor(AirMapPolygon view, int color) { - view.setFillColor(color); - } - - @ReactProp(name = "strokeColor", defaultInt = Color.RED, customType = "Color") - public void setStrokeColor(AirMapPolygon view, int color) { - view.setStrokeColor(color); - } - - @ReactProp(name = "geodesic", defaultBoolean = false) - public void setGeodesic(AirMapPolygon view, boolean geodesic) { - view.setGeodesic(geodesic); - } - - @ReactProp(name = "zIndex", defaultFloat = 1.0f) - public void setZIndex(AirMapPolygon view, float zIndex) { - view.setZIndex(zIndex); - } -} diff --git a/android/lib/src/main/java/com/airbnb/android/react/maps/AirMapPolyline.java b/android/lib/src/main/java/com/airbnb/android/react/maps/AirMapPolyline.java deleted file mode 100644 index cf15dfadf..000000000 --- a/android/lib/src/main/java/com/airbnb/android/react/maps/AirMapPolyline.java +++ /dev/null @@ -1,101 +0,0 @@ -package com.airbnb.android.react.maps; - -import android.content.Context; - -import com.facebook.react.bridge.ReadableArray; -import com.facebook.react.bridge.ReadableMap; -import com.google.android.gms.maps.GoogleMap; -import com.google.android.gms.maps.model.LatLng; -import com.google.android.gms.maps.model.Polyline; -import com.google.android.gms.maps.model.PolylineOptions; - -import java.util.ArrayList; -import java.util.List; - -public class AirMapPolyline extends AirMapFeature { - - private PolylineOptions polylineOptions; - private Polyline polyline; - - private List coordinates; - private int color; - private float width; - private boolean geodesic; - private float zIndex; - - public AirMapPolyline(Context context) { - super(context); - } - - public void setCoordinates(ReadableArray coordinates) { - this.coordinates = new ArrayList<>(coordinates.size()); - for (int i = 0; i < coordinates.size(); i++) { - ReadableMap coordinate = coordinates.getMap(i); - this.coordinates.add(i, - new LatLng(coordinate.getDouble("latitude"), coordinate.getDouble("longitude"))); - } - if (polyline != null) { - polyline.setPoints(this.coordinates); - } - } - - public void setColor(int color) { - this.color = color; - if (polyline != null) { - polyline.setColor(color); - } - } - - public void setWidth(float width) { - this.width = width; - if (polyline != null) { - polyline.setWidth(width); - } - } - - public void setZIndex(float zIndex) { - this.zIndex = zIndex; - if (polyline != null) { - polyline.setZIndex(zIndex); - } - } - - public void setGeodesic(boolean geodesic) { - this.geodesic = geodesic; - if (polyline != null) { - polyline.setGeodesic(geodesic); - } - } - - public PolylineOptions getPolylineOptions() { - if (polylineOptions == null) { - polylineOptions = createPolylineOptions(); - } - return polylineOptions; - } - - private PolylineOptions createPolylineOptions() { - PolylineOptions options = new PolylineOptions(); - options.addAll(coordinates); - options.color(color); - options.width(width); - options.geodesic(geodesic); - options.zIndex(zIndex); - return options; - } - - @Override - public Object getFeature() { - return polyline; - } - - @Override - public void addToMap(GoogleMap map) { - polyline = map.addPolyline(getPolylineOptions()); - } - - @Override - public void removeFromMap(GoogleMap map) { - polyline.remove(); - } -} diff --git a/android/lib/src/main/java/com/airbnb/android/react/maps/AirMapPolylineManager.java b/android/lib/src/main/java/com/airbnb/android/react/maps/AirMapPolylineManager.java deleted file mode 100644 index 89edc861e..000000000 --- a/android/lib/src/main/java/com/airbnb/android/react/maps/AirMapPolylineManager.java +++ /dev/null @@ -1,65 +0,0 @@ -package com.airbnb.android.react.maps; - -import android.content.Context; -import android.graphics.Color; -import android.os.Build; -import android.util.DisplayMetrics; -import android.view.WindowManager; - -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.ReadableArray; -import com.facebook.react.uimanager.ThemedReactContext; -import com.facebook.react.uimanager.ViewGroupManager; -import com.facebook.react.uimanager.annotations.ReactProp; - -public class AirMapPolylineManager extends ViewGroupManager { - private final DisplayMetrics metrics; - - public AirMapPolylineManager(ReactApplicationContext reactContext) { - super(); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { - metrics = new DisplayMetrics(); - ((WindowManager) reactContext.getSystemService(Context.WINDOW_SERVICE)) - .getDefaultDisplay() - .getRealMetrics(metrics); - } else { - metrics = reactContext.getResources().getDisplayMetrics(); - } - } - - @Override - public String getName() { - return "AIRMapPolyline"; - } - - @Override - public AirMapPolyline createViewInstance(ThemedReactContext context) { - return new AirMapPolyline(context); - } - - @ReactProp(name = "coordinates") - public void setCoordinate(AirMapPolyline view, ReadableArray coordinates) { - view.setCoordinates(coordinates); - } - - @ReactProp(name = "strokeWidth", defaultFloat = 1f) - public void setStrokeWidth(AirMapPolyline view, float widthInPoints) { - float widthInScreenPx = metrics.density * widthInPoints; // done for parity with iOS - view.setWidth(widthInScreenPx); - } - - @ReactProp(name = "strokeColor", defaultInt = Color.RED, customType = "Color") - public void setStrokeColor(AirMapPolyline view, int color) { - view.setColor(color); - } - - @ReactProp(name = "geodesic", defaultBoolean = false) - public void setGeodesic(AirMapPolyline view, boolean geodesic) { - view.setGeodesic(geodesic); - } - - @ReactProp(name = "zIndex", defaultFloat = 1.0f) - public void setZIndex(AirMapPolyline view, float zIndex) { - view.setZIndex(zIndex); - } -} diff --git a/android/lib/src/main/java/com/airbnb/android/react/maps/AirMapView.java b/android/lib/src/main/java/com/airbnb/android/react/maps/AirMapView.java deleted file mode 100644 index b817f804f..000000000 --- a/android/lib/src/main/java/com/airbnb/android/react/maps/AirMapView.java +++ /dev/null @@ -1,744 +0,0 @@ -package com.airbnb.android.react.maps; - -import android.content.pm.PackageManager; -import android.content.res.ColorStateList; -import android.graphics.Bitmap; -import android.graphics.Color; -import android.graphics.Point; -import android.graphics.PorterDuff; -import android.os.Handler; -import android.os.Build; -import android.support.v4.view.GestureDetectorCompat; -import android.support.v4.view.MotionEventCompat; -import android.view.GestureDetector; -import android.view.MotionEvent; -import android.view.ScaleGestureDetector; -import android.view.View; -import android.view.View.OnLayoutChangeListener; -import android.content.Context; - -import android.view.ViewGroup; -import android.widget.ImageView; -import android.widget.ProgressBar; -import android.widget.RelativeLayout; -import android.widget.TextView; -import com.facebook.react.bridge.LifecycleEventListener; -import com.facebook.react.bridge.ReadableArray; -import com.facebook.react.bridge.ReadableMap; -import com.facebook.react.bridge.WritableMap; -import com.facebook.react.bridge.WritableNativeMap; -import com.facebook.react.uimanager.ThemedReactContext; -import com.facebook.react.uimanager.UIManagerModule; -import com.facebook.react.uimanager.events.EventDispatcher; -import com.google.android.gms.maps.CameraUpdate; -import com.google.android.gms.maps.CameraUpdateFactory; -import com.google.android.gms.maps.GoogleMap; -import com.google.android.gms.maps.MapView; -import com.google.android.gms.maps.OnMapReadyCallback; -import com.google.android.gms.maps.Projection; -import com.google.android.gms.maps.model.CameraPosition; -import com.google.android.gms.maps.model.Circle; -import com.google.android.gms.maps.model.LatLng; -import com.google.android.gms.maps.model.LatLngBounds; -import com.google.android.gms.maps.model.Marker; -import com.google.android.gms.maps.model.Polygon; -import com.google.android.gms.maps.model.Polyline; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import static android.support.v4.content.PermissionChecker.checkSelfPermission; - -public class AirMapView extends MapView implements GoogleMap.InfoWindowAdapter, - GoogleMap.OnMarkerDragListener, OnMapReadyCallback { - public GoogleMap map; - - private ProgressBar mapLoadingProgressBar; - private RelativeLayout mapLoadingLayout; - private ImageView cacheImageView; - private Boolean isMapLoaded = false; - private Integer loadingBackgroundColor = null; - private Integer loadingIndicatorColor = null; - - private LatLngBounds boundsToMove; - private boolean showUserLocation = false; - private boolean isMonitoringRegion = false; - private boolean isTouchDown = false; - private boolean handlePanDrag = false; - private boolean cacheEnabled = false; - private boolean loadingEnabled = false; - - private static final String[] PERMISSIONS = new String[] { - "android.permission.ACCESS_FINE_LOCATION", "android.permission.ACCESS_COARSE_LOCATION"}; - - private final List features = new ArrayList<>(); - private final Map markerMap = new HashMap<>(); - private final Map polylineMap = new HashMap<>(); - private final Map polygonMap = new HashMap<>(); - private final Map circleMap = new HashMap<>(); - - private final ScaleGestureDetector scaleDetector; - private final GestureDetectorCompat gestureDetector; - private final AirMapManager manager; - private LifecycleEventListener lifecycleListener; - private OnLayoutChangeListener onLayoutChangeListener; - private boolean paused = false; - private ThemedReactContext context; - - final EventDispatcher eventDispatcher; - - public AirMapView(ThemedReactContext context, Context appContext, AirMapManager manager) { - super(appContext); - this.manager = manager; - this.context = context; - - super.onCreate(null); - super.onResume(); - super.getMapAsync(this); - - final AirMapView view = this; - scaleDetector = - new ScaleGestureDetector(context, new ScaleGestureDetector.SimpleOnScaleGestureListener() { -// @Override -// public boolean onScale(ScaleGestureDetector detector) { -// Log.d("AirMapView", "onScale"); -// return false; -// } - - @Override - public boolean onScaleBegin(ScaleGestureDetector detector) { - view.startMonitoringRegion(); - return true; // stop recording this gesture. let mapview handle it. - } - }); - - gestureDetector = - new GestureDetectorCompat(context, new GestureDetector.SimpleOnGestureListener() { - @Override - public boolean onDoubleTap(MotionEvent e) { - view.startMonitoringRegion(); - return false; - } - - @Override - public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, - float distanceY) { - if (handlePanDrag) { - onPanDrag(e2); - } - view.startMonitoringRegion(); - return false; - } - }); - - onLayoutChangeListener = new OnLayoutChangeListener() { - @Override public void onLayoutChange(View v, int left, int top, int right, int bottom, - int oldLeft, int oldTop, int oldRight, int oldBottom) { - if (!AirMapView.this.paused) { - AirMapView.this.cacheView(); - } - } - }; - this.addOnLayoutChangeListener(this.onLayoutChangeListener); - - eventDispatcher = context.getNativeModule(UIManagerModule.class).getEventDispatcher(); - } - - @Override - public void onMapReady(final GoogleMap map) { - this.map = map; - this.map.setInfoWindowAdapter(this); - this.map.setOnMarkerDragListener(this); - - manager.pushEvent(this, "onMapReady", new WritableNativeMap()); - - final AirMapView view = this; - - map.setOnMarkerClickListener(new GoogleMap.OnMarkerClickListener() { - @Override - public boolean onMarkerClick(Marker marker) { - WritableMap event; - - event = makeClickEventData(marker.getPosition()); - event.putString("action", "marker-press"); - manager.pushEvent(view, "onMarkerPress", event); - - event = makeClickEventData(marker.getPosition()); - event.putString("action", "marker-press"); - manager.pushEvent(markerMap.get(marker), "onPress", event); - - return false; // returning false opens the callout window, if possible - } - }); - - map.setOnInfoWindowClickListener(new GoogleMap.OnInfoWindowClickListener() { - @Override - public void onInfoWindowClick(Marker marker) { - WritableMap event; - - event = makeClickEventData(marker.getPosition()); - event.putString("action", "callout-press"); - manager.pushEvent(view, "onCalloutPress", event); - - event = makeClickEventData(marker.getPosition()); - event.putString("action", "callout-press"); - AirMapMarker markerView = markerMap.get(marker); - manager.pushEvent(markerView, "onCalloutPress", event); - - event = makeClickEventData(marker.getPosition()); - event.putString("action", "callout-press"); - AirMapCallout infoWindow = markerView.getCalloutView(); - if (infoWindow != null) manager.pushEvent(infoWindow, "onPress", event); - } - }); - - map.setOnMapClickListener(new GoogleMap.OnMapClickListener() { - @Override - public void onMapClick(LatLng point) { - WritableMap event = makeClickEventData(point); - event.putString("action", "press"); - manager.pushEvent(view, "onPress", event); - } - }); - - map.setOnMapLongClickListener(new GoogleMap.OnMapLongClickListener() { - @Override - public void onMapLongClick(LatLng point) { - WritableMap event = makeClickEventData(point); - event.putString("action", "long-press"); - manager.pushEvent(view, "onLongPress", makeClickEventData(point)); - } - }); - - map.setOnCameraChangeListener(new GoogleMap.OnCameraChangeListener() { - @Override - public void onCameraChange(CameraPosition position) { - LatLngBounds bounds = map.getProjection().getVisibleRegion().latLngBounds; - LatLng center = position.target; - lastBoundsEmitted = bounds; - eventDispatcher.dispatchEvent(new RegionChangeEvent(getId(), bounds, center, isTouchDown)); - view.stopMonitoringRegion(); - } - }); - - map.setOnMapLoadedCallback(new GoogleMap.OnMapLoadedCallback() { - @Override public void onMapLoaded() { - isMapLoaded = true; - AirMapView.this.cacheView(); - } - }); - - // We need to be sure to disable location-tracking when app enters background, in-case some - // other module - // has acquired a wake-lock and is controlling location-updates, otherwise, location-manager - // will be left - // updating location constantly, killing the battery, even though some other location-mgmt - // module may - // desire to shut-down location-services. - lifecycleListener = new LifecycleEventListener() { - @Override - public void onHostResume() { - if (hasPermissions()) { - //noinspection MissingPermission - map.setMyLocationEnabled(showUserLocation); - } - synchronized (AirMapView.this) { - AirMapView.this.onResume(); - paused = false; - } - } - - @Override - public void onHostPause() { - if (hasPermissions()) { - //noinspection MissingPermission - map.setMyLocationEnabled(false); - } - synchronized (AirMapView.this) { - AirMapView.this.onPause(); - paused = true; - } - } - - @Override - public void onHostDestroy() { - AirMapView.this.doDestroy(); - } - }; - - context.addLifecycleEventListener(lifecycleListener); - } - - private boolean hasPermissions() { - return checkSelfPermission(getContext(), PERMISSIONS[0]) == PackageManager.PERMISSION_GRANTED || - checkSelfPermission(getContext(), PERMISSIONS[1]) == PackageManager.PERMISSION_GRANTED; - } - - /* - onDestroy is final method so I can't override it. - */ - public synchronized void doDestroy() { - if (lifecycleListener != null) { - context.removeLifecycleEventListener(lifecycleListener); - lifecycleListener = null; - } - if (!paused) { - onPause(); - } - onDestroy(); - } - - public void setRegion(ReadableMap region) { - if (region == null) return; - - Double lng = region.getDouble("longitude"); - Double lat = region.getDouble("latitude"); - Double lngDelta = region.getDouble("longitudeDelta"); - Double latDelta = region.getDouble("latitudeDelta"); - LatLngBounds bounds = new LatLngBounds( - new LatLng(lat - latDelta / 2, lng - lngDelta / 2), // southwest - new LatLng(lat + latDelta / 2, lng + lngDelta / 2) // northeast - ); - if (super.getHeight() <= 0 || super.getWidth() <= 0) { - // in this case, our map has not been laid out yet, so we save the bounds in a local - // variable, and make a guess of zoomLevel 10. Not to worry, though: as soon as layout - // occurs, we will move the camera to the saved bounds. Note that if we tried to move - // to the bounds now, it would trigger an exception. - map.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(lat, lng), 10)); - boundsToMove = bounds; - } else { - map.moveCamera(CameraUpdateFactory.newLatLngBounds(bounds, 0)); - boundsToMove = null; - } - } - - public void setShowsUserLocation(boolean showUserLocation) { - this.showUserLocation = showUserLocation; // hold onto this for lifecycle handling - if (hasPermissions()) { - //noinspection MissingPermission - map.setMyLocationEnabled(showUserLocation); - } - } - - public void setShowsMyLocationButton(boolean showMyLocationButton) { - if (hasPermissions()) { - map.getUiSettings().setMyLocationButtonEnabled(showMyLocationButton); - } - } - - public void setToolbarEnabled(boolean toolbarEnabled) { - if (hasPermissions()) { - map.getUiSettings().setMapToolbarEnabled(toolbarEnabled); - } - } - - public void setCacheEnabled(boolean cacheEnabled) { - this.cacheEnabled = cacheEnabled; - this.cacheView(); - } - - public void enableMapLoading(boolean loadingEnabled) { - if (loadingEnabled && !this.isMapLoaded) { - this.getMapLoadingLayoutView().setVisibility(View.VISIBLE); - } - } - - public void setLoadingBackgroundColor(Integer loadingBackgroundColor) { - this.loadingBackgroundColor = loadingBackgroundColor; - - if (this.mapLoadingLayout != null) { - if (loadingBackgroundColor == null) { - this.mapLoadingLayout.setBackgroundColor(Color.WHITE); - } else { - this.mapLoadingLayout.setBackgroundColor(this.loadingBackgroundColor); - } - } - } - - public void setLoadingIndicatorColor(Integer loadingIndicatorColor) { - this.loadingIndicatorColor = loadingIndicatorColor; - if (this.mapLoadingProgressBar != null) { - Integer color = loadingIndicatorColor; - if (color == null) { - color = Color.parseColor("#606060"); - } - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - ColorStateList progressTintList = ColorStateList.valueOf(loadingIndicatorColor); - ColorStateList secondaryProgressTintList = ColorStateList.valueOf(loadingIndicatorColor); - ColorStateList indeterminateTintList = ColorStateList.valueOf(loadingIndicatorColor); - - this.mapLoadingProgressBar.setProgressTintList(progressTintList); - this.mapLoadingProgressBar.setSecondaryProgressTintList(secondaryProgressTintList); - this.mapLoadingProgressBar.setIndeterminateTintList(indeterminateTintList); - } else { - PorterDuff.Mode mode = PorterDuff.Mode.SRC_IN; - if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.GINGERBREAD_MR1) { - mode = PorterDuff.Mode.MULTIPLY; - } - if (this.mapLoadingProgressBar.getIndeterminateDrawable() != null) - this.mapLoadingProgressBar.getIndeterminateDrawable().setColorFilter(color, mode); - if (this.mapLoadingProgressBar.getProgressDrawable() != null) - this.mapLoadingProgressBar.getProgressDrawable().setColorFilter(color, mode); - } - } - } - - public void setHandlePanDrag(boolean handlePanDrag) { - this.handlePanDrag = handlePanDrag; - } - - public void addFeature(View child, int index) { - // Our desired API is to pass up annotations/overlays as children to the mapview component. - // This is where we intercept them and do the appropriate underlying mapview action. - if (child instanceof AirMapMarker) { - AirMapMarker annotation = (AirMapMarker) child; - annotation.addToMap(map); - features.add(index, annotation); - Marker marker = (Marker) annotation.getFeature(); - markerMap.put(marker, annotation); - } else if (child instanceof AirMapPolyline) { - AirMapPolyline polylineView = (AirMapPolyline) child; - polylineView.addToMap(map); - features.add(index, polylineView); - Polyline polyline = (Polyline) polylineView.getFeature(); - polylineMap.put(polyline, polylineView); - } else if (child instanceof AirMapPolygon) { - AirMapPolygon polygonView = (AirMapPolygon) child; - polygonView.addToMap(map); - features.add(index, polygonView); - Polygon polygon = (Polygon) polygonView.getFeature(); - polygonMap.put(polygon, polygonView); - } else if (child instanceof AirMapCircle) { - AirMapCircle circleView = (AirMapCircle) child; - circleView.addToMap(map); - features.add(index, circleView); - Circle circle = (Circle) circleView.getFeature(); - circleMap.put(circle, circleView); - } else { - // TODO(lmr): throw? User shouldn't be adding non-feature children. - } - } - - public int getFeatureCount() { - return features.size(); - } - - public View getFeatureAt(int index) { - return features.get(index); - } - - public void removeFeatureAt(int index) { - AirMapFeature feature = features.remove(index); - - - if (feature instanceof AirMapMarker) { - markerMap.remove(feature.getFeature()); - } else if (feature instanceof AirMapPolyline) { - polylineMap.remove(feature.getFeature()); - } else if (feature instanceof AirMapPolygon) { - polygonMap.remove(feature.getFeature()); - } else if (feature instanceof AirMapCircle) { - circleMap.remove(feature.getFeature()); - } - feature.removeFromMap(map); - } - - public WritableMap makeClickEventData(LatLng point) { - WritableMap event = new WritableNativeMap(); - - WritableMap coordinate = new WritableNativeMap(); - coordinate.putDouble("latitude", point.latitude); - coordinate.putDouble("longitude", point.longitude); - event.putMap("coordinate", coordinate); - - Projection projection = map.getProjection(); - Point screenPoint = projection.toScreenLocation(point); - - WritableMap position = new WritableNativeMap(); - position.putDouble("x", screenPoint.x); - position.putDouble("y", screenPoint.y); - event.putMap("position", position); - - return event; - } - - public void updateExtraData(Object extraData) { - // if boundsToMove is not null, we now have the MapView's width/height, so we can apply - // a proper camera move - if (boundsToMove != null) { - HashMap data = (HashMap) extraData; - float width = data.get("width"); - float height = data.get("height"); - map.moveCamera( - CameraUpdateFactory.newLatLngBounds( - boundsToMove, - (int) width, - (int) height, - 0 - ) - ); - boundsToMove = null; - } - } - - public void animateToRegion(LatLngBounds bounds, int duration) { - startMonitoringRegion(); - map.animateCamera(CameraUpdateFactory.newLatLngBounds(bounds, 0), duration, null); - } - - public void animateToCoordinate(LatLng coordinate, int duration) { - startMonitoringRegion(); - map.animateCamera(CameraUpdateFactory.newLatLng(coordinate), duration, null); - } - - public void fitToElements(boolean animated) { - LatLngBounds.Builder builder = new LatLngBounds.Builder(); - for (AirMapFeature feature : features) { - if (feature instanceof AirMapMarker) { - Marker marker = (Marker) feature.getFeature(); - builder.include(marker.getPosition()); - } - // TODO(lmr): may want to include shapes / etc. - } - LatLngBounds bounds = builder.build(); - CameraUpdate cu = CameraUpdateFactory.newLatLngBounds(bounds, 50); - if (animated) { - startMonitoringRegion(); - map.animateCamera(cu); - } else { - map.moveCamera(cu); - } - } - - public void fitToSuppliedMarkers(ReadableArray markerIDsArray, boolean animated) { - LatLngBounds.Builder builder = new LatLngBounds.Builder(); - - String[] markerIDs = new String[markerIDsArray.size()]; - for (int i = 0; i < markerIDsArray.size(); i++) { - markerIDs[i] = markerIDsArray.getString(i); - } - - boolean addedPosition = false; - - List markerIDList = Arrays.asList(markerIDs); - - for (AirMapFeature feature : features) { - if (feature instanceof AirMapMarker) { - String identifier = ((AirMapMarker)feature).getIdentifier(); - Marker marker = (Marker)feature.getFeature(); - if (markerIDList.contains(identifier)) { - builder.include(marker.getPosition()); - addedPosition = true; - } - } - } - - if (addedPosition) { - LatLngBounds bounds = builder.build(); - CameraUpdate cu = CameraUpdateFactory.newLatLngBounds(bounds, 50); - if (animated) { - startMonitoringRegion(); - map.animateCamera(cu); - } else { - map.moveCamera(cu); - } - } - } - - // InfoWindowAdapter interface - - @Override - public View getInfoWindow(Marker marker) { - AirMapMarker markerView = markerMap.get(marker); - return markerView.getCallout(); - } - - @Override - public View getInfoContents(Marker marker) { - AirMapMarker markerView = markerMap.get(marker); - return markerView.getInfoContents(); - } - - @Override - public boolean dispatchTouchEvent(MotionEvent ev) { - scaleDetector.onTouchEvent(ev); - gestureDetector.onTouchEvent(ev); - - int action = MotionEventCompat.getActionMasked(ev); - - switch (action) { - case (MotionEvent.ACTION_DOWN): - this.getParent().requestDisallowInterceptTouchEvent(true); - isTouchDown = true; - break; - case (MotionEvent.ACTION_MOVE): - startMonitoringRegion(); - break; - case (MotionEvent.ACTION_UP): - this.getParent().requestDisallowInterceptTouchEvent(false); - isTouchDown = false; - break; - } - super.dispatchTouchEvent(ev); - return true; - } - - // Timer Implementation - - public void startMonitoringRegion() { - if (isMonitoringRegion) return; - timerHandler.postDelayed(timerRunnable, 100); - isMonitoringRegion = true; - } - - public void stopMonitoringRegion() { - if (!isMonitoringRegion) return; - timerHandler.removeCallbacks(timerRunnable); - isMonitoringRegion = false; - } - - private LatLngBounds lastBoundsEmitted; - - Handler timerHandler = new Handler(); - Runnable timerRunnable = new Runnable() { - - @Override - public void run() { - - LatLngBounds bounds = map.getProjection().getVisibleRegion().latLngBounds; - if (lastBoundsEmitted == null || - LatLngBoundsUtils.BoundsAreDifferent(bounds, lastBoundsEmitted)) { - LatLng center = map.getCameraPosition().target; - lastBoundsEmitted = bounds; - eventDispatcher.dispatchEvent(new RegionChangeEvent(getId(), bounds, center, true)); - } - - timerHandler.postDelayed(this, 100); - } - }; - - @Override - public void onMarkerDragStart(Marker marker) { - WritableMap event = makeClickEventData(marker.getPosition()); - manager.pushEvent(this, "onMarkerDragStart", event); - - AirMapMarker markerView = markerMap.get(marker); - event = makeClickEventData(marker.getPosition()); - manager.pushEvent(markerView, "onDragStart", event); - } - - @Override - public void onMarkerDrag(Marker marker) { - WritableMap event = makeClickEventData(marker.getPosition()); - manager.pushEvent(this, "onMarkerDrag", event); - - AirMapMarker markerView = markerMap.get(marker); - event = makeClickEventData(marker.getPosition()); - manager.pushEvent(markerView, "onDrag", event); - } - - @Override - public void onMarkerDragEnd(Marker marker) { - WritableMap event = makeClickEventData(marker.getPosition()); - manager.pushEvent(this, "onMarkerDragEnd", event); - - AirMapMarker markerView = markerMap.get(marker); - event = makeClickEventData(marker.getPosition()); - manager.pushEvent(markerView, "onDragEnd", event); - } - - private ProgressBar getMapLoadingProgressBar() { - if (this.mapLoadingProgressBar == null) { - this.mapLoadingProgressBar = new ProgressBar(getContext()); - this.mapLoadingProgressBar.setIndeterminate(true); - } - if (this.loadingIndicatorColor != null) { - this.setLoadingIndicatorColor(this.loadingIndicatorColor); - } - return this.mapLoadingProgressBar; - } - - private RelativeLayout getMapLoadingLayoutView() { - if (this.mapLoadingLayout == null) { - this.mapLoadingLayout = new RelativeLayout(getContext()); - this.mapLoadingLayout.setBackgroundColor(Color.LTGRAY); - this.addView(this.mapLoadingLayout, - new ViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.FILL_PARENT)); - - RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT); - params.addRule(RelativeLayout.CENTER_IN_PARENT); - this.mapLoadingLayout.addView(this.getMapLoadingProgressBar(), params); - - this.mapLoadingLayout.setVisibility(View.INVISIBLE); - } - this.setLoadingBackgroundColor(this.loadingBackgroundColor); - return this.mapLoadingLayout; - } - - private ImageView getCacheImageView() { - if (this.cacheImageView == null) { - this.cacheImageView = new ImageView(getContext()); - this.addView(this.cacheImageView, - new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); - this.cacheImageView.setVisibility(View.INVISIBLE); - } - return this.cacheImageView; - } - - private void removeCacheImageView() { - if (this.cacheImageView != null) { - ((ViewGroup)this.cacheImageView.getParent()).removeView(this.cacheImageView); - this.cacheImageView = null; - } - } - - private void removeMapLoadingProgressBar() { - if (this.mapLoadingProgressBar != null) { - ((ViewGroup)this.mapLoadingProgressBar.getParent()).removeView(this.mapLoadingProgressBar); - this.mapLoadingProgressBar = null; - } - } - - private void removeMapLoadingLayoutView() { - this.removeMapLoadingProgressBar(); - if (this.mapLoadingLayout != null) { - ((ViewGroup)this.mapLoadingLayout.getParent()).removeView(this.mapLoadingLayout); - this.mapLoadingLayout = null; - } - } - - private void cacheView() { - if (this.cacheEnabled) { - final ImageView cacheImageView = this.getCacheImageView(); - final RelativeLayout mapLoadingLayout = this.getMapLoadingLayoutView(); - cacheImageView.setVisibility(View.INVISIBLE); - mapLoadingLayout.setVisibility(View.VISIBLE); - if (this.isMapLoaded) { - this.map.snapshot(new GoogleMap.SnapshotReadyCallback() { - @Override public void onSnapshotReady(Bitmap bitmap) { - cacheImageView.setImageBitmap(bitmap); - cacheImageView.setVisibility(View.VISIBLE); - mapLoadingLayout.setVisibility(View.INVISIBLE); - } - }); - } - } - else { - this.removeCacheImageView(); - if (this.isMapLoaded) { - this.removeMapLoadingLayoutView(); - } - } - } - - public void onPanDrag(MotionEvent ev) { - Point point = new Point((int) ev.getX(), (int) ev.getY()); - LatLng coords = this.map.getProjection().fromScreenLocation(point); - WritableMap event = makeClickEventData(coords); - manager.pushEvent(this, "onPanDrag", event); - } -} diff --git a/android/lib/src/main/java/com/airbnb/android/react/maps/LatLngBoundsUtils.java b/android/lib/src/main/java/com/airbnb/android/react/maps/LatLngBoundsUtils.java deleted file mode 100644 index ed1058c88..000000000 --- a/android/lib/src/main/java/com/airbnb/android/react/maps/LatLngBoundsUtils.java +++ /dev/null @@ -1,47 +0,0 @@ -package com.airbnb.android.react.maps; - -import com.google.android.gms.maps.model.LatLng; -import com.google.android.gms.maps.model.LatLngBounds; - -public class LatLngBoundsUtils { - public static boolean BoundsAreDifferent(LatLngBounds a, LatLngBounds b) { - LatLng centerA = a.getCenter(); - double latA = centerA.latitude; - double lngA = centerA.longitude; - double latDeltaA = a.northeast.latitude - a.southwest.latitude; - double lngDeltaA = a.northeast.longitude - a.southwest.longitude; - - LatLng centerB = b.getCenter(); - double latB = centerB.latitude; - double lngB = centerB.longitude; - double latDeltaB = b.northeast.latitude - b.southwest.latitude; - double lngDeltaB = b.northeast.longitude - b.southwest.longitude; - - double latEps = LatitudeEpsilon(a, b); - double lngEps = LongitudeEpsilon(a, b); - - return - different(latA, latB, latEps) || - different(lngA, lngB, lngEps) || - different(latDeltaA, latDeltaB, latEps) || - different(lngDeltaA, lngDeltaB, lngEps); - } - - private static boolean different(double a, double b, double epsilon) { - return Math.abs(a - b) > epsilon; - } - - private static double LatitudeEpsilon(LatLngBounds a, LatLngBounds b) { - double sizeA = a.northeast.latitude - a.southwest.latitude; // something mod 180? - double sizeB = b.northeast.latitude - b.southwest.latitude; // something mod 180? - double size = Math.min(Math.abs(sizeA), Math.abs(sizeB)); - return size / 2560; - } - - private static double LongitudeEpsilon(LatLngBounds a, LatLngBounds b) { - double sizeA = a.northeast.longitude - a.southwest.longitude; - double sizeB = b.northeast.longitude - b.southwest.longitude; - double size = Math.min(Math.abs(sizeA), Math.abs(sizeB)); - return size / 2560; - } -} diff --git a/android/lib/src/main/java/com/airbnb/android/react/maps/MapsPackage.java b/android/lib/src/main/java/com/airbnb/android/react/maps/MapsPackage.java deleted file mode 100644 index f352d924e..000000000 --- a/android/lib/src/main/java/com/airbnb/android/react/maps/MapsPackage.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.airbnb.android.react.maps; - -import android.app.Activity; - -import com.facebook.react.ReactPackage; -import com.facebook.react.bridge.JavaScriptModule; -import com.facebook.react.bridge.NativeModule; -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.uimanager.ViewManager; - -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -public class MapsPackage implements ReactPackage { - public MapsPackage(Activity activity) { } // backwards compatability - public MapsPackage() { } - - @Override - public List createNativeModules(ReactApplicationContext reactContext) { - return Collections.emptyList(); - } - - @Override - public List> createJSModules() { - return Collections.emptyList(); - } - - @Override - public List createViewManagers(ReactApplicationContext reactContext) { - AirMapCalloutManager calloutManager = new AirMapCalloutManager(); - AirMapMarkerManager annotationManager = new AirMapMarkerManager(); - AirMapPolylineManager polylineManager = new AirMapPolylineManager(reactContext); - AirMapPolygonManager polygonManager = new AirMapPolygonManager(reactContext); - AirMapCircleManager circleManager = new AirMapCircleManager(reactContext); - AirMapManager mapManager = new AirMapManager(reactContext.getBaseContext()); - - return Arrays.asList( - calloutManager, - annotationManager, - polylineManager, - polygonManager, - circleManager, - mapManager); - } -} diff --git a/android/lib/src/main/java/com/airbnb/android/react/maps/RegionChangeEvent.java b/android/lib/src/main/java/com/airbnb/android/react/maps/RegionChangeEvent.java deleted file mode 100644 index 28a3b322b..000000000 --- a/android/lib/src/main/java/com/airbnb/android/react/maps/RegionChangeEvent.java +++ /dev/null @@ -1,47 +0,0 @@ -package com.airbnb.android.react.maps; - -import com.facebook.react.bridge.WritableMap; -import com.facebook.react.bridge.WritableNativeMap; -import com.facebook.react.uimanager.events.Event; -import com.facebook.react.uimanager.events.RCTEventEmitter; -import com.google.android.gms.maps.model.LatLng; -import com.google.android.gms.maps.model.LatLngBounds; - -public class RegionChangeEvent extends Event { - private final LatLngBounds bounds; - private final LatLng center; - private final boolean continuous; - - public RegionChangeEvent(int id, LatLngBounds bounds, LatLng center, boolean continuous) { - super(id); - this.bounds = bounds; - this.center = center; - this.continuous = continuous; - } - - @Override - public String getEventName() { - return "topChange"; - } - - @Override - public boolean canCoalesce() { - return false; - } - - @Override - public void dispatch(RCTEventEmitter rctEventEmitter) { - - WritableMap event = new WritableNativeMap(); - event.putBoolean("continuous", continuous); - - WritableMap region = new WritableNativeMap(); - region.putDouble("latitude", center.latitude); - region.putDouble("longitude", center.longitude); - region.putDouble("latitudeDelta", bounds.northeast.latitude - bounds.southwest.latitude); - region.putDouble("longitudeDelta", bounds.northeast.longitude - bounds.southwest.longitude); - event.putMap("region", region); - - rctEventEmitter.receiveEvent(getViewTag(), getEventName(), event); - } -} diff --git a/android/lib/src/main/java/com/airbnb/android/react/maps/SizeReportingShadowNode.java b/android/lib/src/main/java/com/airbnb/android/react/maps/SizeReportingShadowNode.java deleted file mode 100644 index 40ace480f..000000000 --- a/android/lib/src/main/java/com/airbnb/android/react/maps/SizeReportingShadowNode.java +++ /dev/null @@ -1,31 +0,0 @@ -/** - * Copyright (c) 2015-present, Facebook, Inc. - * All rights reserved. - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -package com.airbnb.android.react.maps; - -import com.facebook.react.uimanager.LayoutShadowNode; -import com.facebook.react.uimanager.UIViewOperationQueue; - -import java.util.HashMap; -import java.util.Map; - -// Custom LayoutShadowNode implementation used in conjunction with the AirMapManager -// which sends the width/height of the view after layout occurs. -public class SizeReportingShadowNode extends LayoutShadowNode { - - @Override - public void onCollectExtraUpdates(UIViewOperationQueue uiViewOperationQueue) { - super.onCollectExtraUpdates(uiViewOperationQueue); - - Map data = new HashMap<>(); - data.put("width", getLayoutWidth()); - data.put("height", getLayoutHeight()); - - uiViewOperationQueue.enqueueUpdateExtraData(getReactTag(), data); - } -} From b33de8669fc7748efec0255a2ddef22a1d4dd070 Mon Sep 17 00:00:00 2001 From: Chris Knepper Date: Thu, 25 Aug 2016 21:55:54 -0400 Subject: [PATCH 0017/1148] -Update installation documentation --- docs/installation.md | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/docs/installation.md b/docs/installation.md index 47ddc8d2a..86e87e4ea 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -6,10 +6,10 @@ First, download the library from npm: npm install react-native-maps --save ``` -Then you must install the native dependencies. You can use [`rnpm`](https://github.com/rnpm/rnpm) to +Then you must install the native dependencies. You can use `rnpm` (now part of `react-native` core) to add native dependencies automatically: -`$ rnpm link` +`$ react-native link` Go to step 4 to configure Google Maps API KEY in Android. @@ -45,13 +45,20 @@ To install using Cocoapods, simply insert the following line into your `Podfile` ... dependencies { ... - compile 'com.airbnb.android:react-native-maps:0.7.1' + compile project(':react-native-maps') } ``` -For React Native v0.29.0 or above: +2. in your `android/settings.gradle` add: +```groovy +... +include ':react-native-maps' +project(':react-native-maps').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-maps/android') +``` + +3. in your application object, add: -2. in your application object, add: +For React Native v0.29.0 or above: ```java public class MyApplication extends Application implements ReactApplication { From 17d90593de0856c302d24405f28b8bbc0f566620 Mon Sep 17 00:00:00 2001 From: Chris Knepper Date: Fri, 26 Aug 2016 09:46:28 -0400 Subject: [PATCH 0018/1148] -Be unspecific about react-native dependency version in build.gradle (since react-native versions increment quickly) --- android/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android/build.gradle b/android/build.gradle index 3e22dc951..73aa31606 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -43,7 +43,7 @@ android { } dependencies { - compile 'com.facebook.react:react-native:0.32.0' + compile 'com.facebook.react:react-native:+' compile "com.google.android.gms:play-services-base:8.4.0" compile 'com.google.android.gms:play-services-maps:8.4.0' } From 3c9a6a7b60ebe81995a99910d0dd5561f2e0ecd6 Mon Sep 17 00:00:00 2001 From: Chris Knepper Date: Fri, 26 Aug 2016 22:22:00 -0400 Subject: [PATCH 0019/1148] -Remove obsolete gradle file --- android/settings.gradle | 1 - 1 file changed, 1 deletion(-) delete mode 100644 android/settings.gradle diff --git a/android/settings.gradle b/android/settings.gradle deleted file mode 100644 index 2b49d90f6..000000000 --- a/android/settings.gradle +++ /dev/null @@ -1 +0,0 @@ -include ':lib' \ No newline at end of file From f5a525f0467bcf22cec3804d1f11d6a06e1e72e7 Mon Sep 17 00:00:00 2001 From: Chris Knepper Date: Tue, 30 Aug 2016 00:21:22 -0400 Subject: [PATCH 0020/1148] -Testing changes requested by @felipecsl --- android/build.gradle | 6 +++--- example/android/settings.gradle | 4 ++-- example/package.json | 4 ++-- package.json | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/android/build.gradle b/android/build.gradle index 73aa31606..db482d7a0 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -8,7 +8,7 @@ buildscript { mavenLocal() jcenter() maven { - url "$projectDir/../../react-native/android" + url "$projectDir/../node_modules/react-native/android" } } dependencies { @@ -23,7 +23,7 @@ allprojects { maven { // Refer to the local install of react-native in the node_modules folder // react-native should be installed since it's a peer dependency - url "$projectDir/../../react-native/android" + url "$projectDir/../node_modules/react-native/android" } } } @@ -43,7 +43,7 @@ android { } dependencies { - compile 'com.facebook.react:react-native:+' + compile 'com.facebook.react:react-native:0.32.0' compile "com.google.android.gms:play-services-base:8.4.0" compile 'com.google.android.gms:play-services-maps:8.4.0' } diff --git a/example/android/settings.gradle b/example/android/settings.gradle index 3574854c2..f56b16c18 100644 --- a/example/android/settings.gradle +++ b/example/android/settings.gradle @@ -1,2 +1,2 @@ -include ':app', ':react-native-maps' -project(':react-native-maps').projectDir = new File(rootProject.projectDir, '../../android/lib') \ No newline at end of file +include ':react-native-maps' +project(':react-native-maps').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-maps/android') diff --git a/example/package.json b/example/package.json index 125b6e5a5..a379ea9a2 100644 --- a/example/package.json +++ b/example/package.json @@ -9,8 +9,8 @@ "dev": "concurrently 'npm run watch' 'npm run packager'" }, "dependencies": { - "react": "15.2.0", - "react-native": "^0.29.2", + "react": "15.3.0", + "react-native": "^0.32.0", "react-native-maps": "../" }, "devDependencies": { diff --git a/package.json b/package.json index 52359cafd..407134366 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,7 @@ "mapkit" ], "peerDependencies": { - "react": ">=15.2.0", + "react": ">=15.3.0", "react-native": ">=0.32.0" }, "devDependencies": { From 2fea4763da96512654397722ea36bd358d1bd192 Mon Sep 17 00:00:00 2001 From: Chris Knepper Date: Tue, 30 Aug 2016 00:53:00 -0400 Subject: [PATCH 0021/1148] -Revert build gradle node_modules change --- android/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/android/build.gradle b/android/build.gradle index db482d7a0..3e22dc951 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -8,7 +8,7 @@ buildscript { mavenLocal() jcenter() maven { - url "$projectDir/../node_modules/react-native/android" + url "$projectDir/../../react-native/android" } } dependencies { @@ -23,7 +23,7 @@ allprojects { maven { // Refer to the local install of react-native in the node_modules folder // react-native should be installed since it's a peer dependency - url "$projectDir/../node_modules/react-native/android" + url "$projectDir/../../react-native/android" } } } From b38d6afa78d2e0ce3ab3e7ba4a2ce5af0018aa8f Mon Sep 17 00:00:00 2001 From: Chris Knepper Date: Tue, 30 Aug 2016 16:34:00 -0400 Subject: [PATCH 0022/1148] -Fix missing include in android/settings.gradle --- example/android/settings.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/example/android/settings.gradle b/example/android/settings.gradle index f56b16c18..d9c3d2776 100644 --- a/example/android/settings.gradle +++ b/example/android/settings.gradle @@ -1,2 +1,2 @@ -include ':react-native-maps' +include ':app', ':react-native-maps' project(':react-native-maps').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-maps/android') From 6d30a5092bb756557482a317b9d90038cbb38cc2 Mon Sep 17 00:00:00 2001 From: Spike Brehm Date: Tue, 30 Aug 2016 14:31:35 -0700 Subject: [PATCH 0023/1148] Remove unused `NativeMethodsMixin` for compat with RN 0.32 Remove the unused `NativeMethodsMixin`, which is undefined in `react-native` 0.32.0, causing yellowbox warnings. --- components/MapCallout.js | 3 --- components/MapCircle.js | 3 --- components/MapMarker.js | 3 --- components/MapPolygon.js | 3 --- components/MapPolyline.js | 3 --- components/MapView.js | 3 --- 6 files changed, 18 deletions(-) diff --git a/components/MapCallout.js b/components/MapCallout.js index 205c2b8a6..a4124c356 100644 --- a/components/MapCallout.js +++ b/components/MapCallout.js @@ -1,15 +1,12 @@ import React, { PropTypes } from 'react'; import { View, - NativeMethodsMixin, requireNativeComponent, StyleSheet, } from 'react-native'; // eslint-disable-next-line react/prefer-es6-class const MapCallout = React.createClass({ - mixins: [NativeMethodsMixin], - propTypes: { ...View.propTypes, tooltip: PropTypes.bool, diff --git a/components/MapCircle.js b/components/MapCircle.js index 8f42463f9..2569fc3a4 100644 --- a/components/MapCircle.js +++ b/components/MapCircle.js @@ -1,14 +1,11 @@ import React, { PropTypes } from 'react'; import { View, - NativeMethodsMixin, requireNativeComponent, } from 'react-native'; // eslint-disable-next-line react/prefer-es6-class const MapCircle = React.createClass({ - mixins: [NativeMethodsMixin], - propTypes: { ...View.propTypes, diff --git a/components/MapMarker.js b/components/MapMarker.js index c1ab7bb36..5ee0e8ae0 100644 --- a/components/MapMarker.js +++ b/components/MapMarker.js @@ -1,7 +1,6 @@ import React, { PropTypes } from 'react'; import { View, - NativeMethodsMixin, requireNativeComponent, StyleSheet, Platform, @@ -14,8 +13,6 @@ const resolveAssetSource = require('react-native/Libraries/Image/resolveAssetSou // eslint-disable-next-line react/prefer-es6-class const MapMarker = React.createClass({ - mixins: [NativeMethodsMixin], - viewConfig: { uiViewClassName: 'AIRMapMarker', validAttributes: { diff --git a/components/MapPolygon.js b/components/MapPolygon.js index 9d8af164c..42c22e354 100644 --- a/components/MapPolygon.js +++ b/components/MapPolygon.js @@ -1,14 +1,11 @@ import React, { PropTypes } from 'react'; import { View, - NativeMethodsMixin, requireNativeComponent, } from 'react-native'; // eslint-disable-next-line react/prefer-es6-class const MapPolygon = React.createClass({ - mixins: [NativeMethodsMixin], - propTypes: { ...View.propTypes, diff --git a/components/MapPolyline.js b/components/MapPolyline.js index 905d51b4a..397b4ca0b 100644 --- a/components/MapPolyline.js +++ b/components/MapPolyline.js @@ -1,14 +1,11 @@ import React, { PropTypes } from 'react'; import { View, - NativeMethodsMixin, requireNativeComponent, } from 'react-native'; // eslint-disable-next-line react/prefer-es6-class const MapPolyline = React.createClass({ - mixins: [NativeMethodsMixin], - propTypes: { ...View.propTypes, diff --git a/components/MapView.js b/components/MapView.js index 7540ef50e..c7e881b93 100644 --- a/components/MapView.js +++ b/components/MapView.js @@ -1,7 +1,6 @@ import React, { PropTypes } from 'react'; import { EdgeInsetsPropType, - NativeMethodsMixin, Platform, View, Animated, @@ -18,8 +17,6 @@ import MapCallout from './MapCallout'; // eslint-disable-next-line react/prefer-es6-class const MapView = React.createClass({ - mixins: [NativeMethodsMixin], - viewConfig: { uiViewClassName: 'AIRMap', validAttributes: { From b0fb9709e2858c4c9c8563cdd4c2074d984f9a9d Mon Sep 17 00:00:00 2001 From: Spike Brehm Date: Tue, 30 Aug 2016 19:50:29 -0700 Subject: [PATCH 0024/1148] Update CHANGELOG for 0.8.0 --- CHANGELOG.md | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 93d415781..920dd8683 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,30 @@ # Change Log +## 0.8.0 (August 30, 2016) + +### Breaking Changes + +- Upgrade to `react-native@0.32.0`, and update Android code to match ([#502](https://github.com/lelandrichardson/react-native-maps/pull/502)) + +### Patches + +- [android] Add `showsMyLocationButton` prop ([#382](https://github.com/lelandrichardson/react-native-maps/pull/382)) + +- Add `fitToSuppliedMarkers()` method ([#386](https://github.com/lelandrichardson/react-native-maps/pull/386)) + +- [ios] Update AirMapMarker to use loadImageWithURLRequest ([#389](https://github.com/lelandrichardson/react-native-maps/pull/389)) + +- Improvements to watch and copy script ([#445](https://github.com/lelandrichardson/react-native-maps/pull/445)) + +- [ios] Added check on marker class in predicate ([#485](https://github.com/lelandrichardson/react-native-maps/pull/485)) + +- Use `StyleSheet.absoluteFillObject` where appropriate ([#500](https://github.com/lelandrichardson/react-native-maps/pull/500)) and ([#493](https://github.com/lelandrichardson/react-native-maps/pull/493)) + +- Add ESLint and fix a number of linting violations ([#501](https://github.com/lelandrichardson/react-native-maps/pull/501)) + +- Remove unused `NativeMethodsMixin` for compat with RN 0.32 ([#511](https://github.com/lelandrichardson/react-native-maps/pull/511)) + + ## 0.7.1 (July 9, 2016) ### Patches From 0472bd232ad6fd67b4e5dc8ec80cf02efc486fee Mon Sep 17 00:00:00 2001 From: Spike Brehm Date: Tue, 30 Aug 2016 19:54:58 -0700 Subject: [PATCH 0025/1148] Undo premature bump of version from 0.7.1 to 0.8.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 407134366..a68830235 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "description": "React Native Mapview component for iOS + Android", "main": "index.js", "author": "Leland Richardson ", - "version": "0.8.0", + "version": "0.7.1", "scripts": { "start": "react-native start", "lint": "eslint ." From 31cfa0e7d4f54f6ed44c171139dbfd6cb983983c Mon Sep 17 00:00:00 2001 From: Spike Brehm Date: Tue, 30 Aug 2016 19:55:13 -0700 Subject: [PATCH 0026/1148] 0.8.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a68830235..407134366 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "description": "React Native Mapview component for iOS + Android", "main": "index.js", "author": "Leland Richardson ", - "version": "0.7.1", + "version": "0.8.0", "scripts": { "start": "react-native start", "lint": "eslint ." From 71de3da73c2105678674ac12f255c806e47d9b2f Mon Sep 17 00:00:00 2001 From: Spike Brehm Date: Tue, 30 Aug 2016 14:37:33 -0700 Subject: [PATCH 0027/1148] [ESLint] Add .eslintrc to ./example/scripts/ To disable certain rules. --- example/scripts/.eslintrc | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 example/scripts/.eslintrc diff --git a/example/scripts/.eslintrc b/example/scripts/.eslintrc new file mode 100644 index 000000000..3c1eaf35a --- /dev/null +++ b/example/scripts/.eslintrc @@ -0,0 +1,6 @@ +{ + "rules": { + // Scripts can import things in devDependencies + "import/no-extraneous-dependencies": [2, {"devDependencies": true}] + } +} From fef1a637b655142e8139b1ac549901095fef0a00 Mon Sep 17 00:00:00 2001 From: Spike Brehm Date: Tue, 30 Aug 2016 14:39:29 -0700 Subject: [PATCH 0028/1148] [ESLint] Apply `eslint --fix` --- components/MapView.js | 2 +- example/App.js | 4 ++-- example/examples/AnimatedMarkers.js | 4 ++-- example/examples/AnimatedPriceMarker.js | 2 +- example/examples/AnimatedViews.js | 13 ++++++------- example/examples/CachedMap.js | 4 ++-- example/examples/Callouts.js | 6 +++--- example/examples/CustomCallout.js | 2 +- example/examples/DefaultMarkers.js | 4 ++-- example/examples/DisplayLatLng.js | 7 +++---- example/examples/DraggableMarkers.js | 6 +++--- example/examples/EventListener.js | 8 ++++---- example/examples/FitToSuppliedMarkers.js | 4 ++-- example/examples/LoadingMap.js | 4 ++-- example/examples/MarkerTypes.js | 4 ++-- example/examples/Overlays.js | 4 ++-- example/examples/PanController.js | 2 +- example/examples/PolygonCreator.js | 4 ++-- example/examples/PolylineCreator.js | 4 ++-- example/examples/PriceMarker.js | 2 +- example/examples/TakeSnapshot.js | 4 ++-- example/examples/ViewsAsMarkers.js | 6 +++--- example/examples/finalindexfile.js | 6 +++--- example/index.android.js | 4 ++-- example/index.ios.js | 4 ++-- 25 files changed, 56 insertions(+), 58 deletions(-) diff --git a/components/MapView.js b/components/MapView.js index c7e881b93..cf5ae344d 100644 --- a/components/MapView.js +++ b/components/MapView.js @@ -455,7 +455,7 @@ const MapView = React.createClass({ }, }); -let AIRMap = requireNativeComponent('AIRMap', MapView, { +const AIRMap = requireNativeComponent('AIRMap', MapView, { nativeOnly: { onChange: true, onMapReady: true, diff --git a/example/App.js b/example/App.js index 7e78aea94..2e8c55495 100644 --- a/example/App.js +++ b/example/App.js @@ -1,4 +1,4 @@ -let React = require('react'); +const React = require('react'); const ReactNative = require('react-native'); let { View, @@ -54,7 +54,7 @@ const App = React.createClass({ }, renderExamples(examples) { - let { Component } = this.state; + const { Component } = this.state; return ( {Component && } diff --git a/example/examples/AnimatedMarkers.js b/example/examples/AnimatedMarkers.js index ae7364822..3379a5c17 100644 --- a/example/examples/AnimatedMarkers.js +++ b/example/examples/AnimatedMarkers.js @@ -1,4 +1,4 @@ -let React = require('react'); +const React = require('react'); const ReactNative = require('react-native'); let { StyleSheet, @@ -11,7 +11,7 @@ let { Platform, } = ReactNative; -let MapView = require('react-native-maps'); +const MapView = require('react-native-maps'); const screen = Dimensions.get('window'); diff --git a/example/examples/AnimatedPriceMarker.js b/example/examples/AnimatedPriceMarker.js index 7de89fd02..49c9d718f 100644 --- a/example/examples/AnimatedPriceMarker.js +++ b/example/examples/AnimatedPriceMarker.js @@ -1,4 +1,4 @@ -let React = require('react'); +const React = require('react'); const ReactNative = require('react-native'); const { PropTypes, diff --git a/example/examples/AnimatedViews.js b/example/examples/AnimatedViews.js index 4895e4230..246287fc1 100644 --- a/example/examples/AnimatedViews.js +++ b/example/examples/AnimatedViews.js @@ -1,4 +1,4 @@ -let React = require('react'); +const React = require('react'); const ReactNative = require('react-native'); let { StyleSheet, @@ -11,9 +11,9 @@ let { Platform, } = ReactNative; -let MapView = require('react-native-maps'); -let PanController = require('./PanController'); -let PriceMarker = require('./AnimatedPriceMarker'); +const MapView = require('react-native-maps'); +const PanController = require('./PanController'); +const PriceMarker = require('./AnimatedPriceMarker'); const screen = Dimensions.get('window'); @@ -26,7 +26,7 @@ const LONGITUDE_DELTA = LATITUDE_DELTA * ASPECT_RATIO; const ITEM_SPACING = 10; const ITEM_PREVIEW = 10; const ITEM_WIDTH = screen.width - 2 * ITEM_SPACING - 2 * ITEM_PREVIEW; -let SNAP_WIDTH = ITEM_WIDTH + ITEM_SPACING; +const SNAP_WIDTH = ITEM_WIDTH + ITEM_SPACING; const ITEM_PREVIEW_HEIGHT = 150; const SCALE_END = screen.width / ITEM_WIDTH; const BREAKPOINT1 = 246; @@ -375,8 +375,7 @@ const AnimatedViews = React.createClass({ { scale }, ], }]} - > - + /> ); })} diff --git a/example/examples/CachedMap.js b/example/examples/CachedMap.js index 227b2379d..d022ce67a 100644 --- a/example/examples/CachedMap.js +++ b/example/examples/CachedMap.js @@ -1,4 +1,4 @@ -let React = require('react'); +const React = require('react'); const ReactNative = require('react-native'); let { Text, @@ -9,7 +9,7 @@ let { TouchableOpacity, } = ReactNative; -let MapView = require('react-native-maps'); +const MapView = require('react-native-maps'); const HORIZONTAL_PADDING = 12; const VERTICAL_PADDING = 6; diff --git a/example/examples/Callouts.js b/example/examples/Callouts.js index e519bc8f3..1ee756159 100644 --- a/example/examples/Callouts.js +++ b/example/examples/Callouts.js @@ -1,4 +1,4 @@ -let React = require('react'); +const React = require('react'); const ReactNative = require('react-native'); let { StyleSheet, @@ -10,9 +10,9 @@ let { Image, } = ReactNative; -let MapView = require('react-native-maps'); +const MapView = require('react-native-maps'); const PriceMarker = require('./PriceMarker'); -let CustomCallout = require('./CustomCallout'); +const CustomCallout = require('./CustomCallout'); let { width, height } = Dimensions.get('window'); diff --git a/example/examples/CustomCallout.js b/example/examples/CustomCallout.js index 05edd66b1..0501cb253 100644 --- a/example/examples/CustomCallout.js +++ b/example/examples/CustomCallout.js @@ -1,4 +1,4 @@ -let React = require('react'); +const React = require('react'); const ReactNative = require('react-native'); let { StyleSheet, diff --git a/example/examples/DefaultMarkers.js b/example/examples/DefaultMarkers.js index 9aa7d3e15..48eb1c05d 100644 --- a/example/examples/DefaultMarkers.js +++ b/example/examples/DefaultMarkers.js @@ -1,4 +1,4 @@ -let React = require('react'); +const React = require('react'); const ReactNative = require('react-native'); let { StyleSheet, @@ -9,7 +9,7 @@ let { TouchableOpacity, } = ReactNative; -let MapView = require('react-native-maps'); +const MapView = require('react-native-maps'); let { width, height } = Dimensions.get('window'); diff --git a/example/examples/DisplayLatLng.js b/example/examples/DisplayLatLng.js index 1b8d5c72a..abaebb797 100644 --- a/example/examples/DisplayLatLng.js +++ b/example/examples/DisplayLatLng.js @@ -1,4 +1,4 @@ -let React = require('react'); +const React = require('react'); const ReactNative = require('react-native'); let { StyleSheet, @@ -9,7 +9,7 @@ let { TouchableOpacity, } = ReactNative; -let MapView = require('react-native-maps'); +const MapView = require('react-native-maps'); let { width, height } = Dimensions.get('window'); @@ -61,8 +61,7 @@ const DisplayLatLng = React.createClass({ style={styles.map} region={this.state.region} onRegionChange={this.onRegionChange} - > - + /> {`${this.state.region.latitude.toPrecision(7)}, ${this.state.region.longitude.toPrecision(7)}`} diff --git a/example/examples/DraggableMarkers.js b/example/examples/DraggableMarkers.js index 7ae784c24..612e0fe0b 100644 --- a/example/examples/DraggableMarkers.js +++ b/example/examples/DraggableMarkers.js @@ -1,4 +1,4 @@ -let React = require('react'); +const React = require('react'); const ReactNative = require('react-native'); let { StyleSheet, @@ -10,8 +10,8 @@ let { Image, } = ReactNative; -let MapView = require('react-native-maps'); -let PriceMarker = require('./PriceMarker'); +const MapView = require('react-native-maps'); +const PriceMarker = require('./PriceMarker'); let { width, height } = Dimensions.get('window'); diff --git a/example/examples/EventListener.js b/example/examples/EventListener.js index 7add38786..5b834aaf2 100644 --- a/example/examples/EventListener.js +++ b/example/examples/EventListener.js @@ -1,4 +1,4 @@ -let React = require('react'); +const React = require('react'); const ReactNative = require('react-native'); let { StyleSheet, @@ -10,8 +10,8 @@ let { ScrollView, } = ReactNative; -let MapView = require('react-native-maps'); -let PriceMarker = require('./PriceMarker'); +const MapView = require('react-native-maps'); +const PriceMarker = require('./PriceMarker'); let { width, height } = Dimensions.get('window'); @@ -22,7 +22,7 @@ const LATITUDE_DELTA = 0.0922; const LONGITUDE_DELTA = LATITUDE_DELTA * ASPECT_RATIO; let id = 0; -let Event = React.createClass({ +const Event = React.createClass({ shouldComponentUpdate(nextProps) { return this.props.event.id !== nextProps.event.id; }, diff --git a/example/examples/FitToSuppliedMarkers.js b/example/examples/FitToSuppliedMarkers.js index 40117db6d..1e02b1d61 100644 --- a/example/examples/FitToSuppliedMarkers.js +++ b/example/examples/FitToSuppliedMarkers.js @@ -1,4 +1,4 @@ -let React = require('react'); +const React = require('react'); const ReactNative = require('react-native'); let { StyleSheet, @@ -10,7 +10,7 @@ let { Image, } = ReactNative; -let MapView = require('react-native-maps'); +const MapView = require('react-native-maps'); const PriceMarker = require('./PriceMarker'); let { width, height } = Dimensions.get('window'); diff --git a/example/examples/LoadingMap.js b/example/examples/LoadingMap.js index 50257ec08..b48ea462a 100644 --- a/example/examples/LoadingMap.js +++ b/example/examples/LoadingMap.js @@ -1,4 +1,4 @@ -let React = require('react'); +const React = require('react'); const ReactNative = require('react-native'); let { Text, @@ -7,7 +7,7 @@ let { StyleSheet, } = ReactNative; -let MapView = require('react-native-maps'); +const MapView = require('react-native-maps'); let { width, height } = Dimensions.get('window'); diff --git a/example/examples/MarkerTypes.js b/example/examples/MarkerTypes.js index b2bab5250..876476fe8 100644 --- a/example/examples/MarkerTypes.js +++ b/example/examples/MarkerTypes.js @@ -1,4 +1,4 @@ -let React = require('react'); +const React = require('react'); const ReactNative = require('react-native'); let { StyleSheet, @@ -10,7 +10,7 @@ let { Image, } = ReactNative; -let MapView = require('react-native-maps'); +const MapView = require('react-native-maps'); const PriceMarker = require('./PriceMarker'); let { width, height } = Dimensions.get('window'); diff --git a/example/examples/Overlays.js b/example/examples/Overlays.js index 3804996a2..7f54932da 100644 --- a/example/examples/Overlays.js +++ b/example/examples/Overlays.js @@ -1,4 +1,4 @@ -let React = require('react'); +const React = require('react'); const ReactNative = require('react-native'); let { StyleSheet, @@ -10,7 +10,7 @@ let { Image, } = ReactNative; -let MapView = require('react-native-maps'); +const MapView = require('react-native-maps'); let { width, height } = Dimensions.get('window'); diff --git a/example/examples/PanController.js b/example/examples/PanController.js index a490110c8..7541dcac6 100644 --- a/example/examples/PanController.js +++ b/example/examples/PanController.js @@ -1,4 +1,4 @@ -let React = require('react'); +const React = require('react'); const ReactNative = require('react-native'); const { PropTypes, diff --git a/example/examples/PolygonCreator.js b/example/examples/PolygonCreator.js index 2ab1e1a9b..7df2559e6 100644 --- a/example/examples/PolygonCreator.js +++ b/example/examples/PolygonCreator.js @@ -1,4 +1,4 @@ -let React = require('react'); +const React = require('react'); const ReactNative = require('react-native'); let { StyleSheet, @@ -9,7 +9,7 @@ let { TouchableOpacity, } = ReactNative; -let MapView = require('react-native-maps'); +const MapView = require('react-native-maps'); const PriceMarker = require('./PriceMarker'); let { width, height } = Dimensions.get('window'); diff --git a/example/examples/PolylineCreator.js b/example/examples/PolylineCreator.js index 768be65c1..e6c301522 100644 --- a/example/examples/PolylineCreator.js +++ b/example/examples/PolylineCreator.js @@ -1,4 +1,4 @@ -let React = require('react'); +const React = require('react'); const ReactNative = require('react-native'); let { StyleSheet, @@ -9,7 +9,7 @@ let { TouchableOpacity, } = ReactNative; -let MapView = require('react-native-maps'); +const MapView = require('react-native-maps'); const PriceMarker = require('./PriceMarker'); let { width, height } = Dimensions.get('window'); diff --git a/example/examples/PriceMarker.js b/example/examples/PriceMarker.js index 55c0f3ffc..8dd70b90b 100644 --- a/example/examples/PriceMarker.js +++ b/example/examples/PriceMarker.js @@ -1,4 +1,4 @@ -let React = require('react'); +const React = require('react'); const ReactNative = require('react-native'); let { StyleSheet, diff --git a/example/examples/TakeSnapshot.js b/example/examples/TakeSnapshot.js index 59e924992..28974f3e4 100644 --- a/example/examples/TakeSnapshot.js +++ b/example/examples/TakeSnapshot.js @@ -1,4 +1,4 @@ -let React = require('react'); +const React = require('react'); const ReactNative = require('react-native'); let { StyleSheet, @@ -10,7 +10,7 @@ let { Image, } = ReactNative; -let MapView = require('react-native-maps'); +const MapView = require('react-native-maps'); const PriceMarker = require('./PriceMarker'); let { width, height } = Dimensions.get('window'); diff --git a/example/examples/ViewsAsMarkers.js b/example/examples/ViewsAsMarkers.js index d0e8a0561..16e24fea5 100644 --- a/example/examples/ViewsAsMarkers.js +++ b/example/examples/ViewsAsMarkers.js @@ -1,4 +1,4 @@ -let React = require('react'); +const React = require('react'); const ReactNative = require('react-native'); let { StyleSheet, @@ -9,8 +9,8 @@ let { TouchableOpacity, } = ReactNative; -let MapView = require('react-native-maps'); -let PriceMarker = require('./PriceMarker'); +const MapView = require('react-native-maps'); +const PriceMarker = require('./PriceMarker'); let { width, height } = Dimensions.get('window'); diff --git a/example/examples/finalindexfile.js b/example/examples/finalindexfile.js index 05f9c9010..cb880482c 100644 --- a/example/examples/finalindexfile.js +++ b/example/examples/finalindexfile.js @@ -4,7 +4,7 @@ */ 'use strict'; -let React = require('react'); +const React = require('react'); const ReactNative = require('react-native'); let { AppRegistry, @@ -15,8 +15,8 @@ let { Animated, TouchableOpacity, } = ReactNative; -let MapView = require('react-native-maps'); -let PriceMarker = require('./components/PriceMarker'); +const MapView = require('react-native-maps'); +const PriceMarker = require('./components/PriceMarker'); let { width, height } = Dimensions.get('window'); diff --git a/example/index.android.js b/example/index.android.js index d3cb8508d..d35513e3f 100644 --- a/example/index.android.js +++ b/example/index.android.js @@ -1,10 +1,10 @@ -let React = require('react'); +const React = require('react'); const ReactNative = require('react-native'); const { AppRegistry, } = ReactNative; -let App = require('./App'); +const App = require('./App'); const AirMapsExplorer = React.createClass({ render() { diff --git a/example/index.ios.js b/example/index.ios.js index d3cb8508d..d35513e3f 100644 --- a/example/index.ios.js +++ b/example/index.ios.js @@ -1,10 +1,10 @@ -let React = require('react'); +const React = require('react'); const ReactNative = require('react-native'); const { AppRegistry, } = ReactNative; -let App = require('./App'); +const App = require('./App'); const AirMapsExplorer = React.createClass({ render() { From bf6260e0c65b23e0cc051636299198c7900bba17 Mon Sep 17 00:00:00 2001 From: Yao Bin Then Date: Mon, 8 Aug 2016 22:50:18 +0800 Subject: [PATCH 0029/1148] Use Activity to initialize Google Map --- .../android/react/maps/AirMapModule.java | 22 +++++++++++++++++++ .../android/react/maps/AirMapManager.java | 7 +++--- .../android/react/maps/MapsPackage.java | 2 +- 3 files changed, 27 insertions(+), 4 deletions(-) create mode 100644 android/lib/src/main/java/com/airbnb/android/react/maps/AirMapModule.java diff --git a/android/lib/src/main/java/com/airbnb/android/react/maps/AirMapModule.java b/android/lib/src/main/java/com/airbnb/android/react/maps/AirMapModule.java new file mode 100644 index 000000000..e7e666b70 --- /dev/null +++ b/android/lib/src/main/java/com/airbnb/android/react/maps/AirMapModule.java @@ -0,0 +1,22 @@ +package com.airbnb.android.react.maps; + +import android.app.Activity; + +import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.bridge.ReactContextBaseJavaModule; + +public class AirMapModule extends ReactContextBaseJavaModule { + + public AirMapModule(ReactApplicationContext reactContext) { + super(reactContext); + } + + @Override + public String getName() { + return "AirMapModule"; + } + + public Activity getActivity() { + return getCurrentActivity(); + } +} diff --git a/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java b/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java index 5ca02097b..3dda607e2 100644 --- a/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java +++ b/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java @@ -4,6 +4,7 @@ import android.content.Context; import com.facebook.react.bridge.Arguments; +import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactContext; import com.facebook.react.bridge.ReadableArray; import com.facebook.react.bridge.ReadableMap; @@ -41,9 +42,9 @@ public class AirMapManager extends ViewGroupManager { private ReactContext reactContext; - private final Context appContext; + private final ReactApplicationContext appContext; - public AirMapManager(Context context) { + public AirMapManager(ReactApplicationContext context) { this.appContext = context; } @@ -57,7 +58,7 @@ protected AirMapView createViewInstance(ThemedReactContext context) { reactContext = context; try { - MapsInitializer.initialize(this.appContext); + MapsInitializer.initialize(new AirMapModule(this.appContext).getActivity()); } catch (RuntimeException e) { e.printStackTrace(); emitMapError("Map initialize error", "map_init_error"); diff --git a/android/src/main/java/com/airbnb/android/react/maps/MapsPackage.java b/android/src/main/java/com/airbnb/android/react/maps/MapsPackage.java index f352d924e..33c523800 100644 --- a/android/src/main/java/com/airbnb/android/react/maps/MapsPackage.java +++ b/android/src/main/java/com/airbnb/android/react/maps/MapsPackage.java @@ -33,7 +33,7 @@ public List createViewManagers(ReactApplicationContext reactContext AirMapPolylineManager polylineManager = new AirMapPolylineManager(reactContext); AirMapPolygonManager polygonManager = new AirMapPolygonManager(reactContext); AirMapCircleManager circleManager = new AirMapCircleManager(reactContext); - AirMapManager mapManager = new AirMapManager(reactContext.getBaseContext()); + AirMapManager mapManager = new AirMapManager(reactContext); return Arrays.asList( calloutManager, From dcde97d5e9300fd405533226cc23cbdf60dce5e5 Mon Sep 17 00:00:00 2001 From: Spike Brehm Date: Tue, 30 Aug 2016 15:03:39 -0700 Subject: [PATCH 0030/1148] [ESLint] Refactor React.createClass() to use ES6 classes --- .eslintrc | 1 + components/MapCallout.js | 28 +- components/MapCircle.js | 251 +++++---- components/MapMarker.js | 386 +++++++------- components/MapPolygon.js | 261 +++++----- components/MapPolyline.js | 240 ++++----- components/MapView.js | 638 ++++++++++++----------- docs/installation.md | 43 +- example/App.js | 33 +- example/examples/AnimatedMarkers.js | 32 +- example/examples/AnimatedViews.js | 37 +- example/examples/CachedMap.js | 81 +-- example/examples/Callouts.js | 32 +- example/examples/CustomCallout.js | 22 +- example/examples/DefaultMarkers.js | 24 +- example/examples/DisplayLatLng.js | 45 +- example/examples/DraggableMarkers.js | 19 +- example/examples/EventListener.js | 40 +- example/examples/FitToSuppliedMarkers.js | 69 +-- example/examples/LoadingMap.js | 18 +- example/examples/MarkerTypes.js | 11 +- example/examples/Overlays.js | 24 +- example/examples/PanController.js | 1 + example/examples/PolygonCreator.js | 32 +- example/examples/PolylineCreator.js | 50 +- example/examples/PriceMarker.js | 30 +- example/examples/TakeSnapshot.js | 43 +- example/examples/ViewsAsMarkers.js | 32 +- example/examples/finalindexfile.js | 292 ----------- example/index.android.js | 6 +- example/index.ios.js | 6 +- 31 files changed, 1305 insertions(+), 1522 deletions(-) delete mode 100644 example/examples/finalindexfile.js diff --git a/.eslintrc b/.eslintrc index 2ab7f953b..70d91588b 100644 --- a/.eslintrc +++ b/.eslintrc @@ -7,6 +7,7 @@ "rules": { "prefer-object-spread/prefer-object-spread": 2, "react/jsx-filename-extension": 0, + "react/prefer-stateless-function": 0, "no-use-before-define": 0, "no-underscore-dangle": 0 } diff --git a/components/MapCallout.js b/components/MapCallout.js index a4124c356..3c15945a3 100644 --- a/components/MapCallout.js +++ b/components/MapCallout.js @@ -5,24 +5,24 @@ import { StyleSheet, } from 'react-native'; -// eslint-disable-next-line react/prefer-es6-class -const MapCallout = React.createClass({ - propTypes: { - ...View.propTypes, - tooltip: PropTypes.bool, - onPress: PropTypes.func, - }, +const propTypes = { + ...View.propTypes, + tooltip: PropTypes.bool, + onPress: PropTypes.func, +}; - getDefaultProps() { - return { - tooltip: false, - }; - }, +const defaultProps = { + tooltip: false, +}; +class MapCallout extends React.Component { render() { return ; - }, -}); + } +} + +MapCallout.propTypes = propTypes; +MapCallout.defaultProps = defaultProps; const styles = StyleSheet.create({ callout: { diff --git a/components/MapCircle.js b/components/MapCircle.js index 2569fc3a4..42e87a0ae 100644 --- a/components/MapCircle.js +++ b/components/MapCircle.js @@ -4,142 +4,133 @@ import { requireNativeComponent, } from 'react-native'; -// eslint-disable-next-line react/prefer-es6-class -const MapCircle = React.createClass({ - propTypes: { - ...View.propTypes, +const propTypes = { + ...View.propTypes, + /** + * The coordinate of the center of the circle + */ + center: PropTypes.shape({ /** - * The coordinate of the center of the circle + * Coordinates for the center of the circle. */ - center: PropTypes.shape({ - /** - * Coordinates for the center of the circle. - */ - latitude: PropTypes.number.isRequired, - longitude: PropTypes.number.isRequired, - }).isRequired, - - /** - * The radius of the circle to be drawn (in meters) - */ - radius: PropTypes.number.isRequired, - - /** - * Callback that is called when the user presses on the circle - */ - onPress: PropTypes.func, - - /** - * The stroke width to use for the path. - */ - strokeWidth: PropTypes.number, - - /** - * The stroke color to use for the path. - */ - strokeColor: PropTypes.string, - - /** - * The fill color to use for the path. - */ - fillColor: PropTypes.string, - - /** - * The order in which this tile overlay is drawn with respect to other overlays. An overlay - * with a larger z-index is drawn over overlays with smaller z-indices. The order of overlays - * with the same z-index is arbitrary. The default zIndex is 0. - * - * @platform android - */ - zIndex: PropTypes.number, - - /** - * The line cap style to apply to the open ends of the path. - * The default style is `round`. - * - * @platform ios - */ - lineCap: PropTypes.oneOf([ - 'butt', - 'round', - 'square', - ]), - - /** - * The line join style to apply to corners of the path. - * The default style is `round`. - * - * @platform ios - */ - lineJoin: PropTypes.oneOf([ - 'miter', - 'round', - 'bevel', - ]), - - /** - * The limiting value that helps avoid spikes at junctions between connected line segments. - * The miter limit helps you avoid spikes in paths that use the `miter` `lineJoin` style. If - * the ratio of the miter length—that is, the diagonal length of the miter join—to the line - * thickness exceeds the miter limit, the joint is converted to a bevel join. The default - * miter limit is 10, which results in the conversion of miters whose angle at the joint - * is less than 11 degrees. - * - * @platform ios - */ - miterLimit: PropTypes.number, - - /** - * The offset (in points) at which to start drawing the dash pattern. - * - * Use this property to start drawing a dashed line partway through a segment or gap. For - * example, a phase value of 6 for the patter 5-2-3-2 would cause drawing to begin in the - * middle of the first gap. - * - * The default value of this property is 0. - * - * @platform ios - */ - lineDashPhase: PropTypes.number, - - /** - * An array of numbers specifying the dash pattern to use for the path. - * - * The array contains one or more numbers that indicate the lengths (measured in points) of the - * line segments and gaps in the pattern. The values in the array alternate, starting with the - * first line segment length, followed by the first gap length, followed by the second line - * segment length, and so on. - * - * This property is set to `null` by default, which indicates no line dash pattern. - * - * @platform ios - */ - lineDashPattern: PropTypes.arrayOf(PropTypes.number), - }, - - getDefaultProps() { - return { - strokeColor: '#000', - strokeWidth: 1, - }; - }, - - _onPress(e) { - if (this.props.onPress) { - this.props.onPress(e); - } - }, - + latitude: PropTypes.number.isRequired, + longitude: PropTypes.number.isRequired, + }).isRequired, + + /** + * The radius of the circle to be drawn (in meters) + */ + radius: PropTypes.number.isRequired, + + /** + * Callback that is called when the user presses on the circle + */ + onPress: PropTypes.func, + + /** + * The stroke width to use for the path. + */ + strokeWidth: PropTypes.number, + + /** + * The stroke color to use for the path. + */ + strokeColor: PropTypes.string, + + /** + * The fill color to use for the path. + */ + fillColor: PropTypes.string, + + /** + * The order in which this tile overlay is drawn with respect to other overlays. An overlay + * with a larger z-index is drawn over overlays with smaller z-indices. The order of overlays + * with the same z-index is arbitrary. The default zIndex is 0. + * + * @platform android + */ + zIndex: PropTypes.number, + + /** + * The line cap style to apply to the open ends of the path. + * The default style is `round`. + * + * @platform ios + */ + lineCap: PropTypes.oneOf([ + 'butt', + 'round', + 'square', + ]), + + /** + * The line join style to apply to corners of the path. + * The default style is `round`. + * + * @platform ios + */ + lineJoin: PropTypes.oneOf([ + 'miter', + 'round', + 'bevel', + ]), + + /** + * The limiting value that helps avoid spikes at junctions between connected line segments. + * The miter limit helps you avoid spikes in paths that use the `miter` `lineJoin` style. If + * the ratio of the miter length—that is, the diagonal length of the miter join—to the line + * thickness exceeds the miter limit, the joint is converted to a bevel join. The default + * miter limit is 10, which results in the conversion of miters whose angle at the joint + * is less than 11 degrees. + * + * @platform ios + */ + miterLimit: PropTypes.number, + + /** + * The offset (in points) at which to start drawing the dash pattern. + * + * Use this property to start drawing a dashed line partway through a segment or gap. For + * example, a phase value of 6 for the patter 5-2-3-2 would cause drawing to begin in the + * middle of the first gap. + * + * The default value of this property is 0. + * + * @platform ios + */ + lineDashPhase: PropTypes.number, + + /** + * An array of numbers specifying the dash pattern to use for the path. + * + * The array contains one or more numbers that indicate the lengths (measured in points) of the + * line segments and gaps in the pattern. The values in the array alternate, starting with the + * first line segment length, followed by the first gap length, followed by the second line + * segment length, and so on. + * + * This property is set to `null` by default, which indicates no line dash pattern. + * + * @platform ios + */ + lineDashPattern: PropTypes.arrayOf(PropTypes.number), +}; + +const defaultProps = { + strokeColor: '#000', + strokeWidth: 1, +}; + +class MapCircle extends React.Component { render() { return ( - + ); - }, -}); + } +} + +MapCircle.propTypes = propTypes; +MapCircle.defaultProps = defaultProps; const AIRMapCircle = requireNativeComponent('AIRMapCircle', MapCircle); diff --git a/components/MapMarker.js b/components/MapMarker.js index 5ee0e8ae0..29a3a0ff4 100644 --- a/components/MapMarker.js +++ b/components/MapMarker.js @@ -11,206 +11,215 @@ import { const resolveAssetSource = require('react-native/Libraries/Image/resolveAssetSource'); -// eslint-disable-next-line react/prefer-es6-class -const MapMarker = React.createClass({ - viewConfig: { - uiViewClassName: 'AIRMapMarker', - validAttributes: { - coordinate: true, - }, +const viewConfig = { + uiViewClassName: 'AIRMapMarker', + validAttributes: { + coordinate: true, }, - - propTypes: { - ...View.propTypes, - - // TODO(lmr): get rid of these? - identifier: PropTypes.string, - reuseIdentifier: PropTypes.string, - - /** - * The title of the marker. This is only used if the component has no children that - * are an ``, in which case the default callout behavior will be used, which - * will show both the `title` and the `description`, if provided. - */ - title: PropTypes.string, - - /** - * The description of the marker. This is only used if the component has no children - * that are an ``, in which case the default callout behavior will be used, - * which will show both the `title` and the `description`, if provided. - */ - description: PropTypes.string, - - /** - * A custom image to be used as the marker's icon. Only local image resources are allowed to be - * used. - */ - image: PropTypes.any, - - /** - * If no custom marker view or custom image is provided, the platform default pin will be used, - * which can be customized by this color. Ignored if a custom marker is being used. - */ - pinColor: PropTypes.string, - - /** - * The coordinate for the marker. - */ - coordinate: PropTypes.shape({ - /** - * Coordinates for the anchor point of the marker. - */ - latitude: PropTypes.number.isRequired, - longitude: PropTypes.number.isRequired, - }).isRequired, - - /** - * The offset (in points) at which to display the view. - * - * By default, the center point of an annotation view is placed at the coordinate point of the - * associated annotation. You can use this property to reposition the annotation view as - * needed. This x and y offset values are measured in points. Positive offset values move the - * annotation view down and to the right, while negative values move it up and to the left. - * - * For android, see the `anchor` prop. - * - * @platform ios - */ - centerOffset: PropTypes.shape({ - /** - * Offset from the anchor point - */ - x: PropTypes.number.isRequired, - y: PropTypes.number.isRequired, - }), - - /** - * The offset (in points) at which to place the callout bubble. - * - * This property determines the additional distance by which to move the callout bubble. When - * this property is set to (0, 0), the anchor point of the callout bubble is placed on the - * top-center point of the marker view’s frame. Specifying positive offset values moves the - * callout bubble down and to the right, while specifying negative values moves it up and to - * the left. - * - * For android, see the `calloutAnchor` prop. - * - * @platform ios - */ - calloutOffset: PropTypes.shape({ - /** - * Offset to the callout - */ - x: PropTypes.number.isRequired, - y: PropTypes.number.isRequired, - }), - - /** - * Sets the anchor point for the marker. - * - * The anchor specifies the point in the icon image that is anchored to the marker's position - * on the Earth's surface. - * - * The anchor point is specified in the continuous space [0.0, 1.0] x [0.0, 1.0], where (0, 0) - * is the top-left corner of the image, and (1, 1) is the bottom-right corner. The anchoring - * point in a W x H image is the nearest discrete grid point in a (W + 1) x (H + 1) grid, - * obtained by scaling the then rounding. For example, in a 4 x 2 image, the anchor point - * (0.7, 0.6) resolves to the grid point at (3, 1). - * - * For ios, see the `centerOffset` prop. - * - * @platform android - */ - anchor: PropTypes.shape({ - /** - * Offset to the callout - */ - x: PropTypes.number.isRequired, - y: PropTypes.number.isRequired, - }), - - /** - * Specifies the point in the marker image at which to anchor the callout when it is displayed. - * This is specified in the same coordinate system as the anchor. See the `andor` prop for more - * details. - * - * The default is the top middle of the image. - * - * For ios, see the `calloutOffset` prop. - * - * @platform android - */ - calloutAnchor: PropTypes.shape({ - /** - * Offset to the callout - */ - x: PropTypes.number.isRequired, - y: PropTypes.number.isRequired, - }), - - /** - * Sets whether this marker should be flat against the map true or a billboard facing the - * camera false. - * - * @platform android - */ - flat: PropTypes.bool, - - draggable: PropTypes.bool, - - /** - * Callback that is called when the user presses on the marker - */ - onPress: PropTypes.func, - +}; + +const propTypes = { + ...View.propTypes, + + // TODO(lmr): get rid of these? + identifier: PropTypes.string, + reuseIdentifier: PropTypes.string, + + /** + * The title of the marker. This is only used if the component has no children that + * are an ``, in which case the default callout behavior will be used, which + * will show both the `title` and the `description`, if provided. + */ + title: PropTypes.string, + + /** + * The description of the marker. This is only used if the component has no children + * that are an ``, in which case the default callout behavior will be used, + * which will show both the `title` and the `description`, if provided. + */ + description: PropTypes.string, + + /** + * A custom image to be used as the marker's icon. Only local image resources are allowed to be + * used. + */ + image: PropTypes.any, + + /** + * If no custom marker view or custom image is provided, the platform default pin will be used, + * which can be customized by this color. Ignored if a custom marker is being used. + */ + pinColor: PropTypes.string, + + /** + * The coordinate for the marker. + */ + coordinate: PropTypes.shape({ /** - * Callback that is called when the user selects the marker, before the callout is shown. - * - * @platform ios + * Coordinates for the anchor point of the marker. */ - onSelect: PropTypes.func, - + latitude: PropTypes.number.isRequired, + longitude: PropTypes.number.isRequired, + }).isRequired, + + /** + * The offset (in points) at which to display the view. + * + * By default, the center point of an annotation view is placed at the coordinate point of the + * associated annotation. You can use this property to reposition the annotation view as + * needed. This x and y offset values are measured in points. Positive offset values move the + * annotation view down and to the right, while negative values move it up and to the left. + * + * For android, see the `anchor` prop. + * + * @platform ios + */ + centerOffset: PropTypes.shape({ /** - * Callback that is called when the marker is deselected, before the callout is hidden. - * - * @platform ios + * Offset from the anchor point */ - onDeselect: PropTypes.func, - - /** - * Callback that is called when the user taps the callout view. - */ - onCalloutPress: PropTypes.func, - + x: PropTypes.number.isRequired, + y: PropTypes.number.isRequired, + }), + + /** + * The offset (in points) at which to place the callout bubble. + * + * This property determines the additional distance by which to move the callout bubble. When + * this property is set to (0, 0), the anchor point of the callout bubble is placed on the + * top-center point of the marker view’s frame. Specifying positive offset values moves the + * callout bubble down and to the right, while specifying negative values moves it up and to + * the left. + * + * For android, see the `calloutAnchor` prop. + * + * @platform ios + */ + calloutOffset: PropTypes.shape({ /** - * Callback that is called when the user initiates a drag on this marker (if it is draggable) + * Offset to the callout */ - onDragStart: PropTypes.func, - + x: PropTypes.number.isRequired, + y: PropTypes.number.isRequired, + }), + + /** + * Sets the anchor point for the marker. + * + * The anchor specifies the point in the icon image that is anchored to the marker's position + * on the Earth's surface. + * + * The anchor point is specified in the continuous space [0.0, 1.0] x [0.0, 1.0], where (0, 0) + * is the top-left corner of the image, and (1, 1) is the bottom-right corner. The anchoring + * point in a W x H image is the nearest discrete grid point in a (W + 1) x (H + 1) grid, + * obtained by scaling the then rounding. For example, in a 4 x 2 image, the anchor point + * (0.7, 0.6) resolves to the grid point at (3, 1). + * + * For ios, see the `centerOffset` prop. + * + * @platform android + */ + anchor: PropTypes.shape({ /** - * Callback called continuously as the marker is dragged + * Offset to the callout */ - onDrag: PropTypes.func, - + x: PropTypes.number.isRequired, + y: PropTypes.number.isRequired, + }), + + /** + * Specifies the point in the marker image at which to anchor the callout when it is displayed. + * This is specified in the same coordinate system as the anchor. See the `andor` prop for more + * details. + * + * The default is the top middle of the image. + * + * For ios, see the `calloutOffset` prop. + * + * @platform android + */ + calloutAnchor: PropTypes.shape({ /** - * Callback that is called when a drag on this marker finishes. This is usually the point you - * will want to setState on the marker's coordinate again + * Offset to the callout */ - onDragEnd: PropTypes.func, - - }, + x: PropTypes.number.isRequired, + y: PropTypes.number.isRequired, + }), + + /** + * Sets whether this marker should be flat against the map true or a billboard facing the + * camera false. + * + * @platform android + */ + flat: PropTypes.bool, + + draggable: PropTypes.bool, + + /** + * Callback that is called when the user presses on the marker + */ + onPress: PropTypes.func, + + /** + * Callback that is called when the user selects the marker, before the callout is shown. + * + * @platform ios + */ + onSelect: PropTypes.func, + + /** + * Callback that is called when the marker is deselected, before the callout is hidden. + * + * @platform ios + */ + onDeselect: PropTypes.func, + + /** + * Callback that is called when the user taps the callout view. + */ + onCalloutPress: PropTypes.func, + + /** + * Callback that is called when the user initiates a drag on this marker (if it is draggable) + */ + onDragStart: PropTypes.func, + + /** + * Callback called continuously as the marker is dragged + */ + onDrag: PropTypes.func, + + /** + * Callback that is called when a drag on this marker finishes. This is usually the point you + * will want to setState on the marker's coordinate again + */ + onDragEnd: PropTypes.func, +}; + +const defaultProps = { + onPress() {}, +}; + +class MapMarker extends React.Component { + constructor(props) { + super(props); + + this.showCallout = this.showCallout.bind(this); + this.hideCallout = this.hideCallout.bind(this); + } showCallout() { this._runCommand('showCallout', []); - }, + } hideCallout() { this._runCommand('hideCallout', []); - }, + } _getHandle() { return findNodeHandle(this.refs.marker); - }, + } _runCommand(name, args) { switch (Platform.OS) { @@ -229,13 +238,7 @@ const MapMarker = React.createClass({ ); break; } - }, - - _onPress(e) { - if (this.props.onPress) { - this.props.onPress(e); - } - }, + } render() { let image; @@ -250,11 +253,14 @@ const MapMarker = React.createClass({ {...this.props} image={image} style={[styles.marker, this.props.style]} - onPress={this._onPress} /> ); - }, -}); + } +} + +MapMarker.propTypes = propTypes; +MapMarker.defaultProps = defaultProps; +MapMarker.viewConfig = viewConfig; const styles = StyleSheet.create({ marker: { diff --git a/components/MapPolygon.js b/components/MapPolygon.js index 42c22e354..1bfe0928d 100644 --- a/components/MapPolygon.js +++ b/components/MapPolygon.js @@ -4,147 +4,138 @@ import { requireNativeComponent, } from 'react-native'; -// eslint-disable-next-line react/prefer-es6-class -const MapPolygon = React.createClass({ - propTypes: { - ...View.propTypes, +const propTypes = { + ...View.propTypes, + /** + * An array of coordinates to describe the polygon + */ + coordinates: PropTypes.arrayOf(PropTypes.shape({ /** - * An array of coordinates to describe the polygon + * Latitude/Longitude coordinates */ - coordinates: PropTypes.arrayOf(PropTypes.shape({ - /** - * Latitude/Longitude coordinates - */ - latitude: PropTypes.number.isRequired, - longitude: PropTypes.number.isRequired, - })), - - /** - * Callback that is called when the user presses on the polygon - */ - onPress: PropTypes.func, - - /** - * The stroke width to use for the path. - */ - strokeWidth: PropTypes.number, - - /** - * The stroke color to use for the path. - */ - strokeColor: PropTypes.string, - - /** - * The fill color to use for the path. - */ - fillColor: PropTypes.string, - - /** - * The order in which this tile overlay is drawn with respect to other overlays. An overlay - * with a larger z-index is drawn over overlays with smaller z-indices. The order of overlays - * with the same z-index is arbitrary. The default zIndex is 0. - * - * @platform android - */ - zIndex: PropTypes.number, - - /** - * The line cap style to apply to the open ends of the path. - * The default style is `round`. - * - * @platform ios - */ - lineCap: PropTypes.oneOf([ - 'butt', - 'round', - 'square', - ]), - - /** - * The line join style to apply to corners of the path. - * The default style is `round`. - * - * @platform ios - */ - lineJoin: PropTypes.oneOf([ - 'miter', - 'round', - 'bevel', - ]), - - /** - * The limiting value that helps avoid spikes at junctions between connected line segments. - * The miter limit helps you avoid spikes in paths that use the `miter` `lineJoin` style. If - * the ratio of the miter length—that is, the diagonal length of the miter join—to the line - * thickness exceeds the miter limit, the joint is converted to a bevel join. The default - * miter limit is 10, which results in the conversion of miters whose angle at the joint - * is less than 11 degrees. - * - * @platform ios - */ - miterLimit: PropTypes.number, - - /** - * Boolean to indicate whether to draw each segment of the line as a geodesic as opposed to - * straight lines on the Mercator projection. A geodesic is the shortest path between two - * points on the Earth's surface. The geodesic curve is constructed assuming the Earth is - * a sphere. - * - * @platform android - */ - geodesic: PropTypes.bool, - - /** - * The offset (in points) at which to start drawing the dash pattern. - * - * Use this property to start drawing a dashed line partway through a segment or gap. For - * example, a phase value of 6 for the patter 5-2-3-2 would cause drawing to begin in the - * middle of the first gap. - * - * The default value of this property is 0. - * - * @platform ios - */ - lineDashPhase: PropTypes.number, - - /** - * An array of numbers specifying the dash pattern to use for the path. - * - * The array contains one or more numbers that indicate the lengths (measured in points) of the - * line segments and gaps in the pattern. The values in the array alternate, starting with the - * first line segment length, followed by the first gap length, followed by the second line - * segment length, and so on. - * - * This property is set to `null` by default, which indicates no line dash pattern. - * - * @platform ios - */ - lineDashPattern: PropTypes.arrayOf(PropTypes.number), - }, - - getDefaultProps() { - return { - strokeColor: '#000', - strokeWidth: 1, - }; - }, - - _onPress(e) { - if (this.props.onPress) { - this.props.onPress(e); - } - }, - + latitude: PropTypes.number.isRequired, + longitude: PropTypes.number.isRequired, + })), + + /** + * Callback that is called when the user presses on the polygon + */ + onPress: PropTypes.func, + + /** + * The stroke width to use for the path. + */ + strokeWidth: PropTypes.number, + + /** + * The stroke color to use for the path. + */ + strokeColor: PropTypes.string, + + /** + * The fill color to use for the path. + */ + fillColor: PropTypes.string, + + /** + * The order in which this tile overlay is drawn with respect to other overlays. An overlay + * with a larger z-index is drawn over overlays with smaller z-indices. The order of overlays + * with the same z-index is arbitrary. The default zIndex is 0. + * + * @platform android + */ + zIndex: PropTypes.number, + + /** + * The line cap style to apply to the open ends of the path. + * The default style is `round`. + * + * @platform ios + */ + lineCap: PropTypes.oneOf([ + 'butt', + 'round', + 'square', + ]), + + /** + * The line join style to apply to corners of the path. + * The default style is `round`. + * + * @platform ios + */ + lineJoin: PropTypes.oneOf([ + 'miter', + 'round', + 'bevel', + ]), + + /** + * The limiting value that helps avoid spikes at junctions between connected line segments. + * The miter limit helps you avoid spikes in paths that use the `miter` `lineJoin` style. If + * the ratio of the miter length—that is, the diagonal length of the miter join—to the line + * thickness exceeds the miter limit, the joint is converted to a bevel join. The default + * miter limit is 10, which results in the conversion of miters whose angle at the joint + * is less than 11 degrees. + * + * @platform ios + */ + miterLimit: PropTypes.number, + + /** + * Boolean to indicate whether to draw each segment of the line as a geodesic as opposed to + * straight lines on the Mercator projection. A geodesic is the shortest path between two + * points on the Earth's surface. The geodesic curve is constructed assuming the Earth is + * a sphere. + * + * @platform android + */ + geodesic: PropTypes.bool, + + /** + * The offset (in points) at which to start drawing the dash pattern. + * + * Use this property to start drawing a dashed line partway through a segment or gap. For + * example, a phase value of 6 for the patter 5-2-3-2 would cause drawing to begin in the + * middle of the first gap. + * + * The default value of this property is 0. + * + * @platform ios + */ + lineDashPhase: PropTypes.number, + + /** + * An array of numbers specifying the dash pattern to use for the path. + * + * The array contains one or more numbers that indicate the lengths (measured in points) of the + * line segments and gaps in the pattern. The values in the array alternate, starting with the + * first line segment length, followed by the first gap length, followed by the second line + * segment length, and so on. + * + * This property is set to `null` by default, which indicates no line dash pattern. + * + * @platform ios + */ + lineDashPattern: PropTypes.arrayOf(PropTypes.number), +}; + +const defaultProps = { + strokeColor: '#000', + strokeWidth: 1, +}; + +class MapPolygon extends React.Component { render() { return ( - + ); - }, -}); + } +} + +MapPolygon.propTypes = propTypes; +MapPolygon.defaultProps = defaultProps; const AIRMapPolygon = requireNativeComponent('AIRMapPolygon', MapPolygon); diff --git a/components/MapPolyline.js b/components/MapPolyline.js index 397b4ca0b..8a15ad3a5 100644 --- a/components/MapPolyline.js +++ b/components/MapPolyline.js @@ -4,133 +4,133 @@ import { requireNativeComponent, } from 'react-native'; -// eslint-disable-next-line react/prefer-es6-class -const MapPolyline = React.createClass({ - propTypes: { - ...View.propTypes, +const propTypes = { + ...View.propTypes, + /** + * An array of coordinates to describe the polygon + */ + coordinates: PropTypes.arrayOf(PropTypes.shape({ /** - * An array of coordinates to describe the polygon + * Latitude/Longitude coordinates */ - coordinates: PropTypes.arrayOf(PropTypes.shape({ - /** - * Latitude/Longitude coordinates - */ - latitude: PropTypes.number.isRequired, - longitude: PropTypes.number.isRequired, - })), - - /** - * Callback that is called when the user presses on the polyline - */ - onPress: PropTypes.func, - - /** - * The stroke width to use for the path. - */ - strokeWidth: PropTypes.number, - - /** - * The stroke color to use for the path. - */ - strokeColor: PropTypes.string, - - /** - * The order in which this tile overlay is drawn with respect to other overlays. An overlay - * with a larger z-index is drawn over overlays with smaller z-indices. The order of overlays - * with the same z-index is arbitrary. The default zIndex is 0. - * - * @platform android - */ - zIndex: PropTypes.number, - - /** - * The line cap style to apply to the open ends of the path. - * The default style is `round`. - * - * @platform ios - */ - lineCap: PropTypes.oneOf([ - 'butt', - 'round', - 'square', - ]), - - /** - * The line join style to apply to corners of the path. - * The default style is `round`. - * - * @platform ios - */ - lineJoin: PropTypes.oneOf([ - 'miter', - 'round', - 'bevel', - ]), - - /** - * The limiting value that helps avoid spikes at junctions between connected line segments. - * The miter limit helps you avoid spikes in paths that use the `miter` `lineJoin` style. If - * the ratio of the miter length—that is, the diagonal length of the miter join—to the line - * thickness exceeds the miter limit, the joint is converted to a bevel join. The default - * miter limit is 10, which results in the conversion of miters whose angle at the joint - * is less than 11 degrees. - * - * @platform ios - */ - miterLimit: PropTypes.number, - - /** - * Boolean to indicate whether to draw each segment of the line as a geodesic as opposed to - * straight lines on the Mercator projection. A geodesic is the shortest path between two - * points on the Earth's surface. The geodesic curve is constructed assuming the Earth is - * a sphere. - * - * @platform android - */ - geodesic: PropTypes.bool, - - /** - * The offset (in points) at which to start drawing the dash pattern. - * - * Use this property to start drawing a dashed line partway through a segment or gap. For - * example, a phase value of 6 for the patter 5-2-3-2 would cause drawing to begin in the - * middle of the first gap. - * - * The default value of this property is 0. - * - * @platform ios - */ - lineDashPhase: PropTypes.number, - - /** - * An array of numbers specifying the dash pattern to use for the path. - * - * The array contains one or more numbers that indicate the lengths (measured in points) of the - * line segments and gaps in the pattern. The values in the array alternate, starting with the - * first line segment length, followed by the first gap length, followed by the second line - * segment length, and so on. - * - * This property is set to `null` by default, which indicates no line dash pattern. - * - * @platform ios - */ - lineDashPattern: PropTypes.arrayOf(PropTypes.number), - }, - - getDefaultProps() { - return { - strokeColor: '#000', - strokeWidth: 1, - }; - }, - + latitude: PropTypes.number.isRequired, + longitude: PropTypes.number.isRequired, + })), + + /** + * Callback that is called when the user presses on the polyline + */ + onPress: PropTypes.func, + + /** + * The stroke width to use for the path. + */ + strokeWidth: PropTypes.number, + + /** + * The stroke color to use for the path. + */ + strokeColor: PropTypes.string, + + /** + * The order in which this tile overlay is drawn with respect to other overlays. An overlay + * with a larger z-index is drawn over overlays with smaller z-indices. The order of overlays + * with the same z-index is arbitrary. The default zIndex is 0. + * + * @platform android + */ + zIndex: PropTypes.number, + + /** + * The line cap style to apply to the open ends of the path. + * The default style is `round`. + * + * @platform ios + */ + lineCap: PropTypes.oneOf([ + 'butt', + 'round', + 'square', + ]), + + /** + * The line join style to apply to corners of the path. + * The default style is `round`. + * + * @platform ios + */ + lineJoin: PropTypes.oneOf([ + 'miter', + 'round', + 'bevel', + ]), + + /** + * The limiting value that helps avoid spikes at junctions between connected line segments. + * The miter limit helps you avoid spikes in paths that use the `miter` `lineJoin` style. If + * the ratio of the miter length—that is, the diagonal length of the miter join—to the line + * thickness exceeds the miter limit, the joint is converted to a bevel join. The default + * miter limit is 10, which results in the conversion of miters whose angle at the joint + * is less than 11 degrees. + * + * @platform ios + */ + miterLimit: PropTypes.number, + + /** + * Boolean to indicate whether to draw each segment of the line as a geodesic as opposed to + * straight lines on the Mercator projection. A geodesic is the shortest path between two + * points on the Earth's surface. The geodesic curve is constructed assuming the Earth is + * a sphere. + * + * @platform android + */ + geodesic: PropTypes.bool, + + /** + * The offset (in points) at which to start drawing the dash pattern. + * + * Use this property to start drawing a dashed line partway through a segment or gap. For + * example, a phase value of 6 for the patter 5-2-3-2 would cause drawing to begin in the + * middle of the first gap. + * + * The default value of this property is 0. + * + * @platform ios + */ + lineDashPhase: PropTypes.number, + + /** + * An array of numbers specifying the dash pattern to use for the path. + * + * The array contains one or more numbers that indicate the lengths (measured in points) of the + * line segments and gaps in the pattern. The values in the array alternate, starting with the + * first line segment length, followed by the first gap length, followed by the second line + * segment length, and so on. + * + * This property is set to `null` by default, which indicates no line dash pattern. + * + * @platform ios + */ + lineDashPattern: PropTypes.arrayOf(PropTypes.number), +}; + +const defaultProps = { + strokeColor: '#000', + strokeWidth: 1, +}; + +class MapPolyline extends React.Component { render() { return ( ); - }, -}); + } +} + +MapPolyline.propTypes = propTypes; +MapPolyline.defaultProps = defaultProps; const AIRMapPolyline = requireNativeComponent('AIRMapPolyline', MapPolyline); diff --git a/components/MapView.js b/components/MapView.js index cf5ae344d..23292615e 100644 --- a/components/MapView.js +++ b/components/MapView.js @@ -15,309 +15,314 @@ import MapPolygon from './MapPolygon'; import MapCircle from './MapCircle'; import MapCallout from './MapCallout'; -// eslint-disable-next-line react/prefer-es6-class -const MapView = React.createClass({ - viewConfig: { - uiViewClassName: 'AIRMap', - validAttributes: { - region: true, - }, +const viewConfig = { + uiViewClassName: 'AIRMap', + validAttributes: { + region: true, }, - - propTypes: { - ...View.propTypes, - /** - * Used to style and layout the `MapView`. See `StyleSheet.js` and - * `ViewStylePropTypes.js` for more info. - */ - style: View.propTypes.style, - - /** - * If `true` the app will ask for the user's location. - * Default value is `false`. - * - * **NOTE**: You need to add NSLocationWhenInUseUsageDescription key in - * Info.plist to enable geolocation, otherwise it is going - * to *fail silently*! - */ - showsUserLocation: PropTypes.bool, - - /** - * If `false` hide the button to move map to the current user's location. - * Default value is `true`. - * - * @platform android - */ - showsMyLocationButton: PropTypes.bool, - - /** - * If `true` the map will focus on the user's location. This only works if - * `showsUserLocation` is true and the user has shared their location. - * Default value is `false`. - * - * @platform ios - */ - followsUserLocation: PropTypes.bool, - - /** - * If `false` points of interest won't be displayed on the map. - * Default value is `true`. - * - */ - showsPointsOfInterest: PropTypes.bool, - - /** - * If `false` compass won't be displayed on the map. - * Default value is `true`. - * - * @platform ios - */ - showsCompass: PropTypes.bool, - - /** - * If `false` the user won't be able to pinch/zoom the map. - * Default value is `true`. - * - */ - zoomEnabled: PropTypes.bool, - - /** - * If `false` the user won't be able to pinch/rotate the map. - * Default value is `true`. - * - */ - rotateEnabled: PropTypes.bool, - - /** - * If `true` the map will be cached to an Image for performance - * Default value is `false`. - * - */ - cacheEnabled: PropTypes.bool, - - /** - * If `true` the map will be showing a loading indicator - * Default value is `false`. - * - */ - loadingEnabled: PropTypes.bool, - - /** - * Loading background color while generating map cache image or loading the map - * Default color is light gray. - * - */ - loadingBackgroundColor: ColorPropType, - - /** - * Loading indicator color while generating map cache image or loading the map - * Default color is gray color for iOS, theme color for Android. - * - */ - loadingIndicatorColor: ColorPropType, - - /** - * If `false` the user won't be able to change the map region being displayed. - * Default value is `true`. - * - */ - scrollEnabled: PropTypes.bool, - - /** - * If `false` the user won't be able to adjust the camera’s pitch angle. - * Default value is `true`. - * - */ - pitchEnabled: PropTypes.bool, - - /** - * If `false` will hide 'Navigate' and 'Open in Maps' buttons on marker press - * Default value is `true`. - * - * @platform android - */ - toolbarEnabled: PropTypes.bool, - - /** - * A Boolean indicating whether the map shows scale information. - * Default value is `false` - * - */ - showsScale: PropTypes.bool, - - /** - * A Boolean indicating whether the map displays extruded building information. - * Default value is `true`. - */ - showsBuildings: PropTypes.bool, - - /** - * A Boolean value indicating whether the map displays traffic information. - * Default value is `false`. - */ - showsTraffic: PropTypes.bool, - - /** - * A Boolean indicating whether indoor maps should be enabled. - * Default value is `false` - * - * @platform android - */ - showsIndoors: PropTypes.bool, - - /** - * The map type to be displayed. - * - * - standard: standard road map (default) - * - satellite: satellite view - * - hybrid: satellite view with roads and points of interest overlayed - * - terrain: (Android only) topographic view - */ - mapType: PropTypes.oneOf([ - 'standard', - 'satellite', - 'hybrid', - 'terrain', - ]), - - /** - * The region to be displayed by the map. - * - * The region is defined by the center coordinates and the span of - * coordinates to display. - */ - region: PropTypes.shape({ - /** - * Coordinates for the center of the map. - */ - latitude: PropTypes.number.isRequired, - longitude: PropTypes.number.isRequired, - - /** - * Difference between the minimun and the maximum latitude/longitude - * to be displayed. - */ - latitudeDelta: PropTypes.number.isRequired, - longitudeDelta: PropTypes.number.isRequired, - }), - - /** - * The initial region to be displayed by the map. Use this prop instead of `region` - * only if you don't want to control the viewport of the map besides the initial region. - * - * Changing this prop after the component has mounted will not result in a region change. - * - * This is similar to the `initialValue` prop of a text input. - */ - initialRegion: PropTypes.shape({ - /** - * Coordinates for the center of the map. - */ - latitude: PropTypes.number.isRequired, - longitude: PropTypes.number.isRequired, - - /** - * Difference between the minimun and the maximum latitude/longitude - * to be displayed. - */ - latitudeDelta: PropTypes.number.isRequired, - longitudeDelta: PropTypes.number.isRequired, - }), - - /** - * Maximum size of area that can be displayed. - * - * @platform ios - */ - maxDelta: PropTypes.number, - - /** - * Minimum size of area that can be displayed. - * - * @platform ios - */ - minDelta: PropTypes.number, - - /** - * Insets for the map's legal label, originally at bottom left of the map. - * See `EdgeInsetsPropType.js` for more information. - */ - legalLabelInsets: EdgeInsetsPropType, - - /** - * Callback that is called continuously when the user is dragging the map. - */ - onRegionChange: PropTypes.func, - - /** - * Callback that is called once, when the user is done moving the map. - */ - onRegionChangeComplete: PropTypes.func, - - /** - * Callback that is called when user taps on the map. - */ - onPress: PropTypes.func, - - /** - * Callback that is called when user makes a "long press" somewhere on the map. - */ - onLongPress: PropTypes.func, - - /** - * Callback that is called when user makes a "drag" somewhere on the map - */ - onPanDrag: PropTypes.func, - - /** - * Callback that is called when a marker on the map is tapped by the user. - */ - onMarkerPress: PropTypes.func, - - /** - * Callback that is called when a marker on the map becomes selected. This will be called when - * the callout for that marker is about to be shown. - * - * @platform ios - */ - onMarkerSelect: PropTypes.func, - - /** - * Callback that is called when a marker on the map becomes deselected. This will be called when - * the callout for that marker is about to be hidden. - * - * @platform ios - */ - onMarkerDeselect: PropTypes.func, - - /** - * Callback that is called when a callout is tapped by the user. - */ - onCalloutPress: PropTypes.func, - - /** - * Callback that is called when the user initiates a drag on a marker (if it is draggable) - */ - onMarkerDragStart: PropTypes.func, - - /** - * Callback called continuously as a marker is dragged - */ - onMarkerDrag: PropTypes.func, - - /** - * Callback that is called when a drag on a marker finishes. This is usually the point you - * will want to setState on the marker's coordinate again - */ - onMarkerDragEnd: PropTypes.func, - - }, - - getInitialState() { - return { +}; + +const propTypes = { + ...View.propTypes, + /** + * Used to style and layout the `MapView`. See `StyleSheet.js` and + * `ViewStylePropTypes.js` for more info. + */ + style: View.propTypes.style, + + /** + * If `true` the app will ask for the user's location. + * Default value is `false`. + * + * **NOTE**: You need to add NSLocationWhenInUseUsageDescription key in + * Info.plist to enable geolocation, otherwise it is going + * to *fail silently*! + */ + showsUserLocation: PropTypes.bool, + + /** + * If `false` hide the button to move map to the current user's location. + * Default value is `true`. + * + * @platform android + */ + showsMyLocationButton: PropTypes.bool, + + /** + * If `true` the map will focus on the user's location. This only works if + * `showsUserLocation` is true and the user has shared their location. + * Default value is `false`. + * + * @platform ios + */ + followsUserLocation: PropTypes.bool, + + /** + * If `false` points of interest won't be displayed on the map. + * Default value is `true`. + * + */ + showsPointsOfInterest: PropTypes.bool, + + /** + * If `false` compass won't be displayed on the map. + * Default value is `true`. + * + * @platform ios + */ + showsCompass: PropTypes.bool, + + /** + * If `false` the user won't be able to pinch/zoom the map. + * Default value is `true`. + * + */ + zoomEnabled: PropTypes.bool, + + /** + * If `false` the user won't be able to pinch/rotate the map. + * Default value is `true`. + * + */ + rotateEnabled: PropTypes.bool, + + /** + * If `true` the map will be cached to an Image for performance + * Default value is `false`. + * + */ + cacheEnabled: PropTypes.bool, + + /** + * If `true` the map will be showing a loading indicator + * Default value is `false`. + * + */ + loadingEnabled: PropTypes.bool, + + /** + * Loading background color while generating map cache image or loading the map + * Default color is light gray. + * + */ + loadingBackgroundColor: ColorPropType, + + /** + * Loading indicator color while generating map cache image or loading the map + * Default color is gray color for iOS, theme color for Android. + * + */ + loadingIndicatorColor: ColorPropType, + + /** + * If `false` the user won't be able to change the map region being displayed. + * Default value is `true`. + * + */ + scrollEnabled: PropTypes.bool, + + /** + * If `false` the user won't be able to adjust the camera’s pitch angle. + * Default value is `true`. + * + */ + pitchEnabled: PropTypes.bool, + + /** + * If `false` will hide 'Navigate' and 'Open in Maps' buttons on marker press + * Default value is `true`. + * + * @platform android + */ + toolbarEnabled: PropTypes.bool, + + /** + * A Boolean indicating whether the map shows scale information. + * Default value is `false` + * + */ + showsScale: PropTypes.bool, + + /** + * A Boolean indicating whether the map displays extruded building information. + * Default value is `true`. + */ + showsBuildings: PropTypes.bool, + + /** + * A Boolean value indicating whether the map displays traffic information. + * Default value is `false`. + */ + showsTraffic: PropTypes.bool, + + /** + * A Boolean indicating whether indoor maps should be enabled. + * Default value is `false` + * + * @platform android + */ + showsIndoors: PropTypes.bool, + + /** + * The map type to be displayed. + * + * - standard: standard road map (default) + * - satellite: satellite view + * - hybrid: satellite view with roads and points of interest overlayed + * - terrain: (Android only) topographic view + */ + mapType: PropTypes.oneOf([ + 'standard', + 'satellite', + 'hybrid', + 'terrain', + ]), + + /** + * The region to be displayed by the map. + * + * The region is defined by the center coordinates and the span of + * coordinates to display. + */ + region: PropTypes.shape({ + /** + * Coordinates for the center of the map. + */ + latitude: PropTypes.number.isRequired, + longitude: PropTypes.number.isRequired, + + /** + * Difference between the minimun and the maximum latitude/longitude + * to be displayed. + */ + latitudeDelta: PropTypes.number.isRequired, + longitudeDelta: PropTypes.number.isRequired, + }), + + /** + * The initial region to be displayed by the map. Use this prop instead of `region` + * only if you don't want to control the viewport of the map besides the initial region. + * + * Changing this prop after the component has mounted will not result in a region change. + * + * This is similar to the `initialValue` prop of a text input. + */ + initialRegion: PropTypes.shape({ + /** + * Coordinates for the center of the map. + */ + latitude: PropTypes.number.isRequired, + longitude: PropTypes.number.isRequired, + + /** + * Difference between the minimun and the maximum latitude/longitude + * to be displayed. + */ + latitudeDelta: PropTypes.number.isRequired, + longitudeDelta: PropTypes.number.isRequired, + }), + + /** + * Maximum size of area that can be displayed. + * + * @platform ios + */ + maxDelta: PropTypes.number, + + /** + * Minimum size of area that can be displayed. + * + * @platform ios + */ + minDelta: PropTypes.number, + + /** + * Insets for the map's legal label, originally at bottom left of the map. + * See `EdgeInsetsPropType.js` for more information. + */ + legalLabelInsets: EdgeInsetsPropType, + + /** + * Callback that is called continuously when the user is dragging the map. + */ + onRegionChange: PropTypes.func, + + /** + * Callback that is called once, when the user is done moving the map. + */ + onRegionChangeComplete: PropTypes.func, + + /** + * Callback that is called when user taps on the map. + */ + onPress: PropTypes.func, + + /** + * Callback that is called when user makes a "long press" somewhere on the map. + */ + onLongPress: PropTypes.func, + + /** + * Callback that is called when user makes a "drag" somewhere on the map + */ + onPanDrag: PropTypes.func, + + /** + * Callback that is called when a marker on the map is tapped by the user. + */ + onMarkerPress: PropTypes.func, + + /** + * Callback that is called when a marker on the map becomes selected. This will be called when + * the callout for that marker is about to be shown. + * + * @platform ios + */ + onMarkerSelect: PropTypes.func, + + /** + * Callback that is called when a marker on the map becomes deselected. This will be called when + * the callout for that marker is about to be hidden. + * + * @platform ios + */ + onMarkerDeselect: PropTypes.func, + + /** + * Callback that is called when a callout is tapped by the user. + */ + onCalloutPress: PropTypes.func, + + /** + * Callback that is called when the user initiates a drag on a marker (if it is draggable) + */ + onMarkerDragStart: PropTypes.func, + + /** + * Callback called continuously as a marker is dragged + */ + onMarkerDrag: PropTypes.func, + + /** + * Callback that is called when a drag on a marker finishes. This is usually the point you + * will want to setState on the marker's coordinate again + */ + onMarkerDragEnd: PropTypes.func, + +}; + +class MapView extends React.Component { + constructor(props) { + super(props); + + this.state = { isReady: Platform.OS === 'ios', }; - }, + + this._onMapReady = this._onMapReady.bind(this); + this._onChange = this._onChange.bind(this); + this._onLayout = this._onLayout.bind(this); + } componentDidMount() { const { region, initialRegion } = this.props; @@ -326,7 +331,7 @@ const MapView = React.createClass({ } else if (initialRegion && this.state.isReady) { this.refs.map.setNativeProps({ region: initialRegion }); } - }, + } componentWillUpdate(nextProps) { const a = this.__lastRegion; @@ -340,7 +345,7 @@ const MapView = React.createClass({ ) { this.refs.map.setNativeProps({ region: b }); } - }, + } _onMapReady() { const { region, initialRegion } = this.props; @@ -350,7 +355,7 @@ const MapView = React.createClass({ this.refs.map.setNativeProps({ region: initialRegion }); } this.setState({ isReady: true }); - }, + } _onLayout(e) { const { region, initialRegion, onLayout } = this.props; @@ -363,9 +368,9 @@ const MapView = React.createClass({ this.refs.map.setNativeProps({ region: initialRegion }); } onLayout && onLayout(e); - }, + } - _onChange(event: Event) { + _onChange(event) { this.__lastRegion = event.nativeEvent.region; if (event.nativeEvent.continuous) { this.props.onRegionChange && @@ -374,34 +379,34 @@ const MapView = React.createClass({ this.props.onRegionChangeComplete && this.props.onRegionChangeComplete(event.nativeEvent.region); } - }, + } animateToRegion(region, duration) { this._runCommand('animateToRegion', [region, duration || 500]); - }, + } animateToCoordinate(latLng, duration) { this._runCommand('animateToCoordinate', [latLng, duration || 500]); - }, + } fitToElements(animated) { this._runCommand('fitToElements', [animated]); - }, + } fitToSuppliedMarkers(markers, animated) { this._runCommand('fitToSuppliedMarkers', [markers, animated]); - }, + } takeSnapshot(width, height, region, callback) { if (!region) { region = this.props.region || this.props.initialRegion; } this._runCommand('takeSnapshot', [width, height, region, callback]); - }, + } _getHandle() { return findNodeHandle(this.refs.map); - }, + } _runCommand(name, args) { switch (Platform.OS) { @@ -420,7 +425,7 @@ const MapView = React.createClass({ ); break; } - }, + } render() { let props; @@ -452,8 +457,11 @@ const MapView = React.createClass({ return ( ); - }, -}); + } +} + +MapView.propTypes = propTypes; +MapView.viewConfig = viewConfig; const AIRMap = requireNativeComponent('AIRMap', MapView, { nativeOnly: { diff --git a/docs/installation.md b/docs/installation.md index ecd2f4218..928c0a735 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -159,28 +159,27 @@ const styles = StyleSheet.create({ }, }); -module.exports = React.createClass({ - - render: function () { - const { region } = this.props; - console.log(region); - - return ( - - - - - ) - } -}) +module.exports = class MyApp extends React.Component { + render() { + const { region } = this.props; + console.log(region); + + return ( + + + + + ); + } +} ``` 2. Run "android" and make sure every packages is updated. 3. If not installed yet, you have to install the following packages : diff --git a/example/App.js b/example/App.js index 2e8c55495..aa4f6deb5 100644 --- a/example/App.js +++ b/example/App.js @@ -24,23 +24,26 @@ const LoadingMap = require('./examples/LoadingMap'); const TakeSnapshot = require('./examples/TakeSnapshot'); const FitToSuppliedMarkers = require('./examples/FitToSuppliedMarkers'); -const App = React.createClass({ +class App extends React.Component { + constructor(props) { + super(props); - getInitialState() { - return { Component: null }; - }, + this.state = { + Component: null, + }; + } - renderExample([Component, title], i) { + renderExample([Component, title]) { return ( this.setState({ Component })} > {title} ); - }, + } renderBackButton() { return ( @@ -51,7 +54,7 @@ const App = React.createClass({ ); - }, + } renderExamples(examples) { const { Component } = this.state; @@ -59,17 +62,17 @@ const App = React.createClass({ {Component && } {Component && this.renderBackButton()} - {!Component && ( + {!Component && - {examples.map(this.renderExample)} + {examples.map(example => this.renderExample(example))} - )} + } ); - }, + } render() { return this.renderExamples([ @@ -90,10 +93,10 @@ const App = React.createClass({ [LoadingMap, 'Map with loading'], [FitToSuppliedMarkers, 'Focus Map On Markers'], ]); - }, -}); + } +} -let styles = StyleSheet.create({ +const styles = StyleSheet.create({ container: { ...StyleSheet.absoluteFillObject, justifyContent: 'flex-end', diff --git a/example/examples/AnimatedMarkers.js b/example/examples/AnimatedMarkers.js index 3379a5c17..f422c136d 100644 --- a/example/examples/AnimatedMarkers.js +++ b/example/examples/AnimatedMarkers.js @@ -21,23 +21,25 @@ const LONGITUDE = -122.4324; const LATITUDE_DELTA = 0.0922; const LONGITUDE_DELTA = LATITUDE_DELTA * ASPECT_RATIO; -const AnimatedMarkers = React.createClass({ - getInitialState() { - return { +class AnimatedMarkers extends React.Component { + constructor(props) { + super(props); + + this.state = { coordinate: new Animated.Region({ latitude: LATITUDE, longitude: LONGITUDE, }), }; - }, + } animate() { const { coordinate } = this.state; coordinate.timing({ - latitude: LATITUDE + (Math.random() - 0.5) * LATITUDE_DELTA / 2, - longitude: LONGITUDE + (Math.random() - 0.5) * LONGITUDE_DELTA / 2, + latitude: LATITUDE + ((Math.random() - 0.5) * (LATITUDE_DELTA / 2)), + longitude: LONGITUDE + ((Math.random() - 0.5) * (LONGITUDE_DELTA / 2)), }).start(); - }, + } render() { return ( @@ -56,17 +58,19 @@ const AnimatedMarkers = React.createClass({ /> - - Animate - + + Animate + ); - }, -}); - + } +} -let styles = StyleSheet.create({ +const styles = StyleSheet.create({ container: { ...StyleSheet.absoluteFillObject, justifyContent: 'flex-end', diff --git a/example/examples/AnimatedViews.js b/example/examples/AnimatedViews.js index 246287fc1..801936c75 100644 --- a/example/examples/AnimatedViews.js +++ b/example/examples/AnimatedViews.js @@ -25,17 +25,17 @@ const LONGITUDE_DELTA = LATITUDE_DELTA * ASPECT_RATIO; const ITEM_SPACING = 10; const ITEM_PREVIEW = 10; -const ITEM_WIDTH = screen.width - 2 * ITEM_SPACING - 2 * ITEM_PREVIEW; +const ITEM_WIDTH = screen.width - (2 * ITEM_SPACING) - (2 * ITEM_PREVIEW); const SNAP_WIDTH = ITEM_WIDTH + ITEM_SPACING; const ITEM_PREVIEW_HEIGHT = 150; const SCALE_END = screen.width / ITEM_WIDTH; const BREAKPOINT1 = 246; const BREAKPOINT2 = 350; -const ANDROID = Platform.OS === 'android'; +class AnimatedViews extends React.Component { + constructor(props) { + super(props); -const AnimatedViews = React.createClass({ - getInitialState() { const panX = new Animated.Value(0); const panY = new Animated.Value(0); @@ -183,7 +183,7 @@ const AnimatedViews = React.createClass({ }; }); - return { + this.state = { panX, panY, animations, @@ -201,10 +201,10 @@ const AnimatedViews = React.createClass({ longitudeDelta: LONGITUDE_DELTA, }), }; - }, + } componentDidMount() { - let { region, panX, panY, scrollX, markers } = this.state; + const { region, panX, panY, scrollX, markers } = this.state; panX.addListener(this.onPanXChange); panY.addListener(this.onPanYChange); @@ -221,7 +221,7 @@ const AnimatedViews = React.createClass({ }), duration: 0, }).start(); - }, + } onStartShouldSetPanResponder(e) { // we only want to move the view if they are starting the gesture on top @@ -233,7 +233,7 @@ const AnimatedViews = React.createClass({ const topOfTap = screen.height - pageY; return topOfTap < topOfMainWindow; - }, + } onMoveShouldSetPanResponder(e) { const { panY } = this.state; @@ -242,7 +242,7 @@ const AnimatedViews = React.createClass({ const topOfTap = screen.height - pageY; return topOfTap < topOfMainWindow; - }, + } onPanXChange({ value }) { let { index, region, panX, markers } = this.state; @@ -250,7 +250,7 @@ const AnimatedViews = React.createClass({ if (index !== newIndex) { this.setState({ index: newIndex }); } - }, + } onPanYChange({ value }) { let { canMoveHorizontal, region, scrollY, scrollX, markers, index } = this.state; @@ -293,11 +293,11 @@ const AnimatedViews = React.createClass({ }).start(); } } - }, + } onRegionChange(region) { // this.state.region.setValue(region); - }, + } render() { const { @@ -382,18 +382,17 @@ const AnimatedViews = React.createClass({ ); - }, -}); - + } +} -let styles = StyleSheet.create({ +const styles = StyleSheet.create({ container: { ...StyleSheet.absoluteFillObject, }, itemContainer: { backgroundColor: 'transparent', flexDirection: 'row', - paddingHorizontal: ITEM_SPACING / 2 + ITEM_PREVIEW, + paddingHorizontal: (ITEM_SPACING / 2) + ITEM_PREVIEW, position: 'absolute', // top: screen.height - ITEM_PREVIEW_HEIGHT - 64, paddingTop: screen.height - ITEM_PREVIEW_HEIGHT - 64, @@ -405,7 +404,7 @@ let styles = StyleSheet.create({ }, item: { width: ITEM_WIDTH, - height: screen.height + 2 * ITEM_PREVIEW_HEIGHT, + height: screen.height + (2 * ITEM_PREVIEW_HEIGHT), backgroundColor: 'red', marginHorizontal: ITEM_SPACING / 2, overflow: 'hidden', diff --git a/example/examples/CachedMap.js b/example/examples/CachedMap.js index d022ce67a..2b300452e 100644 --- a/example/examples/CachedMap.js +++ b/example/examples/CachedMap.js @@ -14,14 +14,16 @@ const MapView = require('react-native-maps'); const HORIZONTAL_PADDING = 12; const VERTICAL_PADDING = 6; -const CachedMap = React.createClass({ - getInitialState() { +class CachedMap extends React.Component { + constructor(props) { + super(props); + const ds = new ListView.DataSource({ rowHasChanged: (r1, r2) => r1 !== r2 }); - return { + this.state = { dataSource: ds.cloneWithRows(COUNTRIES), cache: true, }; - }, + } toggleCache() { // a hack to force listview to reload with the same data @@ -32,55 +34,57 @@ const CachedMap = React.createClass({ cache: !this.state.cache, dataSource: this.state.dataSource.cloneWithRows(COUNTRIES), }); - }, + } render() { - let { width, height } = Dimensions.get('window'); + const { width } = Dimensions.get('window'); + const mapSize = width - (HORIZONTAL_PADDING * 2); return ( - + this.toggleCache()} + style={[styles.bubble, styles.button]} + > {this.state.cache ? 'Cached' : 'Not cached'} { - return ( - + + {region.name} + - {region.name} - - - - - - ); - }} + + + + + } /> ); - }, -}); + } +} -let styles = StyleSheet.create({ +const styles = StyleSheet.create({ container: { flex: 1, }, @@ -1823,5 +1827,4 @@ const COUNTRIES = [ }, ]; - module.exports = CachedMap; diff --git a/example/examples/Callouts.js b/example/examples/Callouts.js index 1ee756159..bd68dd3d7 100644 --- a/example/examples/Callouts.js +++ b/example/examples/Callouts.js @@ -11,10 +11,9 @@ let { } = ReactNative; const MapView = require('react-native-maps'); -const PriceMarker = require('./PriceMarker'); const CustomCallout = require('./CustomCallout'); -let { width, height } = Dimensions.get('window'); +const { width, height } = Dimensions.get('window'); const ASPECT_RATIO = width / height; const LATITUDE = 37.78825; @@ -23,9 +22,11 @@ const LATITUDE_DELTA = 0.0922; const LONGITUDE_DELTA = LATITUDE_DELTA * ASPECT_RATIO; const SPACE = 0.01; -const Callouts = React.createClass({ - getInitialState() { - return { +class Callouts extends React.Component { + constructor(props) { + super(props); + + this.state = { region: { latitude: LATITUDE, longitude: LONGITUDE, @@ -53,15 +54,15 @@ const Callouts = React.createClass({ }, ], }; - }, + } show() { this.refs.m1.showCallout(); - }, + } hide() { this.refs.m1.hideCallout(); - }, + } render() { const { region, markers } = this.state; @@ -77,7 +78,10 @@ const Callouts = React.createClass({ title="This is a title" description="This is a description" /> - + This is a plain view @@ -103,19 +107,19 @@ const Callouts = React.createClass({ - + this.show()} style={[styles.bubble, styles.button]}> Show - + this.hide()} style={[styles.bubble, styles.button]}> Hide ); - }, -}); + } +} -let styles = StyleSheet.create({ +const styles = StyleSheet.create({ container: { ...StyleSheet.absoluteFillObject, justifyContent: 'flex-end', diff --git a/example/examples/CustomCallout.js b/example/examples/CustomCallout.js index 0501cb253..783fd7195 100644 --- a/example/examples/CustomCallout.js +++ b/example/examples/CustomCallout.js @@ -1,4 +1,4 @@ -const React = require('react'); +import React, { PropTypes } from 'react'; const ReactNative = require('react-native'); let { StyleSheet, @@ -6,7 +6,12 @@ let { Text, } = ReactNative; -const CustomCallout = React.createClass({ +const propTypes = { + children: PropTypes.node.isRequired, + style: PropTypes.object, +}; + +class CustomCallout extends React.Component { render() { return ( @@ -19,10 +24,12 @@ const CustomCallout = React.createClass({ ); - }, -}); + } +} -let styles = StyleSheet.create({ +CustomCallout.propTypes = propTypes; + +const styles = StyleSheet.create({ container: { flexDirection: 'column', alignSelf: 'flex-start', @@ -38,11 +45,6 @@ let styles = StyleSheet.create({ borderColor: '#007a87', borderWidth: 0.5, }, - dollar: { - - // color: '#FFFFFF', - // fontSize: 10, - }, amount: { flex: 1, }, diff --git a/example/examples/DefaultMarkers.js b/example/examples/DefaultMarkers.js index 48eb1c05d..c676bfb8d 100644 --- a/example/examples/DefaultMarkers.js +++ b/example/examples/DefaultMarkers.js @@ -11,7 +11,7 @@ let { const MapView = require('react-native-maps'); -let { width, height } = Dimensions.get('window'); +const { width, height } = Dimensions.get('window'); const ASPECT_RATIO = width / height; const LATITUDE = 37.78825; @@ -21,12 +21,14 @@ const LONGITUDE_DELTA = LATITUDE_DELTA * ASPECT_RATIO; let id = 0; function randomColor() { - return '#' + Math.floor(Math.random() * 16777215).toString(16); + return `#${Math.floor(Math.random() * 16777215).toString(16)}`; } -const DefaultMarkers = React.createClass({ - getInitialState() { - return { +class DefaultMarkers extends React.Component { + constructor(props) { + super(props); + + this.state = { region: { latitude: LATITUDE, longitude: LONGITUDE, @@ -35,7 +37,7 @@ const DefaultMarkers = React.createClass({ }, markers: [], }; - }, + } onMapPress(e) { this.setState({ @@ -48,7 +50,7 @@ const DefaultMarkers = React.createClass({ }, ], }); - }, + } render() { return ( @@ -56,7 +58,7 @@ const DefaultMarkers = React.createClass({ this.onMapPress(e)} > {this.state.markers.map(marker => ( ); - }, -}); + } +} -let styles = StyleSheet.create({ +const styles = StyleSheet.create({ container: { ...StyleSheet.absoluteFillObject, justifyContent: 'flex-end', diff --git a/example/examples/DisplayLatLng.js b/example/examples/DisplayLatLng.js index abaebb797..439e9db21 100644 --- a/example/examples/DisplayLatLng.js +++ b/example/examples/DisplayLatLng.js @@ -11,7 +11,7 @@ let { const MapView = require('react-native-maps'); -let { width, height } = Dimensions.get('window'); +const { width, height } = Dimensions.get('window'); const ASPECT_RATIO = width / height; const LATITUDE = 37.78825; @@ -19,9 +19,11 @@ const LONGITUDE = -122.4324; const LATITUDE_DELTA = 0.0922; const LONGITUDE_DELTA = LATITUDE_DELTA * ASPECT_RATIO; -const DisplayLatLng = React.createClass({ - getInitialState() { - return { +class DisplayLatLng extends React.Component { + constructor(props) { + super(props); + + this.state = { region: { latitude: LATITUDE, longitude: LONGITUDE, @@ -29,28 +31,28 @@ const DisplayLatLng = React.createClass({ longitudeDelta: LONGITUDE_DELTA, }, }; - }, + } onRegionChange(region) { this.setState({ region }); - }, + } jumpRandom() { this.setState({ region: this.randomRegion() }); - }, + } animateRandom() { this.refs.map.animateToRegion(this.randomRegion()); - }, + } randomRegion() { const { region } = this.state; return { ...this.state.region, - latitude: region.latitude + (Math.random() - 0.5) * region.latitudeDelta / 2, - longitude: region.longitude + (Math.random() - 0.5) * region.longitudeDelta / 2, + latitude: region.latitude + ((Math.random() - 0.5) * (region.latitudeDelta / 2)), + longitude: region.longitude + ((Math.random() - 0.5) * (region.longitudeDelta / 2)), }; - }, + } render() { return ( @@ -60,27 +62,34 @@ const DisplayLatLng = React.createClass({ mapType="terrain" style={styles.map} region={this.state.region} - onRegionChange={this.onRegionChange} + onRegionChange={region => this.onRegionChange(region)} /> - {`${this.state.region.latitude.toPrecision(7)}, ${this.state.region.longitude.toPrecision(7)}`} + {this.state.region.latitude.toPrecision(7)}, + {this.state.region.longitude.toPrecision(7)} - + this.jumpRandom()} + style={[styles.bubble, styles.button]} + > Jump - + this.animateRandom()} + style={[styles.bubble, styles.button]} + > Animate ); - }, -}); + } +} -let styles = StyleSheet.create({ +const styles = StyleSheet.create({ container: { ...StyleSheet.absoluteFillObject, justifyContent: 'flex-end', diff --git a/example/examples/DraggableMarkers.js b/example/examples/DraggableMarkers.js index 612e0fe0b..162a3732e 100644 --- a/example/examples/DraggableMarkers.js +++ b/example/examples/DraggableMarkers.js @@ -13,7 +13,7 @@ let { const MapView = require('react-native-maps'); const PriceMarker = require('./PriceMarker'); -let { width, height } = Dimensions.get('window'); +const { width, height } = Dimensions.get('window'); const ASPECT_RATIO = width / height; const LATITUDE = 37.78825; @@ -22,9 +22,11 @@ const LATITUDE_DELTA = 0.0922; const LONGITUDE_DELTA = LATITUDE_DELTA * ASPECT_RATIO; const SPACE = 0.01; -const MarkerTypes = React.createClass({ - getInitialState() { - return { +class MarkerTypes extends React.Component { + constructor(props) { + super(props); + + this.state = { a: { latitude: LATITUDE + SPACE, longitude: LONGITUDE + SPACE, @@ -34,7 +36,8 @@ const MarkerTypes = React.createClass({ longitude: LONGITUDE - SPACE, }, }; - }, + } + render() { return ( @@ -71,10 +74,10 @@ const MarkerTypes = React.createClass({ ); - }, -}); + } +} -let styles = StyleSheet.create({ +const styles = StyleSheet.create({ container: { ...StyleSheet.absoluteFillObject, justifyContent: 'flex-end', diff --git a/example/examples/EventListener.js b/example/examples/EventListener.js index 5b834aaf2..21019d09a 100644 --- a/example/examples/EventListener.js +++ b/example/examples/EventListener.js @@ -1,8 +1,7 @@ -const React = require('react'); +import React, { PropTypes } from 'react'; const ReactNative = require('react-native'); let { StyleSheet, - PropTypes, View, Text, Dimensions, @@ -13,7 +12,7 @@ let { const MapView = require('react-native-maps'); const PriceMarker = require('./PriceMarker'); -let { width, height } = Dimensions.get('window'); +const { width, height } = Dimensions.get('window'); const ASPECT_RATIO = width / height; const LATITUDE = 37.78825; @@ -22,10 +21,11 @@ const LATITUDE_DELTA = 0.0922; const LONGITUDE_DELTA = LATITUDE_DELTA * ASPECT_RATIO; let id = 0; -const Event = React.createClass({ +class Event extends React.Component { shouldComponentUpdate(nextProps) { return this.props.event.id !== nextProps.event.id; - }, + } + render() { const { event } = this.props; return ( @@ -34,12 +34,20 @@ const Event = React.createClass({ {JSON.stringify(event.data, null, 2)} ); - }, -}); + } +} -const DisplayLatLng = React.createClass({ - getInitialState() { - return { +Event.propTypes = { + event: PropTypes.object, +}; + + +// eslint-disable-next-line react/no-multi-comp +class DisplayLatLng extends React.Component { + constructor(props) { + super(props); + + this.state = { region: { latitude: LATITUDE, longitude: LONGITUDE, @@ -48,7 +56,7 @@ const DisplayLatLng = React.createClass({ }, events: [], }; - }, + } makeEvent(e, name) { return { @@ -56,7 +64,7 @@ const DisplayLatLng = React.createClass({ name, data: e.nativeEvent ? e.nativeEvent : e, }; - }, + } recordEvent(name) { return e => { @@ -68,7 +76,7 @@ const DisplayLatLng = React.createClass({ ], }); }; - }, + } render() { return ( @@ -112,10 +120,10 @@ const DisplayLatLng = React.createClass({ ); - }, -}); + } +} -let styles = StyleSheet.create({ +const styles = StyleSheet.create({ container: { ...StyleSheet.absoluteFillObject, justifyContent: 'flex-end', diff --git a/example/examples/FitToSuppliedMarkers.js b/example/examples/FitToSuppliedMarkers.js index 1e02b1d61..3512af056 100644 --- a/example/examples/FitToSuppliedMarkers.js +++ b/example/examples/FitToSuppliedMarkers.js @@ -11,9 +11,8 @@ let { } = ReactNative; const MapView = require('react-native-maps'); -const PriceMarker = require('./PriceMarker'); -let { width, height } = Dimensions.get('window'); +const { width, height } = Dimensions.get('window'); const ASPECT_RATIO = width / height; const LATITUDE = 37.78825; @@ -26,9 +25,11 @@ const markerIDs = ['Marker1', 'Marker2', 'Marker3', 'Marker4', 'Marker5']; const timeout = 4000; let animationTimeout; -const FocusOnMarkers = React.createClass({ - getInitialState() { - return { +class FocusOnMarkers extends React.Component { + constructor(props) { + super(props); + + this.state = { a: { latitude: LATITUDE + SPACE, longitude: LONGITUDE + SPACE, @@ -50,11 +51,25 @@ const FocusOnMarkers = React.createClass({ longitude: LONGITUDE - (SPACE * 4), }, }; - }, + } + + componentDidMount() { + animationTimeout = setTimeout(() => { + this.focus1(); + }, timeout); + } + + componentWillUnmount() { + if (animationTimeout) { + clearTimeout(animationTimeout); + } + } + focusMap(markers, animated) { - console.log('Markers received to populate map: ' + markers); + console.log(`Markers received to populate map: ${markers}`); this.refs.map.fitToSuppliedMarkers(markers, animated); - }, + } + focus1() { animationTimeout = setTimeout(() => { this.focusMap([ @@ -64,7 +79,8 @@ const FocusOnMarkers = React.createClass({ this.focus2(); }, timeout); - }, + } + focus2() { animationTimeout = setTimeout(() => { this.focusMap([ @@ -74,7 +90,8 @@ const FocusOnMarkers = React.createClass({ this.focus3(); }, timeout); - }, + } + focus3() { animationTimeout = setTimeout(() => { this.focusMap([ @@ -84,7 +101,8 @@ const FocusOnMarkers = React.createClass({ this.focus4(); }, timeout); - }, + } + focus4() { animationTimeout = setTimeout(() => { this.focusMap([ @@ -94,17 +112,8 @@ const FocusOnMarkers = React.createClass({ this.focus1(); }, timeout); - }, - componentDidMount() { - animationTimeout = setTimeout(() => { - this.focus1(); - }, timeout); - }, - componentWillUnmount() { - if (animationTimeout) { - clearTimeout(animationTimeout); - } - }, + } + render() { return ( @@ -119,32 +128,32 @@ const FocusOnMarkers = React.createClass({ }} > ); - }, -}); + } +} -let styles = StyleSheet.create({ +const styles = StyleSheet.create({ container: { ...StyleSheet.absoluteFillObject, justifyContent: 'flex-end', diff --git a/example/examples/LoadingMap.js b/example/examples/LoadingMap.js index b48ea462a..f138fee70 100644 --- a/example/examples/LoadingMap.js +++ b/example/examples/LoadingMap.js @@ -9,7 +9,7 @@ let { const MapView = require('react-native-maps'); -let { width, height } = Dimensions.get('window'); +const { width, height } = Dimensions.get('window'); const ASPECT_RATIO = width / height; const LATITUDE = 37.78825; @@ -18,9 +18,11 @@ const LATITUDE_DELTA = 0.0922; const LONGITUDE_DELTA = LATITUDE_DELTA * ASPECT_RATIO; const SPACE = 0.01; -const LoadingMap = React.createClass({ - getInitialState() { - return { +class LoadingMap extends React.Component { + constructor(props) { + super(props); + + this.state = { region: { latitude: LATITUDE, longitude: LONGITUDE, @@ -28,7 +30,7 @@ const LoadingMap = React.createClass({ longitudeDelta: LONGITUDE_DELTA, }, }; - }, + } render() { return ( @@ -72,10 +74,10 @@ const LoadingMap = React.createClass({ ); - }, -}); + } +} -let styles = StyleSheet.create({ +const styles = StyleSheet.create({ container: { ...StyleSheet.absoluteFillObject, justifyContent: 'flex-end', diff --git a/example/examples/MarkerTypes.js b/example/examples/MarkerTypes.js index 876476fe8..6d95630c7 100644 --- a/example/examples/MarkerTypes.js +++ b/example/examples/MarkerTypes.js @@ -11,9 +11,8 @@ let { } = ReactNative; const MapView = require('react-native-maps'); -const PriceMarker = require('./PriceMarker'); -let { width, height } = Dimensions.get('window'); +const { width, height } = Dimensions.get('window'); const ASPECT_RATIO = width / height; const LATITUDE = 37.78825; @@ -22,7 +21,7 @@ const LATITUDE_DELTA = 0.0922; const LONGITUDE_DELTA = LATITUDE_DELTA * ASPECT_RATIO; const SPACE = 0.01; -const MarkerTypes = React.createClass({ +class MarkerTypes extends React.Component { render() { return ( @@ -59,10 +58,10 @@ const MarkerTypes = React.createClass({ ); - }, -}); + } +} -let styles = StyleSheet.create({ +const styles = StyleSheet.create({ container: { ...StyleSheet.absoluteFillObject, justifyContent: 'flex-end', diff --git a/example/examples/Overlays.js b/example/examples/Overlays.js index 7f54932da..1d2e4bed3 100644 --- a/example/examples/Overlays.js +++ b/example/examples/Overlays.js @@ -12,7 +12,7 @@ let { const MapView = require('react-native-maps'); -let { width, height } = Dimensions.get('window'); +const { width, height } = Dimensions.get('window'); const ASPECT_RATIO = width / height; const LATITUDE = 37.78825; @@ -21,9 +21,11 @@ const LATITUDE_DELTA = 0.0922; const LONGITUDE_DELTA = LATITUDE_DELTA * ASPECT_RATIO; const SPACE = 0.01; -const Overlays = React.createClass({ - getInitialState() { - return { +class Overlays extends React.Component { + constructor(props) { + super(props); + + this.state = { region: { latitude: LATITUDE, longitude: LONGITUDE, @@ -57,20 +59,20 @@ const Overlays = React.createClass({ longitude: LONGITUDE - SPACE, }, { - latitude: LATITUDE - 2 * SPACE, - longitude: LONGITUDE + 2 * SPACE, + latitude: LATITUDE - (2 * SPACE), + longitude: LONGITUDE + (2 * SPACE), }, { latitude: LATITUDE - SPACE, longitude: LONGITUDE - SPACE, }, { - latitude: LATITUDE - 2 * SPACE, + latitude: LATITUDE - (2 * SPACE), longitude: LONGITUDE - SPACE, }, ], }; - }, + } render() { const { region, circle, polygon, polyline } = this.state; @@ -106,10 +108,10 @@ const Overlays = React.createClass({ ); - }, -}); + } +} -let styles = StyleSheet.create({ +const styles = StyleSheet.create({ container: { ...StyleSheet.absoluteFillObject, justifyContent: 'flex-end', diff --git a/example/examples/PanController.js b/example/examples/PanController.js index 7541dcac6..241043051 100644 --- a/example/examples/PanController.js +++ b/example/examples/PanController.js @@ -13,6 +13,7 @@ const ModePropType = PropTypes.oneOf(['decay', 'snap', 'spring-origin']); const OvershootPropType = PropTypes.oneOf(['spring', 'clamp']); const AnimatedPropType = PropTypes.any; +// eslint-disable-next-line react/prefer-es6-class const PanController = React.createClass({ propTypes: { diff --git a/example/examples/PolygonCreator.js b/example/examples/PolygonCreator.js index 7df2559e6..1e5a34c1a 100644 --- a/example/examples/PolygonCreator.js +++ b/example/examples/PolygonCreator.js @@ -10,9 +10,8 @@ let { } = ReactNative; const MapView = require('react-native-maps'); -const PriceMarker = require('./PriceMarker'); -let { width, height } = Dimensions.get('window'); +const { width, height } = Dimensions.get('window'); const ASPECT_RATIO = width / height; const LATITUDE = 37.78825; @@ -21,9 +20,11 @@ const LATITUDE_DELTA = 0.0922; const LONGITUDE_DELTA = LATITUDE_DELTA * ASPECT_RATIO; let id = 0; -const DisplayLatLng = React.createClass({ - getInitialState() { - return { +class DisplayLatLng extends React.Component { + constructor(props) { + super(props); + + this.state = { region: { latitude: LATITUDE, longitude: LONGITUDE, @@ -33,15 +34,15 @@ const DisplayLatLng = React.createClass({ polygons: [], editing: null, }; - }, + } finish() { - let { polygons, editing } = this.state; + const { polygons, editing } = this.state; this.setState({ polygons: [...polygons, editing], editing: null, }); - }, + } onPress(e) { const { editing } = this.state; @@ -63,7 +64,7 @@ const DisplayLatLng = React.createClass({ }, }); } - }, + } render() { const mapOptions = { @@ -80,7 +81,7 @@ const DisplayLatLng = React.createClass({ this.onPress(e)} {...mapOptions} > {this.state.polygons.map(polygon => ( @@ -103,17 +104,20 @@ const DisplayLatLng = React.createClass({ {this.state.editing && ( - + this.finish()} + style={[styles.bubble, styles.button]} + > Finish )} ); - }, -}); + } +} -let styles = StyleSheet.create({ +const styles = StyleSheet.create({ container: { ...StyleSheet.absoluteFillObject, justifyContent: 'flex-end', diff --git a/example/examples/PolylineCreator.js b/example/examples/PolylineCreator.js index e6c301522..981bc5e14 100644 --- a/example/examples/PolylineCreator.js +++ b/example/examples/PolylineCreator.js @@ -10,9 +10,8 @@ let { } = ReactNative; const MapView = require('react-native-maps'); -const PriceMarker = require('./PriceMarker'); -let { width, height } = Dimensions.get('window'); +const { width, height } = Dimensions.get('window'); const ASPECT_RATIO = width / height; const LATITUDE = 37.78825; @@ -21,27 +20,29 @@ const LATITUDE_DELTA = 0.0922; const LONGITUDE_DELTA = LATITUDE_DELTA * ASPECT_RATIO; let id = 0; -const PolylineCreator = React.createClass({ - getInitialState() { - return { +class PolylineCreator extends React.Component { + constructor(props) { + super(props); + + this.state = { region: { latitude: LATITUDE, longitude: LONGITUDE, latitudeDelta: LATITUDE_DELTA, longitudeDelta: LONGITUDE_DELTA, }, - polygons: [], + polylines: [], editing: null, }; - }, + } finish() { - let { polygons, editing } = this.state; + const { polylines, editing } = this.state; this.setState({ - polygons: [...polygons, editing], + polylines: [...polylines, editing], editing: null, }); - }, + } onPanDrag(e) { const { editing } = this.state; @@ -63,7 +64,7 @@ const PolylineCreator = React.createClass({ }, }); } - }, + } render() { return ( @@ -72,40 +73,43 @@ const PolylineCreator = React.createClass({ style={styles.map} initialRegion={this.state.region} scrollEnabled={false} - onPanDrag={this.onPanDrag} + onPanDrag={e => this.onPanDrag(e)} > - {this.state.polygons.map(polygon => ( + {this.state.polylines.map(polyline => ( ))} - {this.state.editing && ( + {this.state.editing && - )} + } {this.state.editing && ( - + this.finish()} + style={[styles.bubble, styles.button]} + > Finish )} ); - }, -}); + } +} -let styles = StyleSheet.create({ +const styles = StyleSheet.create({ container: { ...StyleSheet.absoluteFillObject, justifyContent: 'flex-end', diff --git a/example/examples/PriceMarker.js b/example/examples/PriceMarker.js index 8dd70b90b..dbd4b3826 100644 --- a/example/examples/PriceMarker.js +++ b/example/examples/PriceMarker.js @@ -1,4 +1,4 @@ -const React = require('react'); +import React, { PropTypes } from 'react'; const ReactNative = require('react-native'); let { StyleSheet, @@ -6,27 +6,35 @@ let { Text, } = ReactNative; -const PriceMarker = React.createClass({ - getDefaultProps() { - return { - fontSize: 13, - }; - }, +const propTypes = { + amount: PropTypes.number.isRequired, + fontSize: PropTypes.number, +}; + +const defaultProps = { + fontSize: 13, +}; + +class PriceMarker extends React.Component { render() { + const { fontSize, amount } = this.props; return ( $ - {this.props.amount} + {amount} ); - }, -}); + } +} + +PriceMarker.propTypes = propTypes; +PriceMarker.defaultProps = defaultProps; -let styles = StyleSheet.create({ +const styles = StyleSheet.create({ container: { flexDirection: 'column', alignSelf: 'flex-start', diff --git a/example/examples/TakeSnapshot.js b/example/examples/TakeSnapshot.js index 28974f3e4..9e9f2c899 100644 --- a/example/examples/TakeSnapshot.js +++ b/example/examples/TakeSnapshot.js @@ -11,9 +11,8 @@ let { } = ReactNative; const MapView = require('react-native-maps'); -const PriceMarker = require('./PriceMarker'); -let { width, height } = Dimensions.get('window'); +const { width, height } = Dimensions.get('window'); const ASPECT_RATIO = width / height; const LATITUDE = 37.78825; @@ -22,10 +21,13 @@ const LATITUDE_DELTA = 0.0922; const LONGITUDE_DELTA = LATITUDE_DELTA * ASPECT_RATIO; const SPACE = 0.01; -const MarkerTypes = React.createClass({ - getInitialState() { - return { mapSnapshot: null }; - }, +class MarkerTypes extends React.Component { + constructor(props) { + super(props); + this.state = { + mapSnapshot: null, + }; + } takeSnapshot() { this.refs.map.takeSnapshot(300, 300, { @@ -37,7 +39,7 @@ const MarkerTypes = React.createClass({ if (err) console.log(err); this.setState({ mapSnapshot: data }); }); - }, + } render() { return ( @@ -73,27 +75,30 @@ const MarkerTypes = React.createClass({ - + this.takeSnapshot()} + style={[styles.bubble, styles.button]} + > Take snapshot - {this.state.mapSnapshot - ? this.setState({ mapSnapshot: null })} > - - - : null} + + + } ); - }, -}); + } +} -let styles = StyleSheet.create({ +const styles = StyleSheet.create({ container: { ...StyleSheet.absoluteFillObject, justifyContent: 'flex-end', diff --git a/example/examples/ViewsAsMarkers.js b/example/examples/ViewsAsMarkers.js index 16e24fea5..a0e65479e 100644 --- a/example/examples/ViewsAsMarkers.js +++ b/example/examples/ViewsAsMarkers.js @@ -12,7 +12,7 @@ let { const MapView = require('react-native-maps'); const PriceMarker = require('./PriceMarker'); -let { width, height } = Dimensions.get('window'); +const { width, height } = Dimensions.get('window'); const ASPECT_RATIO = width / height; const LATITUDE = 37.78825; @@ -20,9 +20,11 @@ const LONGITUDE = -122.4324; const LATITUDE_DELTA = 0.0922; const LONGITUDE_DELTA = LATITUDE_DELTA * ASPECT_RATIO; -const DisplayLatLng = React.createClass({ - getInitialState() { - return { +class DisplayLatLng extends React.Component { + constructor(props) { + super(props); + + this.state = { region: { latitude: LATITUDE, longitude: LONGITUDE, @@ -35,15 +37,15 @@ const DisplayLatLng = React.createClass({ }, amount: 99, }; - }, + } increment() { this.setState({ amount: this.state.amount + 1 }); - }, + } decrement() { this.setState({ amount: this.state.amount - 1 }); - }, + } render() { return ( @@ -57,19 +59,25 @@ const DisplayLatLng = React.createClass({ - + this.decrement()} + style={[styles.bubble, styles.button]} + > - - + this.increment()} + style={[styles.bubble, styles.button]} + > + ); - }, -}); + } +} -let styles = StyleSheet.create({ +const styles = StyleSheet.create({ container: { ...StyleSheet.absoluteFillObject, justifyContent: 'flex-end', diff --git a/example/examples/finalindexfile.js b/example/examples/finalindexfile.js deleted file mode 100644 index cb880482c..000000000 --- a/example/examples/finalindexfile.js +++ /dev/null @@ -1,292 +0,0 @@ -/** - * Sample React Native App - * https://github.com/facebook/react-native - */ -'use strict'; - -const React = require('react'); -const ReactNative = require('react-native'); -let { - AppRegistry, - StyleSheet, - Text, - View, - Dimensions, - Animated, - TouchableOpacity, -} = ReactNative; -const MapView = require('react-native-maps'); -const PriceMarker = require('./components/PriceMarker'); - -let { width, height } = Dimensions.get('window'); - -const LATITUDE = 37.78825; -const LONGITUDE = -122.4324; - -const LATD = LATITUDE - 38.89399; -const LNGD = LONGITUDE + 77.03659; - -const LATITUDE_DELTA = 0.0922; -const LONGITUDE_DELTA = 0.1218; - -const MapViewTest = React.createClass({ - getInitialState() { - const scale = new Animated.Value(1); - const latitudeDelta = scale.interpolate({ - inputRange: [1, 2], - outputRange: [LATITUDE_DELTA, LATITUDE_DELTA * 0.6], - }); - const longitudeDelta = scale.interpolate({ - inputRange: [1, 2], - outputRange: [LONGITUDE_DELTA, LONGITUDE_DELTA * 0.6], - }); - return { - val: new Animated.Value(1), - scale, - region: new Animated.Region({ - latitude: LATITUDE, - longitude: LONGITUDE, - latitudeDelta, - longitudeDelta, - }), - markers: [], - coord: { - latitude: LATITUDE, - longitude: LONGITUDE, - }, - }; - }, - - onRegionChange(region) { - // console.log("onRegionChange", region); - this.state.region.setValue(region); - // this.setState({ region }); - }, - - onAnimate() { - const { val } = this.state; - Animated.sequence([ - Animated.timing(val, { toValue: 0, duration: 500 }), - Animated.timing(val, { toValue: 1, duration: 500 }), - ]).start(); - }, - - onAddMarker() { - const coordinate = { - latitude: LATITUDE + LATITUDE_DELTA * (Math.random() - 0.5), - longitude: LONGITUDE + LONGITUDE_DELTA * (Math.random() - 0.5), - }; - let markers = [...this.state.markers, coordinate]; - if (markers.length > 5) { - markers = markers.slice(1); - } - this.setState({ markers }); - }, - - onAnimateZoom() { - let { scale, region } = this.state; - const toValue = scale.__getValue() > 1 ? 1 : 2; - Animated.parallel([ - Animated.spring(region.latitude, { - toValue: LATITUDE + LATITUDE_DELTA * (Math.random() - 0.5), - }), - Animated.spring(region.longitude, { - toValue: LONGITUDE + LONGITUDE_DELTA * (Math.random() - 0.5), - }), - Animated.spring(scale, { - toValue, - }), - ]).start(); - }, - - onMarkerMove() { - this.setState({ - coord: { - latitude: LATITUDE + LATITUDE_DELTA * (Math.random() - 0.5), - longitude: LONGITUDE + LONGITUDE_DELTA * (Math.random() - 0.5), - }, - }); - }, - - onAnimateMapRegion() { - this.refs.map.refs.node.animateToRegion({ - latitude: LATITUDE + LATITUDE_DELTA * (Math.random() - 0.5), - longitude: LONGITUDE + LONGITUDE_DELTA * (Math.random() - 0.5), - latitudeDelta: LATITUDE_DELTA, - longitudeDelta: LONGITUDE_DELTA, - }, 100); - }, - - onZoomToFit() { - this.refs.map.refs.node.fitToElements(true); - }, - - render() { - return ( - - console.log('Map::onRegionChangeComplete', e.nativeEvent)} - onPress={(e) => console.log('Map::onPress', e.nativeEvent)} - onPanDrag={(e) => console.log('Map::onPanDrag', e.nativeEvent)} - onLongPress={(e) => console.log('Map::onLongPress', e.nativeEvent)} - onMarkerPress={(e) => console.log('Map::onMarkerPress', e.nativeEvent)} - onMarkerSelect={(e) => console.log('Map::onMarkerSelect', e.nativeEvent)} - onMarkerDeselect={(e) => console.log('Map::onMarkerDeselect', e.nativeEvent)} - onCalloutPress={(e) => console.log('Map::onCalloutPress', e.nativeEvent)} - onMapPress={(e) => console.log('Map::onMapPress', e.nativeEvent)} - > - - - - console.log('Marker::onPress', e.nativeEvent)} - onCalloutPress={(e) => console.log('Marker::onCalloutPress', e.nativeEvent)} - > - - console.log('Callout::onPress', e.nativeEvent)} - > - - Well hello there... - - - - {this.state.markers.map((coord, i) => ( - console.log('Marker::onPress', e.nativeEvent)} - onCalloutPress={(e) => console.log('Marker::onCalloutPress', e.nativeEvent)} - > - - console.log('Callout::onPress', e.nativeEvent)} - > - - Well hello there... - - - - ))} - - - - - Add Marker - - - - - - Animate Zoom - - - - - - Move Marker - - - - - - Animate Map Region - - - - - - Fit To Elements - - - - ); - }, -}); - -let styles = StyleSheet.create({ - map: { - height: 350, - margin: 10, - borderWidth: 1, - borderColor: '#000000', - }, - row: { - flexDirection: 'row', - justifyContent: 'space-between', - }, - textInput: { - width: 150, - height: 20, - borderWidth: 0.5, - borderColor: '#aaaaaa', - fontSize: 13, - padding: 4, - }, - changeButton: { - alignSelf: 'center', - marginTop: 5, - padding: 3, - borderWidth: 0.5, - borderColor: '#777777', - }, - red: { - width: 50, - height: 50, - backgroundColor: 'red', - }, - blue: { - width: 50, - height: 50, - backgroundColor: 'blue', - }, - callout: { - // flex: 0, - // flexDirection: 'column', - // position: 'absolute', - // flex: 0, - // backgroundColor: '#fff', - // width: 100, - // height: 100, - }, -}); - -module.exports = MapViewTest; -AppRegistry.registerComponent('rn_mapview', () => MapViewTest); diff --git a/example/index.android.js b/example/index.android.js index d35513e3f..8e828e88f 100644 --- a/example/index.android.js +++ b/example/index.android.js @@ -6,10 +6,10 @@ const { const App = require('./App'); -const AirMapsExplorer = React.createClass({ +class AirMapsExplorer extends React.Component { render() { return ; - }, -}); + } +} AppRegistry.registerComponent('AirMapsExplorer', () => AirMapsExplorer); diff --git a/example/index.ios.js b/example/index.ios.js index d35513e3f..8e828e88f 100644 --- a/example/index.ios.js +++ b/example/index.ios.js @@ -6,10 +6,10 @@ const { const App = require('./App'); -const AirMapsExplorer = React.createClass({ +class AirMapsExplorer extends React.Component { render() { return ; - }, -}); + } +} AppRegistry.registerComponent('AirMapsExplorer', () => AirMapsExplorer); From 456e91c985b2ed07989e2e29aee3b072ac1a13c8 Mon Sep 17 00:00:00 2001 From: Spike Brehm Date: Wed, 31 Aug 2016 11:29:01 -0700 Subject: [PATCH 0031/1148] [ESLint] Use ES6 import style --- components/AnimatedRegion.js | 2 + components/MapMarker.js | 2 +- example/App.js | 40 ++++++------- example/examples/AnimatedMarkers.js | 11 ++-- example/examples/AnimatedPriceMarker.js | 75 ++++++++++++------------ example/examples/AnimatedViews.js | 17 ++---- example/examples/CachedMap.js | 9 ++- example/examples/Callouts.js | 13 ++-- example/examples/CustomCallout.js | 6 +- example/examples/DefaultMarkers.js | 11 ++-- example/examples/DisplayLatLng.js | 10 ++-- example/examples/DraggableMarkers.js | 15 ++--- example/examples/EventListener.js | 10 ++-- example/examples/FitToSuppliedMarkers.js | 13 ++-- example/examples/LoadingMap.js | 9 ++- example/examples/MarkerTypes.js | 12 ++-- example/examples/Overlays.js | 12 ++-- example/examples/PanController.js | 13 ++-- example/examples/PolygonCreator.js | 10 ++-- example/examples/PolylineCreator.js | 10 ++-- example/examples/PriceMarker.js | 5 +- example/examples/TakeSnapshot.js | 8 +-- example/examples/ViewsAsMarkers.js | 12 ++-- example/index.android.js | 10 +--- example/index.ios.js | 10 +--- index.js | 2 +- 26 files changed, 144 insertions(+), 203 deletions(-) diff --git a/components/AnimatedRegion.js b/components/AnimatedRegion.js index dba4e01b2..26ed81da4 100644 --- a/components/AnimatedRegion.js +++ b/components/AnimatedRegion.js @@ -1,3 +1,5 @@ +/* eslint-disable */ + class AnimatedRegion extends AnimatedWithChildren { // latitude: AnimatedValue; // longitude: AnimatedValue; diff --git a/components/MapMarker.js b/components/MapMarker.js index 29a3a0ff4..94ddce217 100644 --- a/components/MapMarker.js +++ b/components/MapMarker.js @@ -9,7 +9,7 @@ import { findNodeHandle, } from 'react-native'; -const resolveAssetSource = require('react-native/Libraries/Image/resolveAssetSource'); +import resolveAssetSource from 'react-native/Libraries/Image/resolveAssetSource'; const viewConfig = { uiViewClassName: 'AIRMapMarker', diff --git a/example/App.js b/example/App.js index aa4f6deb5..05d740ae2 100644 --- a/example/App.js +++ b/example/App.js @@ -1,28 +1,28 @@ -const React = require('react'); -const ReactNative = require('react-native'); -let { +import React from 'react'; +import { View, StyleSheet, TouchableOpacity, ScrollView, Text, -} = ReactNative; -const DisplayLatLng = require('./examples/DisplayLatLng'); -const ViewsAsMarkers = require('./examples/ViewsAsMarkers'); -const EventListener = require('./examples/EventListener'); -const MarkerTypes = require('./examples/MarkerTypes'); -const DraggableMarkers = require('./examples/DraggableMarkers'); -const PolygonCreator = require('./examples/PolygonCreator'); -const PolylineCreator = require('./examples/PolylineCreator'); -const AnimatedViews = require('./examples/AnimatedViews'); -const AnimatedMarkers = require('./examples/AnimatedMarkers'); -const Callouts = require('./examples/Callouts'); -const Overlays = require('./examples/Overlays'); -const DefaultMarkers = require('./examples/DefaultMarkers'); -const CachedMap = require('./examples/CachedMap'); -const LoadingMap = require('./examples/LoadingMap'); -const TakeSnapshot = require('./examples/TakeSnapshot'); -const FitToSuppliedMarkers = require('./examples/FitToSuppliedMarkers'); +} from 'react-native'; + +import DisplayLatLng from './examples/DisplayLatLng'; +import ViewsAsMarkers from './examples/ViewsAsMarkers'; +import EventListener from './examples/EventListener'; +import MarkerTypes from './examples/MarkerTypes'; +import DraggableMarkers from './examples/DraggableMarkers'; +import PolygonCreator from './examples/PolygonCreator'; +import PolylineCreator from './examples/PolylineCreator'; +import AnimatedViews from './examples/AnimatedViews'; +import AnimatedMarkers from './examples/AnimatedMarkers'; +import Callouts from './examples/Callouts'; +import Overlays from './examples/Overlays'; +import DefaultMarkers from './examples/DefaultMarkers'; +import CachedMap from './examples/CachedMap'; +import LoadingMap from './examples/LoadingMap'; +import TakeSnapshot from './examples/TakeSnapshot'; +import FitToSuppliedMarkers from './examples/FitToSuppliedMarkers'; class App extends React.Component { constructor(props) { diff --git a/example/examples/AnimatedMarkers.js b/example/examples/AnimatedMarkers.js index f422c136d..49f89f9a1 100644 --- a/example/examples/AnimatedMarkers.js +++ b/example/examples/AnimatedMarkers.js @@ -1,17 +1,14 @@ -const React = require('react'); -const ReactNative = require('react-native'); -let { +import React from 'react'; +import { StyleSheet, - PropTypes, View, Text, Dimensions, TouchableOpacity, Animated, - Platform, -} = ReactNative; +} from 'react-native'; -const MapView = require('react-native-maps'); +import MapView from 'react-native-maps'; const screen = Dimensions.get('window'); diff --git a/example/examples/AnimatedPriceMarker.js b/example/examples/AnimatedPriceMarker.js index 49c9d718f..0a31d7176 100644 --- a/example/examples/AnimatedPriceMarker.js +++ b/example/examples/AnimatedPriceMarker.js @@ -1,49 +1,48 @@ -const React = require('react'); -const ReactNative = require('react-native'); -const { - PropTypes, -} = React; - -let { +import React, { PropTypes } from 'react'; +import { StyleSheet, - View, Text, Animated, -} = ReactNative; +} from 'react-native'; -const PriceMarker = ({ amount, selected, style }) => { - const background = selected.interpolate({ - inputRange: [0, 1], - outputRange: ['#FF5A5F', '#4da2ab'], - }); +class AnimatedPriceMarker extends React.Component { + render() { + const { amount, selected, style } = this.props; - const border = selected.interpolate({ - inputRange: [0, 1], - outputRange: ['#D23F44', '#007a87'], - }); + const background = selected.interpolate({ + inputRange: [0, 1], + outputRange: ['#FF5A5F', '#4da2ab'], + }); - return ( - - - $ - {amount} - - - - - ); -}; + const border = selected.interpolate({ + inputRange: [0, 1], + outputRange: ['#D23F44', '#007a87'], + }); + return ( + + + $ + {amount} + + + + + ); + } +} -PriceMarker.propTypes = { +AnimatedPriceMarker.propTypes = { amount: PropTypes.number.isRequired, + selected: PropTypes.object.isRequired, + style: PropTypes.any, }; const styles = StyleSheet.create({ @@ -99,4 +98,4 @@ const styles = StyleSheet.create({ }, }); -module.exports = PriceMarker; +module.exports = AnimatedPriceMarker; diff --git a/example/examples/AnimatedViews.js b/example/examples/AnimatedViews.js index 801936c75..06a9b3d2e 100644 --- a/example/examples/AnimatedViews.js +++ b/example/examples/AnimatedViews.js @@ -1,19 +1,14 @@ -const React = require('react'); -const ReactNative = require('react-native'); -let { +import React from 'react'; +import { StyleSheet, - PropTypes, View, - Text, Dimensions, - TouchableOpacity, Animated, - Platform, -} = ReactNative; +} from 'react-native'; -const MapView = require('react-native-maps'); -const PanController = require('./PanController'); -const PriceMarker = require('./AnimatedPriceMarker'); +import MapView from 'react-native-maps'; +import PanController from './PanController'; +import PriceMarker from './AnimatedPriceMarker'; const screen = Dimensions.get('window'); diff --git a/example/examples/CachedMap.js b/example/examples/CachedMap.js index 2b300452e..93650616a 100644 --- a/example/examples/CachedMap.js +++ b/example/examples/CachedMap.js @@ -1,15 +1,14 @@ -const React = require('react'); -const ReactNative = require('react-native'); -let { +import React from 'react'; +import { Text, View, Dimensions, StyleSheet, ListView, TouchableOpacity, -} = ReactNative; +} from 'react-native'; -const MapView = require('react-native-maps'); +import MapView from 'react-native-maps'; const HORIZONTAL_PADDING = 12; const VERTICAL_PADDING = 6; diff --git a/example/examples/Callouts.js b/example/examples/Callouts.js index bd68dd3d7..09325d10e 100644 --- a/example/examples/Callouts.js +++ b/example/examples/Callouts.js @@ -1,17 +1,14 @@ -const React = require('react'); -const ReactNative = require('react-native'); -let { +import React from 'react'; +import { StyleSheet, - PropTypes, View, Text, Dimensions, TouchableOpacity, - Image, -} = ReactNative; +} from 'react-native'; -const MapView = require('react-native-maps'); -const CustomCallout = require('./CustomCallout'); +import MapView from 'react-native-maps'; +import CustomCallout from './CustomCallout'; const { width, height } = Dimensions.get('window'); diff --git a/example/examples/CustomCallout.js b/example/examples/CustomCallout.js index 783fd7195..719f04a96 100644 --- a/example/examples/CustomCallout.js +++ b/example/examples/CustomCallout.js @@ -1,10 +1,8 @@ import React, { PropTypes } from 'react'; -const ReactNative = require('react-native'); -let { +import { StyleSheet, View, - Text, -} = ReactNative; +} from 'react-native'; const propTypes = { children: PropTypes.node.isRequired, diff --git a/example/examples/DefaultMarkers.js b/example/examples/DefaultMarkers.js index c676bfb8d..0f6e686a0 100644 --- a/example/examples/DefaultMarkers.js +++ b/example/examples/DefaultMarkers.js @@ -1,15 +1,12 @@ -const React = require('react'); -const ReactNative = require('react-native'); -let { +import React from 'react'; +import { StyleSheet, - PropTypes, View, Text, Dimensions, - TouchableOpacity, -} = ReactNative; +} from 'react-native'; -const MapView = require('react-native-maps'); +import MapView from 'react-native-maps'; const { width, height } = Dimensions.get('window'); diff --git a/example/examples/DisplayLatLng.js b/example/examples/DisplayLatLng.js index 439e9db21..c89e4191a 100644 --- a/example/examples/DisplayLatLng.js +++ b/example/examples/DisplayLatLng.js @@ -1,15 +1,13 @@ -const React = require('react'); -const ReactNative = require('react-native'); -let { +import React from 'react'; +import { StyleSheet, - PropTypes, View, Text, Dimensions, TouchableOpacity, -} = ReactNative; +} from 'react-native'; -const MapView = require('react-native-maps'); +import MapView from 'react-native-maps'; const { width, height } = Dimensions.get('window'); diff --git a/example/examples/DraggableMarkers.js b/example/examples/DraggableMarkers.js index 162a3732e..aec6dad21 100644 --- a/example/examples/DraggableMarkers.js +++ b/example/examples/DraggableMarkers.js @@ -1,17 +1,12 @@ -const React = require('react'); -const ReactNative = require('react-native'); -let { +import React from 'react'; +import { StyleSheet, - PropTypes, View, - Text, Dimensions, - TouchableOpacity, - Image, -} = ReactNative; +} from 'react-native'; -const MapView = require('react-native-maps'); -const PriceMarker = require('./PriceMarker'); +import MapView from 'react-native-maps'; +import PriceMarker from './PriceMarker'; const { width, height } = Dimensions.get('window'); diff --git a/example/examples/EventListener.js b/example/examples/EventListener.js index 21019d09a..ff807a16b 100644 --- a/example/examples/EventListener.js +++ b/example/examples/EventListener.js @@ -1,16 +1,14 @@ import React, { PropTypes } from 'react'; -const ReactNative = require('react-native'); -let { +import { StyleSheet, View, Text, Dimensions, - TouchableOpacity, ScrollView, -} = ReactNative; +} from 'react-native'; -const MapView = require('react-native-maps'); -const PriceMarker = require('./PriceMarker'); +import MapView from 'react-native-maps'; +import PriceMarker from './PriceMarker'; const { width, height } = Dimensions.get('window'); diff --git a/example/examples/FitToSuppliedMarkers.js b/example/examples/FitToSuppliedMarkers.js index 3512af056..15303cc73 100644 --- a/example/examples/FitToSuppliedMarkers.js +++ b/example/examples/FitToSuppliedMarkers.js @@ -1,16 +1,11 @@ -const React = require('react'); -const ReactNative = require('react-native'); -let { +import React from 'react'; +import { StyleSheet, - PropTypes, View, - Text, Dimensions, - TouchableOpacity, - Image, -} = ReactNative; +} from 'react-native'; -const MapView = require('react-native-maps'); +import MapView from 'react-native-maps'; const { width, height } = Dimensions.get('window'); diff --git a/example/examples/LoadingMap.js b/example/examples/LoadingMap.js index f138fee70..8295e6398 100644 --- a/example/examples/LoadingMap.js +++ b/example/examples/LoadingMap.js @@ -1,13 +1,12 @@ -const React = require('react'); -const ReactNative = require('react-native'); -let { +import React from 'react'; +import { Text, View, Dimensions, StyleSheet, -} = ReactNative; +} from 'react-native'; -const MapView = require('react-native-maps'); +import MapView from 'react-native-maps'; const { width, height } = Dimensions.get('window'); diff --git a/example/examples/MarkerTypes.js b/example/examples/MarkerTypes.js index 6d95630c7..89e9d2138 100644 --- a/example/examples/MarkerTypes.js +++ b/example/examples/MarkerTypes.js @@ -1,16 +1,12 @@ -const React = require('react'); -const ReactNative = require('react-native'); -let { +import React from 'react'; +import { StyleSheet, - PropTypes, View, Text, Dimensions, - TouchableOpacity, - Image, -} = ReactNative; +} from 'react-native'; -const MapView = require('react-native-maps'); +import MapView from 'react-native-maps'; const { width, height } = Dimensions.get('window'); diff --git a/example/examples/Overlays.js b/example/examples/Overlays.js index 1d2e4bed3..8e777f433 100644 --- a/example/examples/Overlays.js +++ b/example/examples/Overlays.js @@ -1,16 +1,12 @@ -const React = require('react'); -const ReactNative = require('react-native'); -let { +import React from 'react'; +import { StyleSheet, - PropTypes, View, Text, Dimensions, - TouchableOpacity, - Image, -} = ReactNative; +} from 'react-native'; -const MapView = require('react-native-maps'); +import MapView from 'react-native-maps'; const { width, height } = Dimensions.get('window'); diff --git a/example/examples/PanController.js b/example/examples/PanController.js index 241043051..4857ea099 100644 --- a/example/examples/PanController.js +++ b/example/examples/PanController.js @@ -1,19 +1,16 @@ -const React = require('react'); -const ReactNative = require('react-native'); -const { - PropTypes, -} = React; -let { +/* eslint-disable */ + +import React, { PropTypes } from 'react'; +import { View, Animated, PanResponder, -} = ReactNative; +} from 'react-native'; const ModePropType = PropTypes.oneOf(['decay', 'snap', 'spring-origin']); const OvershootPropType = PropTypes.oneOf(['spring', 'clamp']); const AnimatedPropType = PropTypes.any; -// eslint-disable-next-line react/prefer-es6-class const PanController = React.createClass({ propTypes: { diff --git a/example/examples/PolygonCreator.js b/example/examples/PolygonCreator.js index 1e5a34c1a..cc732b12f 100644 --- a/example/examples/PolygonCreator.js +++ b/example/examples/PolygonCreator.js @@ -1,15 +1,13 @@ -const React = require('react'); -const ReactNative = require('react-native'); -let { +import React from 'react'; +import { StyleSheet, - PropTypes, View, Text, Dimensions, TouchableOpacity, -} = ReactNative; +} from 'react-native'; -const MapView = require('react-native-maps'); +import MapView from 'react-native-maps'; const { width, height } = Dimensions.get('window'); diff --git a/example/examples/PolylineCreator.js b/example/examples/PolylineCreator.js index 981bc5e14..6bc7398d2 100644 --- a/example/examples/PolylineCreator.js +++ b/example/examples/PolylineCreator.js @@ -1,15 +1,13 @@ -const React = require('react'); -const ReactNative = require('react-native'); -let { +import React from 'react'; +import { StyleSheet, - PropTypes, View, Text, Dimensions, TouchableOpacity, -} = ReactNative; +} from 'react-native'; -const MapView = require('react-native-maps'); +import MapView from 'react-native-maps'; const { width, height } = Dimensions.get('window'); diff --git a/example/examples/PriceMarker.js b/example/examples/PriceMarker.js index dbd4b3826..ba40ac10b 100644 --- a/example/examples/PriceMarker.js +++ b/example/examples/PriceMarker.js @@ -1,10 +1,9 @@ import React, { PropTypes } from 'react'; -const ReactNative = require('react-native'); -let { +import { StyleSheet, View, Text, -} = ReactNative; +} from 'react-native'; const propTypes = { amount: PropTypes.number.isRequired, diff --git a/example/examples/TakeSnapshot.js b/example/examples/TakeSnapshot.js index 9e9f2c899..4177f0078 100644 --- a/example/examples/TakeSnapshot.js +++ b/example/examples/TakeSnapshot.js @@ -1,14 +1,12 @@ -const React = require('react'); -const ReactNative = require('react-native'); -let { +import React from 'react'; +import { StyleSheet, - PropTypes, View, Text, Dimensions, TouchableOpacity, Image, -} = ReactNative; +} from 'react-native'; const MapView = require('react-native-maps'); diff --git a/example/examples/ViewsAsMarkers.js b/example/examples/ViewsAsMarkers.js index a0e65479e..7d7857d04 100644 --- a/example/examples/ViewsAsMarkers.js +++ b/example/examples/ViewsAsMarkers.js @@ -1,16 +1,14 @@ -const React = require('react'); -const ReactNative = require('react-native'); -let { +import React from 'react'; +import { StyleSheet, - PropTypes, View, Text, Dimensions, TouchableOpacity, -} = ReactNative; +} from 'react-native'; -const MapView = require('react-native-maps'); -const PriceMarker = require('./PriceMarker'); +import MapView from 'react-native-maps'; +import PriceMarker from './PriceMarker'; const { width, height } = Dimensions.get('window'); diff --git a/example/index.android.js b/example/index.android.js index 8e828e88f..3d259cfd3 100644 --- a/example/index.android.js +++ b/example/index.android.js @@ -1,10 +1,6 @@ -const React = require('react'); -const ReactNative = require('react-native'); -const { - AppRegistry, -} = ReactNative; - -const App = require('./App'); +import React from 'react'; +import { AppRegistry } from 'react-native'; +import App from './App'; class AirMapsExplorer extends React.Component { render() { diff --git a/example/index.ios.js b/example/index.ios.js index 8e828e88f..3d259cfd3 100644 --- a/example/index.ios.js +++ b/example/index.ios.js @@ -1,10 +1,6 @@ -const React = require('react'); -const ReactNative = require('react-native'); -const { - AppRegistry, -} = ReactNative; - -const App = require('./App'); +import React from 'react'; +import { AppRegistry } from 'react-native'; +import App from './App'; class AirMapsExplorer extends React.Component { render() { diff --git a/index.js b/index.js index 50d803692..b2d7d79e1 100644 --- a/index.js +++ b/index.js @@ -1,3 +1,3 @@ -const MapView = require('./components/MapView'); +import MapView from './components/MapView'; module.exports = MapView; From 631c5764a0fadb77a732074e25014a3ad244ed07 Mon Sep 17 00:00:00 2001 From: Spike Brehm Date: Wed, 31 Aug 2016 11:32:52 -0700 Subject: [PATCH 0032/1148] [ESLint] Ignore react/sort-comp rule --- .eslintrc | 1 + 1 file changed, 1 insertion(+) diff --git a/.eslintrc b/.eslintrc index 70d91588b..d4c3aba24 100644 --- a/.eslintrc +++ b/.eslintrc @@ -8,6 +8,7 @@ "prefer-object-spread/prefer-object-spread": 2, "react/jsx-filename-extension": 0, "react/prefer-stateless-function": 0, + "react/sort-comp": 0, "no-use-before-define": 0, "no-underscore-dangle": 0 } From e58e431c81759a5c6c67b4f0de8f94a9a82061af Mon Sep 17 00:00:00 2001 From: Spike Brehm Date: Wed, 31 Aug 2016 11:38:02 -0700 Subject: [PATCH 0033/1148] [ESLint] Ignore "react" in "import/no-unresolved" Because `react` is listed as a peer dep, so it won't necessarily exist on the filesystem. --- .eslintrc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.eslintrc b/.eslintrc index d4c3aba24..5cfda8e5d 100644 --- a/.eslintrc +++ b/.eslintrc @@ -10,6 +10,7 @@ "react/prefer-stateless-function": 0, "react/sort-comp": 0, "no-use-before-define": 0, - "no-underscore-dangle": 0 + "no-underscore-dangle": 0, + "import/no-unresolved": [2, { "ignore": ["react"] }] } } From 3a8d35f8bb730dc5f5c0e9c885683afef5082e8a Mon Sep 17 00:00:00 2001 From: Spike Brehm Date: Wed, 31 Aug 2016 12:14:09 -0700 Subject: [PATCH 0034/1148] [ESLint] Fix all violations except react/no-string-refs --- components/MapMarker.js | 3 + components/MapView.js | 21 +-- example/examples/AnimatedPriceMarker.js | 25 +-- example/examples/AnimatedViews.js | 207 ++++++++++++------------ example/examples/MarkerTypes.js | 6 +- example/examples/TakeSnapshot.js | 8 +- 6 files changed, 145 insertions(+), 125 deletions(-) diff --git a/components/MapMarker.js b/components/MapMarker.js index 94ddce217..4959b3559 100644 --- a/components/MapMarker.js +++ b/components/MapMarker.js @@ -237,6 +237,9 @@ class MapMarker extends React.Component { [this._getHandle(), ...args] ); break; + + default: + break; } } diff --git a/components/MapView.js b/components/MapView.js index 23292615e..7bca35a03 100644 --- a/components/MapView.js +++ b/components/MapView.js @@ -367,16 +367,18 @@ class MapView extends React.Component { this.__layoutCalled = true; this.refs.map.setNativeProps({ region: initialRegion }); } - onLayout && onLayout(e); + if (onLayout) { + onLayout(e); + } } _onChange(event) { this.__lastRegion = event.nativeEvent.region; if (event.nativeEvent.continuous) { - this.props.onRegionChange && - this.props.onRegionChange(event.nativeEvent.region); - } else { - this.props.onRegionChangeComplete && + if (this.props.onRegionChange) { + this.props.onRegionChange(event.nativeEvent.region); + } + } else if (this.props.onRegionChangeComplete) { this.props.onRegionChangeComplete(event.nativeEvent.region); } } @@ -398,10 +400,8 @@ class MapView extends React.Component { } takeSnapshot(width, height, region, callback) { - if (!region) { - region = this.props.region || this.props.initialRegion; - } - this._runCommand('takeSnapshot', [width, height, region, callback]); + const finalRegion = region || this.props.region || this.props.initialRegion; + this._runCommand('takeSnapshot', [width, height, finalRegion, callback]); } _getHandle() { @@ -424,6 +424,9 @@ class MapView extends React.Component { [this._getHandle(), ...args] ); break; + + default: + break; } } diff --git a/example/examples/AnimatedPriceMarker.js b/example/examples/AnimatedPriceMarker.js index 0a31d7176..9e39acbc1 100644 --- a/example/examples/AnimatedPriceMarker.js +++ b/example/examples/AnimatedPriceMarker.js @@ -21,19 +21,24 @@ class AnimatedPriceMarker extends React.Component { return ( - + $ {amount} - - + + ); } diff --git a/example/examples/AnimatedViews.js b/example/examples/AnimatedViews.js index 06a9b3d2e..4d2c421e9 100644 --- a/example/examples/AnimatedViews.js +++ b/example/examples/AnimatedViews.js @@ -26,6 +26,100 @@ const ITEM_PREVIEW_HEIGHT = 150; const SCALE_END = screen.width / ITEM_WIDTH; const BREAKPOINT1 = 246; const BREAKPOINT2 = 350; +const ONE = new Animated.Value(1); + +function getMarkerState(panX, panY, scrollY, i) { + const xLeft = (-SNAP_WIDTH * i) + (SNAP_WIDTH / 2); + const xRight = (-SNAP_WIDTH * i) - (SNAP_WIDTH / 2); + const xPos = -SNAP_WIDTH * i; + + const isIndex = panX.interpolate({ + inputRange: [xRight - 1, xRight, xLeft, xLeft + 1], + outputRange: [0, 1, 1, 0], + extrapolate: 'clamp', + }); + + const isNotIndex = panX.interpolate({ + inputRange: [xRight - 1, xRight, xLeft, xLeft + 1], + outputRange: [1, 0, 0, 1], + extrapolate: 'clamp', + }); + + const center = panX.interpolate({ + inputRange: [xPos - 10, xPos, xPos + 10], + outputRange: [0, 1, 0], + extrapolate: 'clamp', + }); + + const selected = panX.interpolate({ + inputRange: [xRight, xPos, xLeft], + outputRange: [0, 1, 0], + extrapolate: 'clamp', + }); + + const translateY = Animated.multiply(isIndex, panY); + + const translateX = panX; + + const anim = Animated.multiply(isIndex, scrollY.interpolate({ + inputRange: [0, BREAKPOINT1], + outputRange: [0, 1], + extrapolate: 'clamp', + })); + + const scale = Animated.add(ONE, Animated.multiply(isIndex, scrollY.interpolate({ + inputRange: [BREAKPOINT1, BREAKPOINT2], + outputRange: [0, SCALE_END - 1], + extrapolate: 'clamp', + }))); + + // [0 => 1] + let opacity = scrollY.interpolate({ + inputRange: [BREAKPOINT1, BREAKPOINT2], + outputRange: [0, 1], + extrapolate: 'clamp', + }); + + // if i === index: [0 => 0] + // if i !== index: [0 => 1] + opacity = Animated.multiply(isNotIndex, opacity); + + + // if i === index: [1 => 1] + // if i !== index: [1 => 0] + opacity = opacity.interpolate({ + inputRange: [0, 1], + outputRange: [1, 0], + }); + + let markerOpacity = scrollY.interpolate({ + inputRange: [0, BREAKPOINT1], + outputRange: [0, 1], + extrapolate: 'clamp', + }); + + markerOpacity = Animated.multiply(isNotIndex, markerOpacity).interpolate({ + inputRange: [0, 1], + outputRange: [1, 0], + }); + + const markerScale = selected.interpolate({ + inputRange: [0, 1], + outputRange: [1, 1.2], + }); + + return { + translateY, + translateX, + scale, + opacity, + anim, + center, + selected, + markerOpacity, + markerScale, + }; +} class AnimatedViews extends React.Component { constructor(props) { @@ -56,8 +150,6 @@ class AnimatedViews extends React.Component { extrapolate: 'clamp', }); - const ONE = new Animated.Value(1); - const markers = [ { id: 0, @@ -85,98 +177,8 @@ class AnimatedViews extends React.Component { }, ]; - const animations = markers.map((m, i) => { - const xLeft = -SNAP_WIDTH * i + SNAP_WIDTH / 2; - const xRight = -SNAP_WIDTH * i - SNAP_WIDTH / 2; - const xPos = -SNAP_WIDTH * i; - - const isIndex = panX.interpolate({ - inputRange: [xRight - 1, xRight, xLeft, xLeft + 1], - outputRange: [0, 1, 1, 0], - extrapolate: 'clamp', - }); - - const isNotIndex = panX.interpolate({ - inputRange: [xRight - 1, xRight, xLeft, xLeft + 1], - outputRange: [1, 0, 0, 1], - extrapolate: 'clamp', - }); - - const center = panX.interpolate({ - inputRange: [xPos - 10, xPos, xPos + 10], - outputRange: [0, 1, 0], - extrapolate: 'clamp', - }); - - const selected = panX.interpolate({ - inputRange: [xRight, xPos, xLeft], - outputRange: [0, 1, 0], - extrapolate: 'clamp', - }); - - const translateY = Animated.multiply(isIndex, panY); - - const translateX = panX; - - const anim = Animated.multiply(isIndex, scrollY.interpolate({ - inputRange: [0, BREAKPOINT1], - outputRange: [0, 1], - extrapolate: 'clamp', - })); - - const scale = Animated.add(ONE, Animated.multiply(isIndex, scrollY.interpolate({ - inputRange: [BREAKPOINT1, BREAKPOINT2], - outputRange: [0, SCALE_END - 1], - extrapolate: 'clamp', - }))); - - // [0 => 1] - let opacity = scrollY.interpolate({ - inputRange: [BREAKPOINT1, BREAKPOINT2], - outputRange: [0, 1], - extrapolate: 'clamp', - }); - - // if i === index: [0 => 0] - // if i !== index: [0 => 1] - opacity = Animated.multiply(isNotIndex, opacity); - - - // if i === index: [1 => 1] - // if i !== index: [1 => 0] - opacity = opacity.interpolate({ - inputRange: [0, 1], - outputRange: [1, 0], - }); - - let markerOpacity = scrollY.interpolate({ - inputRange: [0, BREAKPOINT1], - outputRange: [0, 1], - extrapolate: 'clamp', - }); - - markerOpacity = Animated.multiply(isNotIndex, markerOpacity).interpolate({ - inputRange: [0, 1], - outputRange: [1, 0], - }); - - const markerScale = selected.interpolate({ - inputRange: [0, 1], - outputRange: [1, 1.2], - }); - - return { - translateY, - translateX, - scale, - opacity, - anim, - center, - selected, - markerOpacity, - markerScale, - }; - }); + const animations = markers.map((m, i) => + getMarkerState(panX, panY, scrollY, i)); this.state = { panX, @@ -224,7 +226,7 @@ class AnimatedViews extends React.Component { // false, the gesture should get passed to the map view appropriately. const { panY } = this.state; const { pageY } = e.nativeEvent; - const topOfMainWindow = ITEM_PREVIEW_HEIGHT + 1 * panY.__getValue(); + const topOfMainWindow = ITEM_PREVIEW_HEIGHT + panY.__getValue(); const topOfTap = screen.height - pageY; return topOfTap < topOfMainWindow; @@ -233,22 +235,22 @@ class AnimatedViews extends React.Component { onMoveShouldSetPanResponder(e) { const { panY } = this.state; const { pageY } = e.nativeEvent; - const topOfMainWindow = ITEM_PREVIEW_HEIGHT + 1 * panY.__getValue(); + const topOfMainWindow = ITEM_PREVIEW_HEIGHT + panY.__getValue(); const topOfTap = screen.height - pageY; return topOfTap < topOfMainWindow; } onPanXChange({ value }) { - let { index, region, panX, markers } = this.state; - const newIndex = Math.floor((-1 * value + SNAP_WIDTH / 2) / SNAP_WIDTH); + const { index } = this.state; + const newIndex = Math.floor(((-1 * value) + (SNAP_WIDTH / 2)) / SNAP_WIDTH); if (index !== newIndex) { this.setState({ index: newIndex }); } } onPanYChange({ value }) { - let { canMoveHorizontal, region, scrollY, scrollX, markers, index } = this.state; + const { canMoveHorizontal, region, scrollY, scrollX, markers, index } = this.state; const shouldBeMovable = Math.abs(value) < 2; if (shouldBeMovable !== canMoveHorizontal) { this.setState({ canMoveHorizontal: shouldBeMovable }); @@ -258,7 +260,10 @@ class AnimatedViews extends React.Component { region.timing({ latitude: scrollY.interpolate({ inputRange: [0, BREAKPOINT1], - outputRange: [coordinate.latitude, coordinate.latitude - LATITUDE_DELTA * 0.5 * 0.375], + outputRange: [ + coordinate.latitude, + coordinate.latitude - (LATITUDE_DELTA * 0.5 * 0.375), + ], extrapolate: 'clamp', }), latitudeDelta: scrollY.interpolate({ @@ -290,7 +295,7 @@ class AnimatedViews extends React.Component { } } - onRegionChange(region) { + onRegionChange(/* region */) { // this.state.region.setValue(region); } diff --git a/example/examples/MarkerTypes.js b/example/examples/MarkerTypes.js index 89e9d2138..ebf00cfdb 100644 --- a/example/examples/MarkerTypes.js +++ b/example/examples/MarkerTypes.js @@ -7,6 +7,8 @@ import { } from 'react-native'; import MapView from 'react-native-maps'; +import flagBlueImg from './assets/flag-blue.png'; +import flagPinkImg from './assets/flag-pink.png'; const { width, height } = Dimensions.get('window'); @@ -38,7 +40,7 @@ class MarkerTypes extends React.Component { }} centerOffset={{ x: -18, y: -60 }} anchor={{ x: 0.69, y: 1 }} - image={require('./assets/flag-blue.png')} + image={flagBlueImg} > X @@ -49,7 +51,7 @@ class MarkerTypes extends React.Component { }} centerOffset={{ x: -42, y: -60 }} anchor={{ x: 0.84, y: 1 }} - image={require('./assets/flag-pink.png')} + image={flagPinkImg} /> diff --git a/example/examples/TakeSnapshot.js b/example/examples/TakeSnapshot.js index 4177f0078..e0126f43d 100644 --- a/example/examples/TakeSnapshot.js +++ b/example/examples/TakeSnapshot.js @@ -8,7 +8,9 @@ import { Image, } from 'react-native'; -const MapView = require('react-native-maps'); +import MapView from 'react-native-maps'; +import flagBlueImg from './assets/flag-blue.png'; +import flagPinkImg from './assets/flag-pink.png'; const { width, height } = Dimensions.get('window'); @@ -59,7 +61,7 @@ class MarkerTypes extends React.Component { }} centerOffset={{ x: -18, y: -60 }} anchor={{ x: 0.69, y: 1 }} - image={require('./assets/flag-blue.png')} + image={flagBlueImg} /> From ce974f1eb9b36426f6466c62e2c54d2e9d702901 Mon Sep 17 00:00:00 2001 From: Spike Brehm Date: Wed, 31 Aug 2016 13:06:13 -0700 Subject: [PATCH 0035/1148] [ESLint] Satisfy react/no-string-refs rule --- components/MapMarker.js | 4 ++-- components/MapView.js | 21 ++++++++++++--------- example/examples/CachedMap.js | 3 ++- example/examples/Callouts.js | 8 +++----- example/examples/DisplayLatLng.js | 4 ++-- example/examples/DraggableMarkers.js | 1 - example/examples/EventListener.js | 1 - example/examples/FitToSuppliedMarkers.js | 4 ++-- example/examples/LoadingMap.js | 3 ++- example/examples/MarkerTypes.js | 1 - example/examples/TakeSnapshot.js | 4 ++-- 11 files changed, 27 insertions(+), 27 deletions(-) diff --git a/components/MapMarker.js b/components/MapMarker.js index 4959b3559..e03458a7f 100644 --- a/components/MapMarker.js +++ b/components/MapMarker.js @@ -218,7 +218,7 @@ class MapMarker extends React.Component { } _getHandle() { - return findNodeHandle(this.refs.marker); + return findNodeHandle(this.marker); } _runCommand(name, args) { @@ -252,7 +252,7 @@ class MapMarker extends React.Component { return ( { this.marker = ref; }} {...this.props} image={image} style={[styles.marker, this.props.style]} diff --git a/components/MapView.js b/components/MapView.js index 7bca35a03..5bbaea374 100644 --- a/components/MapView.js +++ b/components/MapView.js @@ -327,9 +327,9 @@ class MapView extends React.Component { componentDidMount() { const { region, initialRegion } = this.props; if (region && this.state.isReady) { - this.refs.map.setNativeProps({ region }); + this.map.setNativeProps({ region }); } else if (initialRegion && this.state.isReady) { - this.refs.map.setNativeProps({ region: initialRegion }); + this.map.setNativeProps({ region: initialRegion }); } } @@ -343,16 +343,16 @@ class MapView extends React.Component { a.latitudeDelta !== b.latitudeDelta || a.longitudeDelta !== b.longitudeDelta ) { - this.refs.map.setNativeProps({ region: b }); + this.map.setNativeProps({ region: b }); } } _onMapReady() { const { region, initialRegion } = this.props; if (region) { - this.refs.map.setNativeProps({ region }); + this.map.setNativeProps({ region }); } else if (initialRegion) { - this.refs.map.setNativeProps({ region: initialRegion }); + this.map.setNativeProps({ region: initialRegion }); } this.setState({ isReady: true }); } @@ -362,10 +362,10 @@ class MapView extends React.Component { const { isReady } = this.state; if (region && isReady && !this.__layoutCalled) { this.__layoutCalled = true; - this.refs.map.setNativeProps({ region }); + this.map.setNativeProps({ region }); } else if (initialRegion && isReady && !this.__layoutCalled) { this.__layoutCalled = true; - this.refs.map.setNativeProps({ region: initialRegion }); + this.map.setNativeProps({ region: initialRegion }); } if (onLayout) { onLayout(e); @@ -405,7 +405,7 @@ class MapView extends React.Component { } _getHandle() { - return findNodeHandle(this.refs.map); + return findNodeHandle(this.map); } _runCommand(name, args) { @@ -458,7 +458,10 @@ class MapView extends React.Component { } return ( - + { this.map = ref; }} + {...props} + /> ); } } diff --git a/example/examples/CachedMap.js b/example/examples/CachedMap.js index 93650616a..fe1977153 100644 --- a/example/examples/CachedMap.js +++ b/example/examples/CachedMap.js @@ -9,6 +9,7 @@ import { } from 'react-native'; import MapView from 'react-native-maps'; +import flagImg from './assets/flag-blue.png'; const HORIZONTAL_PADDING = 12; const VERTICAL_PADDING = 6; @@ -71,7 +72,7 @@ class CachedMap extends React.Component { coordinate={region} centerOffset={{ x: -18, y: -60 }} anchor={{ x: 0.69, y: 1 }} - image={require('./assets/flag-blue.png')} + image={flagImg} /> diff --git a/example/examples/Callouts.js b/example/examples/Callouts.js index 09325d10e..299ca097e 100644 --- a/example/examples/Callouts.js +++ b/example/examples/Callouts.js @@ -54,11 +54,11 @@ class Callouts extends React.Component { } show() { - this.refs.m1.showCallout(); + this.marker1.showCallout(); } hide() { - this.refs.m1.hideCallout(); + this.marker1.hideCallout(); } render() { @@ -70,13 +70,12 @@ class Callouts extends React.Component { initialRegion={region} > { this.marker1 = ref; }} coordinate={markers[0].coordinate} title="This is a title" description="This is a description" /> @@ -86,7 +85,6 @@ class Callouts extends React.Component { { this.map = ref; }} mapType="terrain" style={styles.map} region={this.state.region} diff --git a/example/examples/DraggableMarkers.js b/example/examples/DraggableMarkers.js index aec6dad21..c3a21127f 100644 --- a/example/examples/DraggableMarkers.js +++ b/example/examples/DraggableMarkers.js @@ -37,7 +37,6 @@ class MarkerTypes extends React.Component { return ( { this.map = ref; }} style={styles.map} initialRegion={{ latitude: LATITUDE, diff --git a/example/examples/LoadingMap.js b/example/examples/LoadingMap.js index 8295e6398..28b45e3f7 100644 --- a/example/examples/LoadingMap.js +++ b/example/examples/LoadingMap.js @@ -7,6 +7,7 @@ import { } from 'react-native'; import MapView from 'react-native-maps'; +import flagImg from './assets/flag-blue.png'; const { width, height } = Dimensions.get('window'); @@ -49,7 +50,7 @@ class LoadingMap extends React.Component { }} centerOffset={{ x: -18, y: -60 }} anchor={{ x: 0.69, y: 1 }} - image={require('./assets/flag-blue.png')} + image={flagImg} /> { this.map = ref; }} style={styles.map} initialRegion={{ latitude: LATITUDE, From c9d783a32546b942217b999e5e06381639910e1b Mon Sep 17 00:00:00 2001 From: Spike Brehm Date: Wed, 31 Aug 2016 13:15:42 -0700 Subject: [PATCH 0036/1148] [ESLint] Fix bug in PolygonCreator from ESLint refactor --- example/examples/PolygonCreator.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/example/examples/PolygonCreator.js b/example/examples/PolygonCreator.js index cc732b12f..93c3ef09d 100644 --- a/example/examples/PolygonCreator.js +++ b/example/examples/PolygonCreator.js @@ -71,7 +71,7 @@ class DisplayLatLng extends React.Component { if (this.state.editing) { mapOptions.scrollEnabled = false; - mapOptions.onPanDrag = this.onPress; + mapOptions.onPanDrag = e => this.onPress(e); } return ( From 7b6c4cdf757e26afd26945a60be4784c7e8af062 Mon Sep 17 00:00:00 2001 From: Spike Brehm Date: Wed, 31 Aug 2016 14:17:39 -0700 Subject: [PATCH 0037/1148] Make ScrollView in example/App.js full-width The example app had bad UX because you could only scroll in the middle of the screen. Make the `` use `StyleSheet.absoluteFill` to make it full-width. --- example/App.js | 1 + 1 file changed, 1 insertion(+) diff --git a/example/App.js b/example/App.js index 7e78aea94..95a1c1953 100644 --- a/example/App.js +++ b/example/App.js @@ -61,6 +61,7 @@ const App = React.createClass({ {Component && this.renderBackButton()} {!Component && ( From 1dd545947a538799a7dc5a983870dc697a5ed8e9 Mon Sep 17 00:00:00 2001 From: Spike Brehm Date: Wed, 31 Aug 2016 14:51:38 -0700 Subject: [PATCH 0038/1148] [ESLint] Fix comment spacing issue --- example/examples/AnimatedViews.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/example/examples/AnimatedViews.js b/example/examples/AnimatedViews.js index 4d2c421e9..52818f854 100644 --- a/example/examples/AnimatedViews.js +++ b/example/examples/AnimatedViews.js @@ -396,7 +396,7 @@ const styles = StyleSheet.create({ position: 'absolute', // top: screen.height - ITEM_PREVIEW_HEIGHT - 64, paddingTop: screen.height - ITEM_PREVIEW_HEIGHT - 64, - //paddingTop: !ANDROID ? 0 : screen.height - ITEM_PREVIEW_HEIGHT - 64, + // paddingTop: !ANDROID ? 0 : screen.height - ITEM_PREVIEW_HEIGHT - 64, }, map: { backgroundColor: 'transparent', From 9ff97a5bfc7ee08835df3788e3b2592febcd387f Mon Sep 17 00:00:00 2001 From: Spike Brehm Date: Thu, 1 Sep 2016 18:42:17 -0700 Subject: [PATCH 0039/1148] Fix path of AirMapModule The PR that added `AirMapModule` (#449) was merged after the PR that moved all the `lib/src/*` files to just `src/*` (#502). Fix it by moving `AirMapModule` to `src/`. --- .../main/java/com/airbnb/android/react/maps/AirMapManager.java | 1 - .../main/java/com/airbnb/android/react/maps/AirMapModule.java | 0 2 files changed, 1 deletion(-) rename android/{lib => }/src/main/java/com/airbnb/android/react/maps/AirMapModule.java (100%) diff --git a/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java b/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java index 3dda607e2..876495d19 100644 --- a/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java +++ b/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java @@ -1,7 +1,6 @@ package com.airbnb.android.react.maps; import android.view.View; -import android.content.Context; import com.facebook.react.bridge.Arguments; import com.facebook.react.bridge.ReactApplicationContext; diff --git a/android/lib/src/main/java/com/airbnb/android/react/maps/AirMapModule.java b/android/src/main/java/com/airbnb/android/react/maps/AirMapModule.java similarity index 100% rename from android/lib/src/main/java/com/airbnb/android/react/maps/AirMapModule.java rename to android/src/main/java/com/airbnb/android/react/maps/AirMapModule.java From b6197a8865c3963d5cb16b081ef5e3c56e2c5568 Mon Sep 17 00:00:00 2001 From: Spike Brehm Date: Thu, 1 Sep 2016 18:48:58 -0700 Subject: [PATCH 0040/1148] Fix path to react-native when developing outside of the example app In #502, the local maven url pointing to the `react-native` node module changed to work better for the example app. However, that broke the path to `react-native` when developing in the context of the library, not the example app. In this PR, specify both paths. --- android/build.gradle | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/android/build.gradle b/android/build.gradle index 3e22dc951..e639f6aa8 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -8,6 +8,15 @@ buildscript { mavenLocal() jcenter() maven { + // For developing the library outside the context of the example app, expect `react-native` + // to be installed at `./android/node_modules`. + url "$projectDir/../node_modules/react-native/android" + } + maven { + // For developing the example app, expect this library to be installed as a node module + // inside of the example app. So traverse from `./android/example/node_modules/react-native-maps/android` + // to `./android/example/node_modules/react-native/android`. + // react-native should be installed since it's a peer dependency url "$projectDir/../../react-native/android" } } @@ -20,8 +29,15 @@ allprojects { repositories { mavenLocal() jcenter() + maven { + // For developing the library outside the context of the example app, expect `react-native` + // to be installed at `./android/node_modules`. + url "$projectDir/../node_modules/react-native/android" + } maven { - // Refer to the local install of react-native in the node_modules folder + // For developing the example app, expect this library to be installed as a node module + // inside of the example app. So traverse from `./android/example/node_modules/react-native-maps/android` + // to `./android/example/node_modules/react-native/android`. // react-native should be installed since it's a peer dependency url "$projectDir/../../react-native/android" } From f0ba243bb02124c677afd23842739e026633c770 Mon Sep 17 00:00:00 2001 From: Saro Vindigni Date: Fri, 2 Sep 2016 10:55:28 +0200 Subject: [PATCH 0041/1148] ADD npm version on Readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6b36fb930..fcbc03d9a 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# react-native-maps +# react-native-maps [![npm version](https://img.shields.io/npm/v/react-native-maps.svg?style=flat)](https://www.npmjs.com/package/react-native-maps) React Native Map components for iOS + Android From 0e60f723adf13c0e0223c26fa88f50e5b7600482 Mon Sep 17 00:00:00 2001 From: Ivan Wu Date: Fri, 2 Sep 2016 09:39:05 -0700 Subject: [PATCH 0042/1148] Bumped google-play-things in build.gradle to 9.+ --- android/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/android/build.gradle b/android/build.gradle index 3e22dc951..57c1d1ccc 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -44,6 +44,6 @@ android { dependencies { compile 'com.facebook.react:react-native:0.32.0' - compile "com.google.android.gms:play-services-base:8.4.0" - compile 'com.google.android.gms:play-services-maps:8.4.0' + compile "com.google.android.gms:play-services-base:9.+" + compile 'com.google.android.gms:play-services-maps:9.+' } From 78470a16b73a1d57f5fa1cc3b6b13af644a91340 Mon Sep 17 00:00:00 2001 From: Ben Roth Date: Fri, 2 Sep 2016 12:50:15 -0700 Subject: [PATCH 0043/1148] Fix a few warnings on iOS --- ios/AirMaps/AIRMapManager.m | 2 +- ios/AirMaps/AIRMapMarker.m | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ios/AirMaps/AIRMapManager.m b/ios/AirMaps/AIRMapManager.m index 6794577a1..df806210e 100644 --- a/ios/AirMaps/AIRMapManager.m +++ b/ios/AirMaps/AIRMapManager.m @@ -172,7 +172,7 @@ - (UIView *)view } else { AIRMap *mapView = (AIRMap *)view; // TODO(lmr): we potentially want to include overlays here... and could concat the two arrays together. - id annotations = mapView.annotations; + // id annotations = mapView.annotations; NSPredicate *filterMarkers = [NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary *bindings) { AIRMapMarker *marker = (AIRMapMarker *)evaluatedObject; diff --git a/ios/AirMaps/AIRMapMarker.m b/ios/AirMaps/AIRMapMarker.m index 2c8c16e86..b457d2fb0 100644 --- a/ios/AirMaps/AIRMapMarker.m +++ b/ios/AirMaps/AIRMapMarker.m @@ -53,7 +53,7 @@ - (void)insertReactSubview:(id)subview atIndex:(NSInteger)atIndex if ([subview isKindOfClass:[AIRMapCallout class]]) { self.calloutView = (AIRMapCallout *)subview; } else { - [super insertReactSubview:subview atIndex:atIndex]; + [super insertReactSubview:(UIView *)subview atIndex:atIndex]; } } @@ -61,7 +61,7 @@ - (void)removeReactSubview:(id)subview { if ([subview isKindOfClass:[AIRMapCallout class]] && self.calloutView == subview) { self.calloutView = nil; } else { - [super removeReactSubview:subview]; + [super removeReactSubview:(UIView *)subview]; } } @@ -213,7 +213,7 @@ - (void)setImageSrc:(NSString *)imageSrc size:self.bounds.size scale:RCTScreenScale() clipped:YES - resizeMode:UIViewContentModeCenter + resizeMode:RCTResizeModeCenter progressBlock:nil completionBlock:^(NSError *error, UIImage *image) { if (error) { From 68669bd5ab88db50b905898b7f3760e2d920628b Mon Sep 17 00:00:00 2001 From: Ivan Wu Date: Fri, 2 Sep 2016 15:50:49 -0700 Subject: [PATCH 0044/1148] changed build.gradle to use play services 9.4.0 --- android/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/android/build.gradle b/android/build.gradle index 57c1d1ccc..f327eac8a 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -44,6 +44,6 @@ android { dependencies { compile 'com.facebook.react:react-native:0.32.0' - compile "com.google.android.gms:play-services-base:9.+" - compile 'com.google.android.gms:play-services-maps:9.+' + compile "com.google.android.gms:play-services-base:9.4.0" + compile 'com.google.android.gms:play-services-maps:9.4.0' } From c1cd9f9438d453d3e94bd22f7360649af697a20a Mon Sep 17 00:00:00 2001 From: Spike Brehm Date: Tue, 6 Sep 2016 11:31:54 -0700 Subject: [PATCH 0045/1148] Add .travis.yml to run ESLint --- .travis.yml | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 000000000..e1b9dc4ea --- /dev/null +++ b/.travis.yml @@ -0,0 +1,11 @@ +language: node_js + +node_js: + - "6" + +cache: + directories: + - node_modules + - example/node_modules + +script: npm install && npm run lint From f20b6e6e1ce2c1dae4356cfa6a6fe5c54127909d Mon Sep 17 00:00:00 2001 From: Spike Brehm Date: Tue, 6 Sep 2016 11:35:10 -0700 Subject: [PATCH 0046/1148] Remove explicit `npm install`, which happens automatically --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index e1b9dc4ea..5e075585c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,4 +8,4 @@ cache: - node_modules - example/node_modules -script: npm install && npm run lint +script: npm run lint From 37cb17d2e38af5d93b748da6bbad6c024bf4a891 Mon Sep 17 00:00:00 2001 From: Spike Brehm Date: Tue, 6 Sep 2016 11:16:56 -0700 Subject: [PATCH 0047/1148] Fix a few spots where forgot to update version from 0.7.1 to 0.8.0 Update the respective Android & iOS versioning files to indicate we're on version 0.8.0 instead of 0.7.1. --- android/gradle.properties | 2 +- react-native-maps.podspec | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/android/gradle.properties b/android/gradle.properties index c86911511..116e1e693 100644 --- a/android/gradle.properties +++ b/android/gradle.properties @@ -1,5 +1,5 @@ VERSION_CODE=2 -VERSION_NAME=0.7.1 +VERSION_NAME=0.8.0 GROUP=com.airbnb.android POM_DESCRIPTION=React Native Map view component for Android diff --git a/react-native-maps.podspec b/react-native-maps.podspec index c9fe89337..c3823f92e 100644 --- a/react-native-maps.podspec +++ b/react-native-maps.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "react-native-maps" - s.version = "0.7.1" + s.version = "0.8.0" s.summary = "React Native Mapview component for iOS + Android" s.authors = { "intelligibabble" => "leland.m.richardson@gmail.com" } From 41a065dcfe43269d7d443b08d07cb6247fdd9dde Mon Sep 17 00:00:00 2001 From: Felipe Matos Santana Date: Wed, 7 Sep 2016 12:36:36 -0300 Subject: [PATCH 0048/1148] Use latest version of RN to build Android --- android/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android/build.gradle b/android/build.gradle index b23540e12..684c92e24 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -59,7 +59,7 @@ android { } dependencies { - compile 'com.facebook.react:react-native:0.32.0' + compile 'com.facebook.react:react-native:+' compile "com.google.android.gms:play-services-base:9.4.0" compile 'com.google.android.gms:play-services-maps:9.4.0' } From 3631a8cc41280c6834c1df99a9f32fb6d12f60f3 Mon Sep 17 00:00:00 2001 From: Felipe Lima Date: Thu, 8 Sep 2016 17:22:18 -0300 Subject: [PATCH 0049/1148] Prepare for release v0.8.1 --- CHANGELOG.md | 4 ++++ android/gradle.properties | 2 +- example/android/build.gradle | 2 +- example/android/gradle/wrapper/gradle-wrapper.properties | 3 ++- package.json | 2 +- react-native-maps.podspec | 2 +- 6 files changed, 10 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 920dd8683..c4daa92cb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Change Log +### Patches + +- Use latest available (wildcard version) of RN to build Android ([PR #547](https://github.com/lelandrichardson/react-native-maps/pull/547)) + ## 0.8.0 (August 30, 2016) ### Breaking Changes diff --git a/android/gradle.properties b/android/gradle.properties index 116e1e693..3c3e83764 100644 --- a/android/gradle.properties +++ b/android/gradle.properties @@ -1,5 +1,5 @@ VERSION_CODE=2 -VERSION_NAME=0.8.0 +VERSION_NAME=0.8.1 GROUP=com.airbnb.android POM_DESCRIPTION=React Native Map view component for Android diff --git a/example/android/build.gradle b/example/android/build.gradle index c9f24f32a..421e13f2f 100644 --- a/example/android/build.gradle +++ b/example/android/build.gradle @@ -5,7 +5,7 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:2.1.0' + classpath 'com.android.tools.build:gradle:2.1.3' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files diff --git a/example/android/gradle/wrapper/gradle-wrapper.properties b/example/android/gradle/wrapper/gradle-wrapper.properties index b3c42aa00..1aeeffed4 100644 --- a/example/android/gradle/wrapper/gradle-wrapper.properties +++ b/example/android/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,6 @@ +#Thu Sep 08 17:18:44 BRT 2016 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-2.13-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip diff --git a/package.json b/package.json index 407134366..4a60f2b20 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "description": "React Native Mapview component for iOS + Android", "main": "index.js", "author": "Leland Richardson ", - "version": "0.8.0", + "version": "0.8.1", "scripts": { "start": "react-native start", "lint": "eslint ." diff --git a/react-native-maps.podspec b/react-native-maps.podspec index c3823f92e..2eaba6cb5 100644 --- a/react-native-maps.podspec +++ b/react-native-maps.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "react-native-maps" - s.version = "0.8.0" + s.version = "0.8.1" s.summary = "React Native Mapview component for iOS + Android" s.authors = { "intelligibabble" => "leland.m.richardson@gmail.com" } From 8ff3fe13b2589beeaad65381cb5156e24ecf9c10 Mon Sep 17 00:00:00 2001 From: Felipe Lima Date: Thu, 8 Sep 2016 17:31:49 -0300 Subject: [PATCH 0050/1148] Add a version header to the changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c4daa92cb..3c6621b2d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,7 @@ # Change Log +## 0.8.1 (September 8, 2016) + ### Patches - Use latest available (wildcard version) of RN to build Android ([PR #547](https://github.com/lelandrichardson/react-native-maps/pull/547)) From 34d88f162f6276b3719aa4e457cd01c51a74ced6 Mon Sep 17 00:00:00 2001 From: Felipe Lima Date: Thu, 8 Sep 2016 17:49:02 -0300 Subject: [PATCH 0051/1148] Adds full list of changes to the changelog --- CHANGELOG.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3c6621b2d..b56086804 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,13 @@ ### Patches -- Use latest available (wildcard version) of RN to build Android ([PR #547](https://github.com/lelandrichardson/react-native-maps/pull/547)) +- [Android] Use latest available (wildcard version) of RN to build Android ([PR #547](https://github.com/lelandrichardson/react-native-maps/pull/547)) +- [Android] Use `Activity` to call `MapsInitialier.initialize()` ([PR #449](https://github.com/lelandrichardson/react-native-maps/pull/449)) +- [Android] Fix file path for `AirMapModule` ([PR #526](https://github.com/lelandrichardson/react-native-maps/pull/526)) +- [Android] Fix path to React Native in `node_modules` ([PR #527](https://github.com/lelandrichardson/react-native-maps/pull/527)) +- [Android] Bump Google Play Services dependency to `9.4.0` ([PR #533](https://github.com/lelandrichardson/react-native-maps/pull/533)) +- [iOS] Fix a few warnings ([PR #534](https://github.com/lelandrichardson/react-native-maps/pull/534)) +- [JS] Fix ESLint violations ([PR #515](https://github.com/lelandrichardson/react-native-maps/pull/515)) ## 0.8.0 (August 30, 2016) From c79af5fb6a5b2734fec8143067af7b10551a9c50 Mon Sep 17 00:00:00 2001 From: Spike Brehm Date: Thu, 8 Sep 2016 14:44:47 -0700 Subject: [PATCH 0052/1148] Version 0.8.2 --- CHANGELOG.md | 19 ++++++++++++++++++- android/gradle.properties | 2 +- package.json | 2 +- react-native-maps.podspec | 2 +- 4 files changed, 21 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b56086804..12854022f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,23 @@ # Change Log -## 0.8.1 (September 8, 2016) +## 0.8.2 (September 8, 2016) + +We realized immediately after publishing 0.8.1 that the NPM package contained +some test code in the `example2/` directory that contained a copy of the +`react-native` package, causing this packager error: + +``` +Failed to build DependencyGraph: @providesModule naming collision: + Duplicate module name: String.prototype.es6 + Paths: /Users//node_modules/react-native-maps/example2/node_modules/react-native/packager/react-packager/src/Resolver/polyfills/String.prototype.es6.js collides with /Users//node_modules/react-native/packager/react-packager/src/Resolver/polyfills/String.prototype.es6.js + +This error is caused by a @providesModule declaration with the same name accross two different files. +``` + +0.8.2 is identical to 0.8.1, except with the offending code removed from the NPM package. + + +## 0.8.1 (September 8, 2016) *[DEPRECATED]* ### Patches diff --git a/android/gradle.properties b/android/gradle.properties index 3c3e83764..c81d03497 100644 --- a/android/gradle.properties +++ b/android/gradle.properties @@ -1,5 +1,5 @@ VERSION_CODE=2 -VERSION_NAME=0.8.1 +VERSION_NAME=0.8.2 GROUP=com.airbnb.android POM_DESCRIPTION=React Native Map view component for Android diff --git a/package.json b/package.json index 4a60f2b20..2025e7b2f 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "description": "React Native Mapview component for iOS + Android", "main": "index.js", "author": "Leland Richardson ", - "version": "0.8.1", + "version": "0.8.2", "scripts": { "start": "react-native start", "lint": "eslint ." diff --git a/react-native-maps.podspec b/react-native-maps.podspec index 2eaba6cb5..148329e12 100644 --- a/react-native-maps.podspec +++ b/react-native-maps.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "react-native-maps" - s.version = "0.8.1" + s.version = "0.8.2" s.summary = "React Native Mapview component for iOS + Android" s.authors = { "intelligibabble" => "leland.m.richardson@gmail.com" } From d76517f5795670a1eb4d0d2dbc1e39099ad8e0e9 Mon Sep 17 00:00:00 2001 From: Spike Brehm Date: Thu, 8 Sep 2016 14:49:57 -0700 Subject: [PATCH 0053/1148] Update CHANGELOG.md --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 12854022f..db21f9f5e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,8 @@ This error is caused by a @providesModule declaration with the same name accross ## 0.8.1 (September 8, 2016) *[DEPRECATED]* +#### *NOTE: 0.8.1 has been unpublished from NPM beacuse it was faulty. Please use 0.8.2.* + ### Patches - [Android] Use latest available (wildcard version) of RN to build Android ([PR #547](https://github.com/lelandrichardson/react-native-maps/pull/547)) From 705061044796c533db0b75549d2055fa7b349ce8 Mon Sep 17 00:00:00 2001 From: Ben Roth Date: Fri, 9 Sep 2016 20:21:40 -0700 Subject: [PATCH 0054/1148] Add class prefix to EmptyCalloutBackgroundView --- ios/AirMaps/AIRMapMarker.h | 4 ++-- ios/AirMaps/AIRMapMarker.m | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ios/AirMaps/AIRMapMarker.h b/ios/AirMaps/AIRMapMarker.h index d57c1f9d0..d1779074f 100644 --- a/ios/AirMaps/AIRMapMarker.h +++ b/ios/AirMaps/AIRMapMarker.h @@ -51,5 +51,5 @@ @end -@interface EmptyCalloutBackgroundView : SMCalloutBackgroundView -@end \ No newline at end of file +@interface AIREmptyCalloutBackgroundView : SMCalloutBackgroundView +@end diff --git a/ios/AirMaps/AIRMapMarker.m b/ios/AirMaps/AIRMapMarker.m index b457d2fb0..79343cff0 100644 --- a/ios/AirMaps/AIRMapMarker.m +++ b/ios/AirMaps/AIRMapMarker.m @@ -15,7 +15,7 @@ #import "RCTUtils.h" #import "RCTImageLoader.h" -@implementation EmptyCalloutBackgroundView +@implementation AIREmptyCalloutBackgroundView @end @implementation AIRMapMarker { @@ -110,7 +110,7 @@ - (void)fillCalloutView:(SMCalloutView *)calloutView if (self.calloutView.tooltip) { // if tooltip is true, then the user wants their react view to be the "tooltip" as wwell, so we set // the background view to something empty/transparent - calloutView.backgroundView = [EmptyCalloutBackgroundView new]; + calloutView.backgroundView = [AIREmptyCalloutBackgroundView new]; } else { // the default tooltip look is wanted, and the user is just filling the content with their react subviews. // as a result, we use the default "masked" background view. From 81745300d1c5646be1004680aa264b6ae2410fe0 Mon Sep 17 00:00:00 2001 From: Felipe Lima Date: Sat, 10 Sep 2016 19:04:50 -0300 Subject: [PATCH 0055/1148] [Android] Minor code cleanup * Remove unused variables and fields * Fix compiler warnings (unchecked, deprecation, etc) --- .../gradle/wrapper/gradle-wrapper.properties | 4 +- .../react/maps/AirMapCalloutManager.java | 7 +-- .../react/maps/AirMapMarkerManager.java | 6 +- .../airbnb/android/react/maps/AirMapView.java | 55 ++++--------------- .../android/react/maps/MapsPackage.java | 7 ++- 5 files changed, 23 insertions(+), 56 deletions(-) diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties index ab100c03b..e122d0524 100644 --- a/android/gradle/wrapper/gradle-wrapper.properties +++ b/android/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Mon Dec 28 10:00:20 PST 2015 +#Sat Sep 10 19:01:47 BRT 2016 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-2.13-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip diff --git a/android/src/main/java/com/airbnb/android/react/maps/AirMapCalloutManager.java b/android/src/main/java/com/airbnb/android/react/maps/AirMapCalloutManager.java index 5c21fadd3..359e6847b 100644 --- a/android/src/main/java/com/airbnb/android/react/maps/AirMapCalloutManager.java +++ b/android/src/main/java/com/airbnb/android/react/maps/AirMapCalloutManager.java @@ -28,12 +28,9 @@ public void setTooltip(AirMapCallout view, boolean tooltip) { } @Override - public @Nullable - Map getExportedCustomDirectEventTypeConstants() { - return MapBuilder.of( - "onPress", MapBuilder.of("registrationName", "onPress") - ); + public Map getExportedCustomDirectEventTypeConstants() { + return MapBuilder.of("onPress", MapBuilder.of("registrationName", "onPress")); } @Override diff --git a/android/src/main/java/com/airbnb/android/react/maps/AirMapMarkerManager.java b/android/src/main/java/com/airbnb/android/react/maps/AirMapMarkerManager.java index 52a0e6fc7..f87a8233a 100644 --- a/android/src/main/java/com/airbnb/android/react/maps/AirMapMarkerManager.java +++ b/android/src/main/java/com/airbnb/android/react/maps/AirMapMarkerManager.java @@ -19,8 +19,8 @@ public class AirMapMarkerManager extends ViewGroupManager { - public static final int SHOW_INFO_WINDOW = 1; - public static final int HIDE_INFO_WINDOW = 2; + private static final int SHOW_INFO_WINDOW = 1; + private static final int HIDE_INFO_WINDOW = 2; public AirMapMarkerManager() { } @@ -159,7 +159,7 @@ public void receiveCommand(AirMapMarker view, int commandId, @Nullable ReadableA @Override @Nullable public Map getExportedCustomDirectEventTypeConstants() { - Map map = MapBuilder.of( + Map> map = MapBuilder.of( "onPress", MapBuilder.of("registrationName", "onPress"), "onCalloutPress", MapBuilder.of("registrationName", "onCalloutPress"), "onDragStart", MapBuilder.of("registrationName", "onDragStart"), diff --git a/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java b/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java index b817f804f..dc1bc8876 100644 --- a/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java +++ b/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java @@ -1,27 +1,25 @@ package com.airbnb.android.react.maps; +import android.content.Context; import android.content.pm.PackageManager; import android.content.res.ColorStateList; import android.graphics.Bitmap; import android.graphics.Color; import android.graphics.Point; import android.graphics.PorterDuff; -import android.os.Handler; import android.os.Build; +import android.os.Handler; import android.support.v4.view.GestureDetectorCompat; import android.support.v4.view.MotionEventCompat; import android.view.GestureDetector; import android.view.MotionEvent; import android.view.ScaleGestureDetector; import android.view.View; -import android.view.View.OnLayoutChangeListener; -import android.content.Context; - import android.view.ViewGroup; import android.widget.ImageView; import android.widget.ProgressBar; import android.widget.RelativeLayout; -import android.widget.TextView; + import com.facebook.react.bridge.LifecycleEventListener; import com.facebook.react.bridge.ReadableArray; import com.facebook.react.bridge.ReadableMap; @@ -37,12 +35,9 @@ import com.google.android.gms.maps.OnMapReadyCallback; import com.google.android.gms.maps.Projection; import com.google.android.gms.maps.model.CameraPosition; -import com.google.android.gms.maps.model.Circle; import com.google.android.gms.maps.model.LatLng; import com.google.android.gms.maps.model.LatLngBounds; import com.google.android.gms.maps.model.Marker; -import com.google.android.gms.maps.model.Polygon; -import com.google.android.gms.maps.model.Polyline; import java.util.ArrayList; import java.util.Arrays; @@ -55,40 +50,31 @@ public class AirMapView extends MapView implements GoogleMap.InfoWindowAdapter, GoogleMap.OnMarkerDragListener, OnMapReadyCallback { public GoogleMap map; - private ProgressBar mapLoadingProgressBar; private RelativeLayout mapLoadingLayout; private ImageView cacheImageView; private Boolean isMapLoaded = false; private Integer loadingBackgroundColor = null; private Integer loadingIndicatorColor = null; - private LatLngBounds boundsToMove; private boolean showUserLocation = false; private boolean isMonitoringRegion = false; private boolean isTouchDown = false; private boolean handlePanDrag = false; private boolean cacheEnabled = false; - private boolean loadingEnabled = false; private static final String[] PERMISSIONS = new String[] { "android.permission.ACCESS_FINE_LOCATION", "android.permission.ACCESS_COARSE_LOCATION"}; private final List features = new ArrayList<>(); private final Map markerMap = new HashMap<>(); - private final Map polylineMap = new HashMap<>(); - private final Map polygonMap = new HashMap<>(); - private final Map circleMap = new HashMap<>(); - private final ScaleGestureDetector scaleDetector; private final GestureDetectorCompat gestureDetector; private final AirMapManager manager; private LifecycleEventListener lifecycleListener; - private OnLayoutChangeListener onLayoutChangeListener; private boolean paused = false; - private ThemedReactContext context; - - final EventDispatcher eventDispatcher; + private final ThemedReactContext context; + private final EventDispatcher eventDispatcher; public AirMapView(ThemedReactContext context, Context appContext, AirMapManager manager) { super(appContext); @@ -102,12 +88,6 @@ public AirMapView(ThemedReactContext context, Context appContext, AirMapManager final AirMapView view = this; scaleDetector = new ScaleGestureDetector(context, new ScaleGestureDetector.SimpleOnScaleGestureListener() { -// @Override -// public boolean onScale(ScaleGestureDetector detector) { -// Log.d("AirMapView", "onScale"); -// return false; -// } - @Override public boolean onScaleBegin(ScaleGestureDetector detector) { view.startMonitoringRegion(); @@ -134,15 +114,14 @@ public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, } }); - onLayoutChangeListener = new OnLayoutChangeListener() { + this.addOnLayoutChangeListener(new OnLayoutChangeListener() { @Override public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) { if (!AirMapView.this.paused) { AirMapView.this.cacheView(); } } - }; - this.addOnLayoutChangeListener(this.onLayoutChangeListener); + }); eventDispatcher = context.getNativeModule(UIManagerModule.class).getEventDispatcher(); } @@ -404,20 +383,14 @@ public void addFeature(View child, int index) { AirMapPolyline polylineView = (AirMapPolyline) child; polylineView.addToMap(map); features.add(index, polylineView); - Polyline polyline = (Polyline) polylineView.getFeature(); - polylineMap.put(polyline, polylineView); } else if (child instanceof AirMapPolygon) { AirMapPolygon polygonView = (AirMapPolygon) child; polygonView.addToMap(map); features.add(index, polygonView); - Polygon polygon = (Polygon) polygonView.getFeature(); - polygonMap.put(polygon, polygonView); } else if (child instanceof AirMapCircle) { AirMapCircle circleView = (AirMapCircle) child; circleView.addToMap(map); features.add(index, circleView); - Circle circle = (Circle) circleView.getFeature(); - circleMap.put(circle, circleView); } else { // TODO(lmr): throw? User shouldn't be adding non-feature children. } @@ -433,16 +406,8 @@ public View getFeatureAt(int index) { public void removeFeatureAt(int index) { AirMapFeature feature = features.remove(index); - - if (feature instanceof AirMapMarker) { markerMap.remove(feature.getFeature()); - } else if (feature instanceof AirMapPolyline) { - polylineMap.remove(feature.getFeature()); - } else if (feature instanceof AirMapPolygon) { - polygonMap.remove(feature.getFeature()); - } else if (feature instanceof AirMapCircle) { - circleMap.remove(feature.getFeature()); } feature.removeFromMap(map); } @@ -667,9 +632,11 @@ private RelativeLayout getMapLoadingLayoutView() { this.mapLoadingLayout = new RelativeLayout(getContext()); this.mapLoadingLayout.setBackgroundColor(Color.LTGRAY); this.addView(this.mapLoadingLayout, - new ViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.FILL_PARENT)); + new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.MATCH_PARENT)); - RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT); + RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams( + RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT); params.addRule(RelativeLayout.CENTER_IN_PARENT); this.mapLoadingLayout.addView(this.getMapLoadingProgressBar(), params); diff --git a/android/src/main/java/com/airbnb/android/react/maps/MapsPackage.java b/android/src/main/java/com/airbnb/android/react/maps/MapsPackage.java index 33c523800..6b910d7a3 100644 --- a/android/src/main/java/com/airbnb/android/react/maps/MapsPackage.java +++ b/android/src/main/java/com/airbnb/android/react/maps/MapsPackage.java @@ -13,8 +13,11 @@ import java.util.List; public class MapsPackage implements ReactPackage { - public MapsPackage(Activity activity) { } // backwards compatability - public MapsPackage() { } + public MapsPackage(Activity activity) { + } // backwards compatability + + public MapsPackage() { + } @Override public List createNativeModules(ReactApplicationContext reactContext) { From 4c827857c27bd1a70875ee406b3f77e34c70a480 Mon Sep 17 00:00:00 2001 From: Haibin Yu Date: Sun, 11 Sep 2016 10:49:51 +0800 Subject: [PATCH 0056/1148] add showsMyLocationButton props in docs --- docs/mapview.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/mapview.md b/docs/mapview.md index 34999e236..90c26684f 100644 --- a/docs/mapview.md +++ b/docs/mapview.md @@ -9,6 +9,7 @@ | `mapType` | `String` | `"standard"` | The map type to be displayed.

- standard: standard road map (default)
- satellite: satellite view
- hybrid: satellite view with roads and points of interest overlayed
- terrain: (Android only) topographic view | `showsUserLocation` | `Boolean` | `false` | If `true` the app will ask for the user's location. **NOTE**: You need to add `NSLocationWhenInUseUsageDescription` key in Info.plist to enable geolocation, otherwise it is going to *fail silently*! | `followsUserLocation` | `Boolean` | `false` | If `true` the map will focus on the user's location. This only works if `showsUserLocation` is true and the user has shared their location. **Note**: iOS only. +| `showsMyLocationButton` | `Boolean` | `true` | `Android only` If `false` hide the button to move map to the current user's location. | `showsPointsOfInterest` | `Boolean` | `true` | If `false` points of interest won't be displayed on the map. | `showsCompass` | `Boolean` | `true` | If `false` compass won't be displayed on the map. | `showsScale` | `Boolean` | `true` | A Boolean indicating whether the map shows scale information. From 05ab993504914fa4ad63c0449fab6f6ec15e748d Mon Sep 17 00:00:00 2001 From: Ryan Kaskel Date: Sun, 11 Sep 2016 13:45:09 +0100 Subject: [PATCH 0057/1148] Don't fit to elements if no positions added --- .../airbnb/android/react/maps/AirMapView.java | 21 ++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java b/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java index b817f804f..6cf538074 100644 --- a/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java +++ b/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java @@ -497,20 +497,27 @@ public void animateToCoordinate(LatLng coordinate, int duration) { public void fitToElements(boolean animated) { LatLngBounds.Builder builder = new LatLngBounds.Builder(); + + boolean addedPosition = false; + for (AirMapFeature feature : features) { if (feature instanceof AirMapMarker) { Marker marker = (Marker) feature.getFeature(); builder.include(marker.getPosition()); + addedPosition = true; } // TODO(lmr): may want to include shapes / etc. } - LatLngBounds bounds = builder.build(); - CameraUpdate cu = CameraUpdateFactory.newLatLngBounds(bounds, 50); - if (animated) { - startMonitoringRegion(); - map.animateCamera(cu); - } else { - map.moveCamera(cu); + + if (addedPosition) { + LatLngBounds bounds = builder.build(); + CameraUpdate cu = CameraUpdateFactory.newLatLngBounds(bounds, 50); + if (animated) { + startMonitoringRegion(); + map.animateCamera(cu); + } else { + map.moveCamera(cu); + } } } From 96ff40c0ce54baaa6a397504aec47c58197e60df Mon Sep 17 00:00:00 2001 From: Spike Brehm Date: Tue, 13 Sep 2016 08:57:23 -0700 Subject: [PATCH 0058/1148] s/lelandrichardson/airbnb/ Now that we've moved the repo over, updated all references of `lelandrichardson` to be `airbnb`. --- CHANGELOG.md | 44 +++++++++++++++++++-------------------- README.md | 4 ++-- android/gradle.properties | 12 +++++------ docs/installation.md | 2 +- package.json | 2 +- react-native-maps.podspec | 4 ++-- 6 files changed, 34 insertions(+), 34 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index db21f9f5e..24555b136 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,44 +23,44 @@ This error is caused by a @providesModule declaration with the same name accross ### Patches -- [Android] Use latest available (wildcard version) of RN to build Android ([PR #547](https://github.com/lelandrichardson/react-native-maps/pull/547)) -- [Android] Use `Activity` to call `MapsInitialier.initialize()` ([PR #449](https://github.com/lelandrichardson/react-native-maps/pull/449)) -- [Android] Fix file path for `AirMapModule` ([PR #526](https://github.com/lelandrichardson/react-native-maps/pull/526)) -- [Android] Fix path to React Native in `node_modules` ([PR #527](https://github.com/lelandrichardson/react-native-maps/pull/527)) -- [Android] Bump Google Play Services dependency to `9.4.0` ([PR #533](https://github.com/lelandrichardson/react-native-maps/pull/533)) -- [iOS] Fix a few warnings ([PR #534](https://github.com/lelandrichardson/react-native-maps/pull/534)) -- [JS] Fix ESLint violations ([PR #515](https://github.com/lelandrichardson/react-native-maps/pull/515)) +- [Android] Use latest available (wildcard version) of RN to build Android ([PR #547](https://github.com/airbnb/react-native-maps/pull/547)) +- [Android] Use `Activity` to call `MapsInitialier.initialize()` ([PR #449](https://github.com/airbnb/react-native-maps/pull/449)) +- [Android] Fix file path for `AirMapModule` ([PR #526](https://github.com/airbnb/react-native-maps/pull/526)) +- [Android] Fix path to React Native in `node_modules` ([PR #527](https://github.com/airbnb/react-native-maps/pull/527)) +- [Android] Bump Google Play Services dependency to `9.4.0` ([PR #533](https://github.com/airbnb/react-native-maps/pull/533)) +- [iOS] Fix a few warnings ([PR #534](https://github.com/airbnb/react-native-maps/pull/534)) +- [JS] Fix ESLint violations ([PR #515](https://github.com/airbnb/react-native-maps/pull/515)) ## 0.8.0 (August 30, 2016) ### Breaking Changes -- Upgrade to `react-native@0.32.0`, and update Android code to match ([#502](https://github.com/lelandrichardson/react-native-maps/pull/502)) +- Upgrade to `react-native@0.32.0`, and update Android code to match ([#502](https://github.com/airbnb/react-native-maps/pull/502)) ### Patches -- [android] Add `showsMyLocationButton` prop ([#382](https://github.com/lelandrichardson/react-native-maps/pull/382)) +- [android] Add `showsMyLocationButton` prop ([#382](https://github.com/airbnb/react-native-maps/pull/382)) -- Add `fitToSuppliedMarkers()` method ([#386](https://github.com/lelandrichardson/react-native-maps/pull/386)) +- Add `fitToSuppliedMarkers()` method ([#386](https://github.com/airbnb/react-native-maps/pull/386)) -- [ios] Update AirMapMarker to use loadImageWithURLRequest ([#389](https://github.com/lelandrichardson/react-native-maps/pull/389)) +- [ios] Update AirMapMarker to use loadImageWithURLRequest ([#389](https://github.com/airbnb/react-native-maps/pull/389)) -- Improvements to watch and copy script ([#445](https://github.com/lelandrichardson/react-native-maps/pull/445)) +- Improvements to watch and copy script ([#445](https://github.com/airbnb/react-native-maps/pull/445)) -- [ios] Added check on marker class in predicate ([#485](https://github.com/lelandrichardson/react-native-maps/pull/485)) +- [ios] Added check on marker class in predicate ([#485](https://github.com/airbnb/react-native-maps/pull/485)) -- Use `StyleSheet.absoluteFillObject` where appropriate ([#500](https://github.com/lelandrichardson/react-native-maps/pull/500)) and ([#493](https://github.com/lelandrichardson/react-native-maps/pull/493)) +- Use `StyleSheet.absoluteFillObject` where appropriate ([#500](https://github.com/airbnb/react-native-maps/pull/500)) and ([#493](https://github.com/airbnb/react-native-maps/pull/493)) -- Add ESLint and fix a number of linting violations ([#501](https://github.com/lelandrichardson/react-native-maps/pull/501)) +- Add ESLint and fix a number of linting violations ([#501](https://github.com/airbnb/react-native-maps/pull/501)) -- Remove unused `NativeMethodsMixin` for compat with RN 0.32 ([#511](https://github.com/lelandrichardson/react-native-maps/pull/511)) +- Remove unused `NativeMethodsMixin` for compat with RN 0.32 ([#511](https://github.com/airbnb/react-native-maps/pull/511)) ## 0.7.1 (July 9, 2016) ### Patches -- Fix iOS CocoaPods Issue ([#308](https://github.com/lelandrichardson/react-native-maps/pull/308)) +- Fix iOS CocoaPods Issue ([#308](https://github.com/airbnb/react-native-maps/pull/308)) @@ -68,18 +68,18 @@ This error is caused by a @providesModule declaration with the same name accross ### Breaking Changes -- RN 0.29 compatibility changes ([#363](https://github.com/lelandrichardson/react-native-maps/pull/363) and [#370](https://github.com/lelandrichardson/react-native-maps/pull/370)) +- RN 0.29 compatibility changes ([#363](https://github.com/airbnb/react-native-maps/pull/363) and [#370](https://github.com/airbnb/react-native-maps/pull/370)) ### Patches -- Fixing scrolling map inside a scrollView ([#343](https://github.com/lelandrichardson/react-native-maps/pull/343)) +- Fixing scrolling map inside a scrollView ([#343](https://github.com/airbnb/react-native-maps/pull/343)) -- Fix shouldUsePinView ([#344](https://github.com/lelandrichardson/react-native-maps/pull/344)) +- Fix shouldUsePinView ([#344](https://github.com/airbnb/react-native-maps/pull/344)) -- Not calling setLoadingIndicatorColor when null ([#337](https://github.com/lelandrichardson/react-native-maps/pull/337)) +- Not calling setLoadingIndicatorColor when null ([#337](https://github.com/airbnb/react-native-maps/pull/337)) -- Fixes `Undefined symbols for architecture x86_64: “std::terminate()”` ([#329](https://github.com/lelandrichardson/react-native-maps/pull/329)) +- Fixes `Undefined symbols for architecture x86_64: “std::terminate()”` ([#329](https://github.com/airbnb/react-native-maps/pull/329)) diff --git a/README.md b/README.md index 7acff192f..5fcdd8e42 100644 --- a/README.md +++ b/README.md @@ -262,7 +262,7 @@ Markers are draggable, and emit continuous drag events to update other UI during The API of this Map has been built with the intention of it being able to utilize the [Animated API](https://facebook.github.io/react-native/docs/animated.html). In order to get this to work, you will need to modify the `AnimatedImplementation.js` file in the -source of react-native with [this one](https://gist.github.com/lelandrichardson/c0d938e02301f9294465). +source of react-native with [this one](https://gist.github.com/airbnb/c0d938e02301f9294465). Ideally this will be possible in the near future without this modification. @@ -417,7 +417,7 @@ License you may not use this file except in compliance with the License. You may obtain a copy of the License at - https://raw.githubusercontent.com/lelandrichardson/react-native-maps/master/LICENSE + https://raw.githubusercontent.com/airbnb/react-native-maps/master/LICENSE Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, diff --git a/android/gradle.properties b/android/gradle.properties index c81d03497..33a00d044 100644 --- a/android/gradle.properties +++ b/android/gradle.properties @@ -3,14 +3,14 @@ VERSION_NAME=0.8.2 GROUP=com.airbnb.android POM_DESCRIPTION=React Native Map view component for Android -POM_URL=https://github.com/lelandrichardson/react-native-maps/tree/new-scv -POM_SCM_URL=https://github.com/lelandrichardson/react-native-maps/tree/new-scv -POM_SCM_CONNECTION=scm:git@github.com:lelandrichardson/react-native-maps.git -POM_SCM_DEV_CONNECTION=scm:git@github.com:lelandrichardson/react-native-maps.git +POM_URL=https://github.com/airbnb/react-native-maps/tree/new-scv +POM_SCM_URL=https://github.com/airbnb/react-native-maps/tree/new-scv +POM_SCM_CONNECTION=scm:git@github.com:airbnb/react-native-maps.git +POM_SCM_DEV_CONNECTION=scm:git@github.com:airbnb/react-native-maps.git POM_LICENSE_NAME=MIT -POM_LICENSE_URL=https://github.com/lelandrichardson/react-native-maps/blob/master/LICENSE +POM_LICENSE_URL=https://github.com/airbnb/react-native-maps/blob/master/LICENSE POM_LICENSE_DIST=repo -POM_DEVELOPER_ID=lelandrichardson +POM_DEVELOPER_ID=airbnb POM_DEVELOPER_NAME=Leland Richardson POM_NAME=ReactNative Maps library diff --git a/docs/installation.md b/docs/installation.md index 928c0a735..13f170750 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -133,7 +133,7 @@ Add your **Android** API key to your manifest file: **Troubleshooting** -If you have a blank map issue, ([#118](https://github.com/lelandrichardson/react-native-maps/issues/118), [#176](https://github.com/lelandrichardson/react-native-maps/issues/176)) try the following lines : +If you have a blank map issue, ([#118](https://github.com/airbnb/react-native-maps/issues/118), [#176](https://github.com/airbnb/react-native-maps/issues/176)) try the following lines : **On iOS :** diff --git a/package.json b/package.json index 2025e7b2f..df61e0a0b 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,7 @@ }, "repository": { "type": "git", - "url": "https://github.com/lelandrichardson/react-native-maps" + "url": "https://github.com/airbnb/react-native-maps" }, "keywords": [ "react", diff --git a/react-native-maps.podspec b/react-native-maps.podspec index 148329e12..ddbf4f4f4 100644 --- a/react-native-maps.podspec +++ b/react-native-maps.podspec @@ -4,11 +4,11 @@ Pod::Spec.new do |s| s.summary = "React Native Mapview component for iOS + Android" s.authors = { "intelligibabble" => "leland.m.richardson@gmail.com" } - s.homepage = "https://github.com/lelandrichardson/react-native-maps#readme" + s.homepage = "https://github.com/airbnb/react-native-maps#readme" s.license = "MIT" s.platform = :ios, "8.0" - s.source = { :git => "https://github.com/lelandrichardson/react-native-maps.git" } + s.source = { :git => "https://github.com/airbnb/react-native-maps.git" } s.source_files = "ios/AirMaps/**/*.{h,m}" s.dependency 'React' From 3e5c5715cced64f07c9167f55827a1555babefa0 Mon Sep 17 00:00:00 2001 From: Spike Brehm Date: Tue, 13 Sep 2016 10:11:05 -0700 Subject: [PATCH 0059/1148] Change back the gist.github.com link to lelandrichardson --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5fcdd8e42..fe1f9a87a 100644 --- a/README.md +++ b/README.md @@ -262,7 +262,7 @@ Markers are draggable, and emit continuous drag events to update other UI during The API of this Map has been built with the intention of it being able to utilize the [Animated API](https://facebook.github.io/react-native/docs/animated.html). In order to get this to work, you will need to modify the `AnimatedImplementation.js` file in the -source of react-native with [this one](https://gist.github.com/airbnb/c0d938e02301f9294465). +source of react-native with [this one](https://gist.github.com/lelandrichardson/c0d938e02301f9294465). Ideally this will be possible in the near future without this modification. From c8ea624e4a9b4fa00c4402186a596728a7d7e0f9 Mon Sep 17 00:00:00 2001 From: Daniele Rossetti Date: Sat, 17 Sep 2016 16:01:46 +0100 Subject: [PATCH 0060/1148] Adding support for Android lite mode --- README.md | 5 ++ .../android/react/maps/AirMapLiteManager.java | 20 +++++++ .../android/react/maps/AirMapManager.java | 6 ++- .../airbnb/android/react/maps/AirMapView.java | 6 ++- .../android/react/maps/MapsPackage.java | 4 +- components/MapView.js | 25 +++++++++ docs/mapview.md | 1 + example/App.js | 2 + example/examples/LiteMapView.js | 53 +++++++++++++++++++ 9 files changed, 118 insertions(+), 4 deletions(-) create mode 100644 android/src/main/java/com/airbnb/android/react/maps/AirMapLiteManager.java create mode 100644 example/examples/LiteMapView.js diff --git a/README.md b/README.md index fe1f9a87a..40519bb5b 100644 --- a/README.md +++ b/README.md @@ -240,6 +240,11 @@ Markers are draggable, and emit continuous drag events to update other UI during ![](http://i.giphy.com/l2JImnZxdv1WbpQfC.gif) ![](http://i.giphy.com/l2JIhv4Jx6Ugx1EGI.gif) +### Lite Mode ( Android ) + +Enable lite mode on Android with `liteMode` prop. Ideal when having multiple maps in a View or ScrollView. + +![](http://i.giphy.com/qZ2lAf18s89na.gif) ## Component API diff --git a/android/src/main/java/com/airbnb/android/react/maps/AirMapLiteManager.java b/android/src/main/java/com/airbnb/android/react/maps/AirMapLiteManager.java new file mode 100644 index 000000000..62495c5e4 --- /dev/null +++ b/android/src/main/java/com/airbnb/android/react/maps/AirMapLiteManager.java @@ -0,0 +1,20 @@ +package com.airbnb.android.react.maps; + +import com.facebook.react.bridge.ReactApplicationContext; +import com.google.android.gms.maps.GoogleMapOptions; + +public class AirMapLiteManager extends AirMapManager { + + private static final String REACT_CLASS = "AIRMapLite"; + + @Override + public String getName() { + return REACT_CLASS; + } + + public AirMapLiteManager(ReactApplicationContext context) { + super(context); + this.googleMapOptions = new GoogleMapOptions().liteMode(true); + } + +} diff --git a/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java b/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java index 876495d19..11d06a592 100644 --- a/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java +++ b/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java @@ -16,6 +16,7 @@ import com.facebook.react.uimanager.annotations.ReactProp; import com.facebook.react.uimanager.events.RCTEventEmitter; import com.google.android.gms.maps.GoogleMap; +import com.google.android.gms.maps.GoogleMapOptions; import com.google.android.gms.maps.MapsInitializer; import com.google.android.gms.maps.model.LatLng; import com.google.android.gms.maps.model.LatLngBounds; @@ -43,8 +44,11 @@ public class AirMapManager extends ViewGroupManager { private final ReactApplicationContext appContext; + protected GoogleMapOptions googleMapOptions; + public AirMapManager(ReactApplicationContext context) { this.appContext = context; + this.googleMapOptions = new GoogleMapOptions(); } @Override @@ -63,7 +67,7 @@ protected AirMapView createViewInstance(ThemedReactContext context) { emitMapError("Map initialize error", "map_init_error"); } - return new AirMapView(context, this.appContext, this); + return new AirMapView(context, this.appContext, this, this.googleMapOptions); } @Override diff --git a/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java b/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java index 0ed717207..4c2c00563 100644 --- a/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java +++ b/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java @@ -31,6 +31,7 @@ import com.google.android.gms.maps.CameraUpdate; import com.google.android.gms.maps.CameraUpdateFactory; import com.google.android.gms.maps.GoogleMap; +import com.google.android.gms.maps.GoogleMapOptions; import com.google.android.gms.maps.MapView; import com.google.android.gms.maps.OnMapReadyCallback; import com.google.android.gms.maps.Projection; @@ -76,8 +77,9 @@ public class AirMapView extends MapView implements GoogleMap.InfoWindowAdapter, private final ThemedReactContext context; private final EventDispatcher eventDispatcher; - public AirMapView(ThemedReactContext context, Context appContext, AirMapManager manager) { - super(appContext); + public AirMapView(ThemedReactContext context, Context appContext, AirMapManager manager, GoogleMapOptions googleMapOptions) { + super(appContext, googleMapOptions); + this.manager = manager; this.context = context; diff --git a/android/src/main/java/com/airbnb/android/react/maps/MapsPackage.java b/android/src/main/java/com/airbnb/android/react/maps/MapsPackage.java index 6b910d7a3..e08879e57 100644 --- a/android/src/main/java/com/airbnb/android/react/maps/MapsPackage.java +++ b/android/src/main/java/com/airbnb/android/react/maps/MapsPackage.java @@ -37,6 +37,7 @@ public List createViewManagers(ReactApplicationContext reactContext AirMapPolygonManager polygonManager = new AirMapPolygonManager(reactContext); AirMapCircleManager circleManager = new AirMapCircleManager(reactContext); AirMapManager mapManager = new AirMapManager(reactContext); + AirMapLiteManager mapLiteManager = new AirMapLiteManager(reactContext); return Arrays.asList( calloutManager, @@ -44,6 +45,7 @@ public List createViewManagers(ReactApplicationContext reactContext polylineManager, polygonManager, circleManager, - mapManager); + mapManager, + mapLiteManager); } } diff --git a/components/MapView.js b/components/MapView.js index 5bbaea374..860c25e6d 100644 --- a/components/MapView.js +++ b/components/MapView.js @@ -222,6 +222,14 @@ const propTypes = { longitudeDelta: PropTypes.number.isRequired, }), + /** + * A Boolean indicating whether to use liteMode for android + * Default value is `false` + * + * @platform android + */ + liteMode: PropTypes.bool, + /** * Maximum size of area that can be displayed. * @@ -457,6 +465,15 @@ class MapView extends React.Component { }; } + if (Platform.OS === 'android' && this.props.liteMode) { + return ( + { this.map = ref; }} + {...props} + /> + ); + } + return ( { this.map = ref; }} @@ -477,6 +494,14 @@ const AIRMap = requireNativeComponent('AIRMap', MapView, { }, }); +const AIRMapLite = requireNativeComponent('AIRMapLite', MapView, { + nativeOnly: { + onChange: true, + onMapReady: true, + handlePanDrag: true, + }, +}); + MapView.Marker = MapMarker; MapView.Polyline = MapPolyline; MapView.Polygon = MapPolygon; diff --git a/docs/mapview.md b/docs/mapview.md index 90c26684f..12ba14fb9 100644 --- a/docs/mapview.md +++ b/docs/mapview.md @@ -6,6 +6,7 @@ |---|---|---|---| | `region` | `Region` | | The region to be displayed by the map.

The region is defined by the center coordinates and the span of coordinates to display. | `initialRegion` | `Region` | | The initial region to be displayed by the map. Use this prop instead of `region` only if you don't want to control the viewport of the map besides the initial region.

Changing this prop after the component has mounted will not result in a region change.

This is similar to the `initialValue` prop of a text input. +| `liteMode` | `Boolean` | `false` | Enable lite mode. **Note**: Android only. | `mapType` | `String` | `"standard"` | The map type to be displayed.

- standard: standard road map (default)
- satellite: satellite view
- hybrid: satellite view with roads and points of interest overlayed
- terrain: (Android only) topographic view | `showsUserLocation` | `Boolean` | `false` | If `true` the app will ask for the user's location. **NOTE**: You need to add `NSLocationWhenInUseUsageDescription` key in Info.plist to enable geolocation, otherwise it is going to *fail silently*! | `followsUserLocation` | `Boolean` | `false` | If `true` the map will focus on the user's location. This only works if `showsUserLocation` is true and the user has shared their location. **Note**: iOS only. diff --git a/example/App.js b/example/App.js index be1816f35..49ac10ea5 100644 --- a/example/App.js +++ b/example/App.js @@ -23,6 +23,7 @@ import CachedMap from './examples/CachedMap'; import LoadingMap from './examples/LoadingMap'; import TakeSnapshot from './examples/TakeSnapshot'; import FitToSuppliedMarkers from './examples/FitToSuppliedMarkers'; +import LiteMapView from './examples/LiteMapView'; class App extends React.Component { constructor(props) { @@ -93,6 +94,7 @@ class App extends React.Component { [CachedMap, 'Cached Map'], [LoadingMap, 'Map with loading'], [FitToSuppliedMarkers, 'Focus Map On Markers'], + [LiteMapView, 'Android Lite MapView'], ]); } } diff --git a/example/examples/LiteMapView.js b/example/examples/LiteMapView.js new file mode 100644 index 000000000..7f65fb6c9 --- /dev/null +++ b/example/examples/LiteMapView.js @@ -0,0 +1,53 @@ +import React from 'react'; +import { + StyleSheet, + Dimensions, + ScrollView, +} from 'react-native'; + +import MapView from 'react-native-maps'; + +const { width, height } = Dimensions.get('window'); + +const ASPECT_RATIO = width / height; +const LATITUDE = 37.78825; +const LONGITUDE = -122.4324; +const LATITUDE_DELTA = 0.0922; +const LONGITUDE_DELTA = LATITUDE_DELTA * ASPECT_RATIO; + +const SAMPLE_REGION = { + latitude: LATITUDE, + longitude: LONGITUDE, + latitudeDelta: LATITUDE_DELTA, + longitudeDelta: LONGITUDE_DELTA, +}; + +class LiteMapView extends React.Component { + render() { + const maps = []; + for (let i = 0; i < 10; i++) { + maps.push( + + ); + } + return ( + + {maps} + + ); + } +} + +const styles = StyleSheet.create({ + map: { + height: 200, + marginVertical: 50, + }, +}); + +module.exports = LiteMapView; From f09fb25a04627df622e70aee1eded31dd82c49b4 Mon Sep 17 00:00:00 2001 From: Alastairm Date: Sun, 18 Sep 2016 15:40:31 +0800 Subject: [PATCH 0061/1148] Updated Mapview onRegionChange events notes Clarified the difference between onRegionChange and onRegionChange notes for each match comments in MapView.js --- docs/mapview.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/mapview.md b/docs/mapview.md index 90c26684f..8c90e3dd1 100644 --- a/docs/mapview.md +++ b/docs/mapview.md @@ -32,8 +32,8 @@ | Event Name | Returns | Notes |---|---|---| -| `onRegionChange` | `Region` | Fired when the map ends panning or zooming. -| `onRegionChangeComplete` | `Region` | Fired when the map ends panning or zooming. +| `onRegionChange` | `Region` | Callback that is called continuously when the user is dragging the map. +| `onRegionChangeComplete` | `Region` | Callback that is called once, when the user is done moving the map. | `onPress` | `{ coordinate: LatLng, position: Point }` | Callback that is called when user taps on the map. | `onPanDrag` | `{ coordinate: LatLng, position: Point }` | Callback that is called when user presses and drags the map. **NOTE**: for iOS `scrollEnabled` should be set to false to trigger the event | `onLongPress` | `{ coordinate: LatLng, position: Point }` | Callback that is called when user makes a "long press" somewhere on the map. From 902d6eed05ac5b8d9a5e8a770725dd23ddc7c611 Mon Sep 17 00:00:00 2001 From: cascadian Date: Fri, 18 Mar 2016 13:41:39 -0700 Subject: [PATCH 0062/1148] initial support for tile overlays --- .../main/java/com/AirMaps/AirMapUrlTile.java | 98 +++++++++++++++++++ .../com/AirMaps/AirMapUrlTileManager.java | 51 ++++++++++ .../android/react/maps/AirMapManager.java | 3 +- .../airbnb/android/react/maps/AirMapView.java | 13 +++ .../android/react/maps/MapsPackage.java | 4 +- components/MapUrlTile.js | 43 ++++++++ components/MapView.js | 4 + 7 files changed, 214 insertions(+), 2 deletions(-) create mode 100644 android/src/main/java/com/AirMaps/AirMapUrlTile.java create mode 100644 android/src/main/java/com/AirMaps/AirMapUrlTileManager.java create mode 100644 components/MapUrlTile.js diff --git a/android/src/main/java/com/AirMaps/AirMapUrlTile.java b/android/src/main/java/com/AirMaps/AirMapUrlTile.java new file mode 100644 index 000000000..596fabaf9 --- /dev/null +++ b/android/src/main/java/com/AirMaps/AirMapUrlTile.java @@ -0,0 +1,98 @@ +package com.AirMaps; + +import android.content.Context; + +import com.google.android.gms.maps.GoogleMap; +import com.google.android.gms.maps.model.TileOverlay; +import com.google.android.gms.maps.model.TileOverlayOptions; +import com.google.android.gms.maps.model.UrlTileProvider; + +import java.net.MalformedURLException; +import java.net.URL; +import java.util.Locale; + +public class AirMapUrlTile extends AirMapFeature { + + class AIRMapUrlTileProvider extends UrlTileProvider + { + private String url; + public AIRMapUrlTileProvider(int width, int height, String url) { + super(width, height); + this.url = url; + } + @Override + public synchronized URL getTileUrl(int x, int y, int zoom) { + + String s = String.format(Locale.US, this.url, zoom, x, y); + URL url = null; + try { + url = new URL(s); + } catch (MalformedURLException e) { + throw new AssertionError(e); + } + return url; + } + + public void setUrl(String url) { + this.url = url; + } + } + + private TileOverlayOptions tileOverlayOptions; + private TileOverlay tileOverlay; + private AIRMapUrlTileProvider tileProvider; + + private String url; + private float zIndex; + + public AirMapUrlTile(Context context) { + super(context); + } + + public void setUrl(String url) { + this.url = url; + if (tileProvider != null) { + tileProvider.setUrl(url); + } + if (tileOverlay != null) { + tileOverlay.clearTileCache(); + } + } + + public void setZIndex(float zIndex) { + this.zIndex = zIndex; + if (tileOverlay != null) { + tileOverlay.setZIndex(zIndex); + } + } + + public TileOverlayOptions getTileOverlayOptions() { + if (tileOverlayOptions == null) { + tileOverlayOptions = createTileOverlayOptions(); + } + return tileOverlayOptions; + } +// http://a.tile.openstreetmap.org/${z}/${x}/${y}.png + private TileOverlayOptions createTileOverlayOptions() { + TileOverlayOptions options = new TileOverlayOptions(); + options.zIndex(zIndex); + this.tileProvider = new AIRMapUrlTileProvider(256, 256, this.url); + options.tileProvider(this.tileProvider); + return options; + } + + @Override + public Object getFeature() { + return tileOverlay; + } + + @Override + public void addToMap(GoogleMap map) { + this.tileOverlay = map.addTileOverlay(getTileOverlayOptions()); + } + + @Override + public void removeFromMap(GoogleMap map) { + tileOverlay.remove(); + } +} diff --git a/android/src/main/java/com/AirMaps/AirMapUrlTileManager.java b/android/src/main/java/com/AirMaps/AirMapUrlTileManager.java new file mode 100644 index 000000000..a3ad8163f --- /dev/null +++ b/android/src/main/java/com/AirMaps/AirMapUrlTileManager.java @@ -0,0 +1,51 @@ +package com.AirMaps; + +import android.content.Context; +import android.graphics.Color; +import android.os.Build; +import android.util.DisplayMetrics; +import android.view.WindowManager; + +import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.bridge.ReadableMap; +import com.facebook.react.uimanager.annotations.ReactProp; +import com.facebook.react.uimanager.ThemedReactContext; +import com.facebook.react.uimanager.ViewGroupManager; +import com.google.android.gms.maps.model.LatLng; + +public class AirMapUrlTileManager extends ViewGroupManager { + private DisplayMetrics metrics; + + public AirMapUrlTileManager(ReactApplicationContext reactContext) { + super(); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { + metrics = new DisplayMetrics(); + ((WindowManager) reactContext.getSystemService(Context.WINDOW_SERVICE)) + .getDefaultDisplay() + .getRealMetrics(metrics); + } else { + metrics = reactContext.getResources().getDisplayMetrics(); + } + } + + @Override + public String getName() { + return "AIRMapUrlTile"; + } + + @Override + public AirMapUrlTile createViewInstance(ThemedReactContext context) { + return new AirMapUrlTile(context); + } + + @ReactProp(name = "url") + public void setCenter(AirMapUrlTile view, String url) { + view.setUrl(url); + } + + @ReactProp(name = "zIndex", defaultFloat = 1.0f) + public void setZIndex(AirMapUrlTile view, float zIndex) { + view.setZIndex(zIndex); + } + +} diff --git a/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java b/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java index 11d06a592..b91fa814c 100644 --- a/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java +++ b/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java @@ -37,7 +37,8 @@ public class AirMapManager extends ViewGroupManager { "standard", GoogleMap.MAP_TYPE_NORMAL, "satellite", GoogleMap.MAP_TYPE_SATELLITE, "hybrid", GoogleMap.MAP_TYPE_HYBRID, - "terrain", GoogleMap.MAP_TYPE_TERRAIN + "terrain", GoogleMap.MAP_TYPE_TERRAIN, + "none", GoogleMap.MAP_TYPE_NONE ); private ReactContext reactContext; diff --git a/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java b/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java index 4c2c00563..a772aeff2 100644 --- a/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java +++ b/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java @@ -39,6 +39,7 @@ import com.google.android.gms.maps.model.LatLng; import com.google.android.gms.maps.model.LatLngBounds; import com.google.android.gms.maps.model.Marker; +import com.google.android.gms.maps.model.TileOverlay; import java.util.ArrayList; import java.util.Arrays; @@ -67,6 +68,8 @@ public class AirMapView extends MapView implements GoogleMap.InfoWindowAdapter, private static final String[] PERMISSIONS = new String[] { "android.permission.ACCESS_FINE_LOCATION", "android.permission.ACCESS_COARSE_LOCATION"}; + // TODO: don't need tileMap at all??? + private HashMap tileMap = new HashMap<>(); private final List features = new ArrayList<>(); private final Map markerMap = new HashMap<>(); private final ScaleGestureDetector scaleDetector; @@ -393,6 +396,13 @@ public void addFeature(View child, int index) { AirMapCircle circleView = (AirMapCircle) child; circleView.addToMap(map); features.add(index, circleView); + } else if (child instanceof AirMapUrlTile) { + AirMapUrlTile urlTileView = (AirMapUrlTile) child; + urlTileView.addToMap(map); + features.add(index, urlTileView); + TileOverlay tile = (TileOverlay)urlTileView.getFeature(); + // TODO: don't need tileMap at all??? + tileMap.put(tile, urlTileView); } else { // TODO(lmr): throw? User shouldn't be adding non-feature children. } @@ -410,6 +420,9 @@ public void removeFeatureAt(int index) { AirMapFeature feature = features.remove(index); if (feature instanceof AirMapMarker) { markerMap.remove(feature.getFeature()); + } else if (feature instanceof AirMapUrlTile) { + // TODO: don't need tileMap at all??? + tileMap.remove(feature.getFeature()); } feature.removeFromMap(map); } diff --git a/android/src/main/java/com/airbnb/android/react/maps/MapsPackage.java b/android/src/main/java/com/airbnb/android/react/maps/MapsPackage.java index e08879e57..5480c16ab 100644 --- a/android/src/main/java/com/airbnb/android/react/maps/MapsPackage.java +++ b/android/src/main/java/com/airbnb/android/react/maps/MapsPackage.java @@ -38,6 +38,7 @@ public List createViewManagers(ReactApplicationContext reactContext AirMapCircleManager circleManager = new AirMapCircleManager(reactContext); AirMapManager mapManager = new AirMapManager(reactContext); AirMapLiteManager mapLiteManager = new AirMapLiteManager(reactContext); + AirMapUrlTileManager tileManager = new AirMapUrlTileManager(reactContext); return Arrays.asList( calloutManager, @@ -46,6 +47,7 @@ public List createViewManagers(ReactApplicationContext reactContext polygonManager, circleManager, mapManager, - mapLiteManager); + mapLiteManager, + tileManager); } } diff --git a/components/MapUrlTile.js b/components/MapUrlTile.js new file mode 100644 index 000000000..9bc0428ec --- /dev/null +++ b/components/MapUrlTile.js @@ -0,0 +1,43 @@ + +var React = require('react-native'); +var { + View, + NativeMethodsMixin, + requireNativeComponent, + StyleSheet, + PropTypes, +} = React; + +var MapUrlTile = React.createClass({ + mixins: [NativeMethodsMixin], + + propTypes: { + ...View.propTypes, + + /** + * The radius of the UrlTile to be drawn (in meters) + */ + url: PropTypes.string.isRequired, + + /** + * The order in which this tile overlay is drawn with respect to other overlays. An overlay + * with a larger z-index is drawn over overlays with smaller z-indices. The order of overlays + * with the same z-index is arbitrary. The default zIndex is 0. + * + * @platform android + */ + zIndex: PropTypes.number, + }, + + render: function() { + return ( + + ); + }, +}); + +var AIRMapUrlTile = requireNativeComponent('AIRMapUrlTile', MapUrlTile); + +module.exports = MapUrlTile; diff --git a/components/MapView.js b/components/MapView.js index 860c25e6d..a55d4d726 100644 --- a/components/MapView.js +++ b/components/MapView.js @@ -6,6 +6,7 @@ import { Animated, requireNativeComponent, NativeModules, +<<<<<<< 70a6c8a927b90df86e7092acc6e026df1a58331c ColorPropType, findNodeHandle, } from 'react-native'; @@ -14,6 +15,7 @@ import MapPolyline from './MapPolyline'; import MapPolygon from './MapPolygon'; import MapCircle from './MapCircle'; import MapCallout from './MapCallout'; +import MapUrlTile './MapUrlTile'; const viewConfig = { uiViewClassName: 'AIRMap', @@ -176,6 +178,7 @@ const propTypes = { 'satellite', 'hybrid', 'terrain', + 'none', ]), /** @@ -506,6 +509,7 @@ MapView.Marker = MapMarker; MapView.Polyline = MapPolyline; MapView.Polygon = MapPolygon; MapView.Circle = MapCircle; +MapView.UrlTile = MapUrlTile; MapView.Callout = MapCallout; MapView.Animated = Animated.createAnimatedComponent(MapView); From 2855d8a6f293de925ec7ebe5119579b3af3eded8 Mon Sep 17 00:00:00 2001 From: cascadian Date: Fri, 18 Mar 2016 15:39:52 -0700 Subject: [PATCH 0063/1148] changed url template to use {x} {y} {z} pattern replacement --- .../main/java/com/AirMaps/AirMapUrlTile.java | 7 +- .../com/AirMaps/AirMapUrlTileManager.java | 2 +- components/MapUrlTile.js | 5 +- example/App.js | 2 + example/examples/CustomTiles.js | 100 ++++++++++++++++++ 5 files changed, 111 insertions(+), 5 deletions(-) create mode 100644 example/examples/CustomTiles.js diff --git a/android/src/main/java/com/AirMaps/AirMapUrlTile.java b/android/src/main/java/com/AirMaps/AirMapUrlTile.java index 596fabaf9..5eb26f9b7 100644 --- a/android/src/main/java/com/AirMaps/AirMapUrlTile.java +++ b/android/src/main/java/com/AirMaps/AirMapUrlTile.java @@ -23,7 +23,10 @@ public AIRMapUrlTileProvider(int width, int height, String url) { @Override public synchronized URL getTileUrl(int x, int y, int zoom) { - String s = String.format(Locale.US, this.url, zoom, x, y); + String s = this.url + .replace("{x}", Integer.toString(x)) + .replace("{y}", Integer.toString(y)) + .replace("{z}", Integer.toString(zoom)); URL url = null; try { url = new URL(s); @@ -72,7 +75,7 @@ public TileOverlayOptions getTileOverlayOptions() { } return tileOverlayOptions; } -// http://a.tile.openstreetmap.org/${z}/${x}/${y}.png + private TileOverlayOptions createTileOverlayOptions() { TileOverlayOptions options = new TileOverlayOptions(); options.zIndex(zIndex); diff --git a/android/src/main/java/com/AirMaps/AirMapUrlTileManager.java b/android/src/main/java/com/AirMaps/AirMapUrlTileManager.java index a3ad8163f..8cba82b82 100644 --- a/android/src/main/java/com/AirMaps/AirMapUrlTileManager.java +++ b/android/src/main/java/com/AirMaps/AirMapUrlTileManager.java @@ -43,7 +43,7 @@ public void setCenter(AirMapUrlTile view, String url) { view.setUrl(url); } - @ReactProp(name = "zIndex", defaultFloat = 1.0f) + @ReactProp(name = "zIndex", defaultFloat = -1.0f) public void setZIndex(AirMapUrlTile view, float zIndex) { view.setZIndex(zIndex); } diff --git a/components/MapUrlTile.js b/components/MapUrlTile.js index 9bc0428ec..7d1dc1cce 100644 --- a/components/MapUrlTile.js +++ b/components/MapUrlTile.js @@ -15,14 +15,15 @@ var MapUrlTile = React.createClass({ ...View.propTypes, /** - * The radius of the UrlTile to be drawn (in meters) + * The url template of the tile server. The patterns {x} {y} {z} will be replaced at runtime + * For example, http://c.tile.openstreetmap.org/{z}/{x}/{y}.png */ url: PropTypes.string.isRequired, /** * The order in which this tile overlay is drawn with respect to other overlays. An overlay * with a larger z-index is drawn over overlays with smaller z-indices. The order of overlays - * with the same z-index is arbitrary. The default zIndex is 0. + * with the same z-index is arbitrary. The default zIndex is -1. * * @platform android */ diff --git a/example/App.js b/example/App.js index 49ac10ea5..d21ef0d4f 100644 --- a/example/App.js +++ b/example/App.js @@ -24,6 +24,7 @@ import LoadingMap from './examples/LoadingMap'; import TakeSnapshot from './examples/TakeSnapshot'; import FitToSuppliedMarkers from './examples/FitToSuppliedMarkers'; import LiteMapView from './examples/LiteMapView'; +import CustomTiles from './examples/CustomTiles'; class App extends React.Component { constructor(props) { @@ -95,6 +96,7 @@ class App extends React.Component { [LoadingMap, 'Map with loading'], [FitToSuppliedMarkers, 'Focus Map On Markers'], [LiteMapView, 'Android Lite MapView'], + [CustomTiles, 'Custom Tiles'], ]); } } diff --git a/example/examples/CustomTiles.js b/example/examples/CustomTiles.js new file mode 100644 index 000000000..6ac69bf87 --- /dev/null +++ b/example/examples/CustomTiles.js @@ -0,0 +1,100 @@ +var React = require('react-native'); +var { + StyleSheet, + PropTypes, + View, + Text, + Dimensions, + TouchableOpacity, + Image, + } = React; + +var MapView = require('react-native-maps'); + +var { width, height } = Dimensions.get('window'); + +const ASPECT_RATIO = width / height; +const LATITUDE = 37.78825; +const LONGITUDE = -122.4324; +const LATITUDE_DELTA = 0.0922; +const LONGITUDE_DELTA = LATITUDE_DELTA * ASPECT_RATIO; +const SPACE = 0.01; + +var Overlays = React.createClass({ + getInitialState() { + return { + region: { + latitude: LATITUDE, + longitude: LONGITUDE, + latitudeDelta: LATITUDE_DELTA, + longitudeDelta: LONGITUDE_DELTA, + }, + }; + }, + + render() { + const { region, circle, polygon, polyline } = this.state; + return ( + + + + + + + Custom Tiles + + + + ); + }, +}); + +var styles = StyleSheet.create({ + container: { + position: 'absolute', + top: 0, + left: 0, + right: 0, + bottom: 0, + justifyContent: 'flex-end', + alignItems: 'center', + }, + map: { + position: 'absolute', + top: 0, + left: 0, + right: 0, + bottom: 0, + }, + bubble: { + flex: 1, + backgroundColor: 'rgba(255,255,255,0.7)', + paddingHorizontal: 18, + paddingVertical: 12, + borderRadius: 20, + }, + latlng: { + width: 200, + alignItems: 'stretch', + }, + button: { + width: 80, + paddingHorizontal: 12, + alignItems: 'center', + marginHorizontal: 10, + }, + buttonContainer: { + flexDirection: 'row', + marginVertical: 20, + backgroundColor: 'transparent', + }, +}); + +module.exports = Overlays; From 2adea8c8f96409bef859bf63d6c796e779577c29 Mon Sep 17 00:00:00 2001 From: Paul Currit Date: Sat, 19 Mar 2016 20:24:32 -0700 Subject: [PATCH 0064/1148] added support for tile overlays (MKTileOverlay) --- components/MapUrlTile.js | 2 +- ios/AirMaps.xcodeproj/project.pbxproj | 14 ++++++- ios/AirMaps/AIRMap.m | 5 +++ ios/AirMaps/AIRMapManager.m | 3 ++ ios/AirMaps/AIRMapUrlTile.h | 35 ++++++++++++++++ ios/AirMaps/AIRMapUrlTile.m | 58 +++++++++++++++++++++++++++ ios/AirMaps/AIRMapUrlTileManager.h | 14 +++++++ ios/AirMaps/AIRMapUrlTileManager.m | 38 ++++++++++++++++++ 8 files changed, 167 insertions(+), 2 deletions(-) create mode 100644 ios/AirMaps/AIRMapUrlTile.h create mode 100644 ios/AirMaps/AIRMapUrlTile.m create mode 100644 ios/AirMaps/AIRMapUrlTileManager.h create mode 100644 ios/AirMaps/AIRMapUrlTileManager.m diff --git a/components/MapUrlTile.js b/components/MapUrlTile.js index 7d1dc1cce..09f3c7fe2 100644 --- a/components/MapUrlTile.js +++ b/components/MapUrlTile.js @@ -18,7 +18,7 @@ var MapUrlTile = React.createClass({ * The url template of the tile server. The patterns {x} {y} {z} will be replaced at runtime * For example, http://c.tile.openstreetmap.org/{z}/{x}/{y}.png */ - url: PropTypes.string.isRequired, + urlTemplate: PropTypes.string.isRequired, /** * The order in which this tile overlay is drawn with respect to other overlays. An overlay diff --git a/ios/AirMaps.xcodeproj/project.pbxproj b/ios/AirMaps.xcodeproj/project.pbxproj index a8d5d6e5e..56d021703 100644 --- a/ios/AirMaps.xcodeproj/project.pbxproj +++ b/ios/AirMaps.xcodeproj/project.pbxproj @@ -22,6 +22,8 @@ 1125B2E61C4AD3DA007D0023 /* AIRMapPolylineManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 1125B2D61C4AD3DA007D0023 /* AIRMapPolylineManager.m */; }; 1125B2E71C4AD3DA007D0023 /* RCTConvert+MoreMapKit.m in Sources */ = {isa = PBXBuildFile; fileRef = 1125B2D91C4AD3DA007D0023 /* RCTConvert+MoreMapKit.m */; }; 1125B2F21C4AD445007D0023 /* SMCalloutView.m in Sources */ = {isa = PBXBuildFile; fileRef = 1125B2F11C4AD445007D0023 /* SMCalloutView.m */; }; + DA6C26381C9E2AFE0035349F /* AIRMapUrlTile.m in Sources */ = {isa = PBXBuildFile; fileRef = DA6C26371C9E2AFE0035349F /* AIRMapUrlTile.m */; settings = {ASSET_TAGS = (); }; }; + DA6C263E1C9E324A0035349F /* AIRMapUrlTileManager.m in Sources */ = {isa = PBXBuildFile; fileRef = DA6C263D1C9E324A0035349F /* AIRMapUrlTileManager.m */; settings = {ASSET_TAGS = (); }; }; /* End PBXBuildFile section */ /* Begin PBXCopyFilesBuildPhase section */ @@ -68,6 +70,10 @@ 1125B2F01C4AD445007D0023 /* SMCalloutView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SMCalloutView.h; path = AirMaps/Callout/SMCalloutView.h; sourceTree = SOURCE_ROOT; }; 1125B2F11C4AD445007D0023 /* SMCalloutView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SMCalloutView.m; path = AirMaps/Callout/SMCalloutView.m; sourceTree = SOURCE_ROOT; }; 11FA5C511C4A1296003AC2EE /* libAirMaps.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libAirMaps.a; sourceTree = BUILT_PRODUCTS_DIR; }; + DA6C26361C9E2AFE0035349F /* AIRMapUrlTile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRMapUrlTile.h; sourceTree = ""; }; + DA6C26371C9E2AFE0035349F /* AIRMapUrlTile.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRMapUrlTile.m; sourceTree = ""; }; + DA6C263C1C9E324A0035349F /* AIRMapUrlTileManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRMapUrlTileManager.h; sourceTree = ""; }; + DA6C263D1C9E324A0035349F /* AIRMapUrlTileManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRMapUrlTileManager.m; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -110,6 +116,7 @@ 1125B2C41C4AD3DA007D0023 /* AIRMapCircle.m */, 1125B2C51C4AD3DA007D0023 /* AIRMapCircleManager.h */, 1125B2C61C4AD3DA007D0023 /* AIRMapCircleManager.m */, + 1125B2D41C4AD3DA007D0023 /* AIRMapPolyline.m */, 1125B2C71C4AD3DA007D0023 /* AIRMapCoordinate.h */, 1125B2C81C4AD3DA007D0023 /* AIRMapCoordinate.m */, 1125B2C91C4AD3DA007D0023 /* AIRMapManager.h */, @@ -123,13 +130,16 @@ 1125B2D11C4AD3DA007D0023 /* AIRMapPolygonManager.h */, 1125B2D21C4AD3DA007D0023 /* AIRMapPolygonManager.m */, 1125B2D31C4AD3DA007D0023 /* AIRMapPolyline.h */, - 1125B2D41C4AD3DA007D0023 /* AIRMapPolyline.m */, 1125B2D51C4AD3DA007D0023 /* AIRMapPolylineManager.h */, 1125B2D61C4AD3DA007D0023 /* AIRMapPolylineManager.m */, 1125B2F01C4AD445007D0023 /* SMCalloutView.h */, 1125B2F11C4AD445007D0023 /* SMCalloutView.m */, 1125B2D81C4AD3DA007D0023 /* RCTConvert+MoreMapKit.h */, 1125B2D91C4AD3DA007D0023 /* RCTConvert+MoreMapKit.m */, + DA6C26361C9E2AFE0035349F /* AIRMapUrlTile.h */, + DA6C26371C9E2AFE0035349F /* AIRMapUrlTile.m */, + DA6C263C1C9E324A0035349F /* AIRMapUrlTileManager.h */, + DA6C263D1C9E324A0035349F /* AIRMapUrlTileManager.m */, ); path = AirMaps; sourceTree = ""; @@ -197,12 +207,14 @@ 1125B2E61C4AD3DA007D0023 /* AIRMapPolylineManager.m in Sources */, 1125B2DD1C4AD3DA007D0023 /* AIRMapCircle.m in Sources */, 1125B2E51C4AD3DA007D0023 /* AIRMapPolyline.m in Sources */, + DA6C263E1C9E324A0035349F /* AIRMapUrlTileManager.m in Sources */, 1125B2DA1C4AD3DA007D0023 /* AIRMap.m in Sources */, 1125B2E71C4AD3DA007D0023 /* RCTConvert+MoreMapKit.m in Sources */, 1125B2DF1C4AD3DA007D0023 /* AIRMapCoordinate.m in Sources */, 1125B2F21C4AD445007D0023 /* SMCalloutView.m in Sources */, 1125B2E11C4AD3DA007D0023 /* AIRMapMarker.m in Sources */, 1125B2E21C4AD3DA007D0023 /* AIRMapMarkerManager.m in Sources */, + DA6C26381C9E2AFE0035349F /* AIRMapUrlTile.m in Sources */, 1125B2DE1C4AD3DA007D0023 /* AIRMapCircleManager.m in Sources */, 1125B2DC1C4AD3DA007D0023 /* AIRMapCalloutManager.m in Sources */, ); diff --git a/ios/AirMaps/AIRMap.m b/ios/AirMaps/AIRMap.m index 702fba92d..1cb2bc640 100644 --- a/ios/AirMaps/AIRMap.m +++ b/ios/AirMaps/AIRMap.m @@ -16,6 +16,7 @@ #import "AIRMapPolygon.h" #import "AIRMapCircle.h" #import +#import "AIRMapUrlTile.h" const CLLocationDegrees AIRMapDefaultSpan = 0.005; const NSTimeInterval AIRMapRegionChangeObserveInterval = 0.1; @@ -100,6 +101,8 @@ - (void)insertReactSubview:(id)subview atIndex:(NSInteger)atIndex [self addOverlay:(id)subview]; } else if ([subview isKindOfClass:[AIRMapCircle class]]) { [self addOverlay:(id)subview]; + } else if ([subview isKindOfClass:[AIRMapUrlTile class]]) { + [self addOverlay:(id)subview]; } [_reactSubviews insertObject:(UIView *)subview atIndex:(NSUInteger) atIndex]; } @@ -115,6 +118,8 @@ - (void)removeReactSubview:(id)subview { [self removeOverlay:(id ) subview]; } else if ([subview isKindOfClass:[AIRMapCircle class]]) { [self removeOverlay:(id ) subview]; + } else if ([subview isKindOfClass:[AIRMapUrlTile class]]) { + [self removeOverlay:(id ) subview]; } [_reactSubviews removeObject:(UIView *)subview]; } diff --git a/ios/AirMaps/AIRMapManager.m b/ios/AirMaps/AIRMapManager.m index df806210e..3ac5a693d 100644 --- a/ios/AirMaps/AIRMapManager.m +++ b/ios/AirMaps/AIRMapManager.m @@ -24,6 +24,7 @@ #import "AIRMapPolygon.h" #import "AIRMapCircle.h" #import "SMCalloutView.h" +#import "AIRMapUrlTile.h" #import @@ -342,6 +343,8 @@ - (MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id +#import +#import + +#import "RCTConvert+MapKit.h" +#import "RCTComponent.h" +#import "AIRMapCoordinate.h" +#import "AIRMap.h" +#import "RCTView.h" + +@interface AIRMapUrlTile : MKAnnotationView + +@property (nonatomic, weak) AIRMap *map; + +@property (nonatomic, strong) MKTileOverlay *tileOverlay; +@property (nonatomic, strong) MKTileOverlayRenderer *renderer; + +@property (nonatomic, copy) NSString *urlTemplate; + +#pragma mark MKOverlay protocol + +@property(nonatomic, readonly) CLLocationCoordinate2D coordinate; +@property(nonatomic, readonly) MKMapRect boundingMapRect; +- (BOOL)intersectsMapRect:(MKMapRect)mapRect; +- (BOOL)canReplaceMapContent; + +@end diff --git a/ios/AirMaps/AIRMapUrlTile.m b/ios/AirMaps/AIRMapUrlTile.m new file mode 100644 index 000000000..5fbe1a3b8 --- /dev/null +++ b/ios/AirMaps/AIRMapUrlTile.m @@ -0,0 +1,58 @@ +// +// AIRUrlTileOverlay.m +// AirMaps +// +// Created by cascadian on 3/19/16. +// Copyright © 2016. All rights reserved. +// + +#import "AIRMapUrlTile.h" +#import "UIView+React.h" + +@implementation AIRMapUrlTile { + BOOL _urlTemplateSet; +} + + +- (void)setUrlTemplate:(NSString *)urlTemplate{ + _urlTemplate = urlTemplate; + _urlTemplateSet = YES; + [self createTileOverlayAndRendererIfPossible]; + [self update]; +} + +- (void) createTileOverlayAndRendererIfPossible +{ + if (!_urlTemplateSet) return; + self.tileOverlay = [[MKTileOverlay alloc] initWithURLTemplate:self.urlTemplate]; + self.tileOverlay.canReplaceMapContent = YES; + self.renderer = [[MKTileOverlayRenderer alloc] initWithTileOverlay:self.tileOverlay]; +} + +- (void) update +{ + if (!_renderer) return; + + if (_map == nil) return; + [_map removeOverlay:self]; + [_map addOverlay:self level:MKOverlayLevelAboveLabels]; +} + +#pragma mark MKOverlay implementation + +- (CLLocationCoordinate2D) coordinate +{ + return self.tileOverlay.coordinate; +} + +- (MKMapRect) boundingMapRect +{ + return self.tileOverlay.boundingMapRect; +} + +- (BOOL)canReplaceMapContent +{ + return self.tileOverlay.canReplaceMapContent; +} + +@end diff --git a/ios/AirMaps/AIRMapUrlTileManager.h b/ios/AirMaps/AIRMapUrlTileManager.h new file mode 100644 index 000000000..6a79b2233 --- /dev/null +++ b/ios/AirMaps/AIRMapUrlTileManager.h @@ -0,0 +1,14 @@ +// +// AIRMapUrlTileManager.h +// AirMaps +// +// Created by cascadian on 3/19/16. +// Copyright © 2016. All rights reserved. +// + + +#import "RCTViewManager.h" + +@interface AIRMapUrlTileManager : RCTViewManager + +@end diff --git a/ios/AirMaps/AIRMapUrlTileManager.m b/ios/AirMaps/AIRMapUrlTileManager.m new file mode 100644 index 000000000..decec5170 --- /dev/null +++ b/ios/AirMaps/AIRMapUrlTileManager.m @@ -0,0 +1,38 @@ +// +// AIRMapUrlTileManager.m +// AirMaps +// +// Created by cascadian on 3/19/16. +// Copyright © 2016. All rights reserved. +// + +#import "RCTBridge.h" +#import "RCTConvert.h" +#import "RCTConvert+CoreLocation.h" +#import "RCTEventDispatcher.h" +#import "UIView+React.h" +#import "AIRMapMarker.h" +#import "RCTViewManager.h" +#import "AIRMapUrlTile.h" + +#import "AIRMapUrlTileManager.h" + +@interface AIRMapUrlTileManager() + +@end + +@implementation AIRMapUrlTileManager + + +RCT_EXPORT_MODULE() + +- (UIView *)view +{ + AIRMapUrlTile *tile = [AIRMapUrlTile new]; + return tile; +} + +RCT_EXPORT_VIEW_PROPERTY(urlTemplate, NSString) + +@end + From 3faac1b98b34f713779b6f3111d3d09105349d30 Mon Sep 17 00:00:00 2001 From: cascadian Date: Sat, 19 Mar 2016 21:59:26 -0700 Subject: [PATCH 0065/1148] renamed the 'url' property to 'urlTemplate' for consistency with ios --- .../main/java/com/AirMaps/AirMapUrlTile.java | 22 +++++++++---------- .../com/AirMaps/AirMapUrlTileManager.java | 6 ++--- components/MapView.js | 3 +-- example/examples/CustomTiles.js | 2 +- 4 files changed, 16 insertions(+), 17 deletions(-) diff --git a/android/src/main/java/com/AirMaps/AirMapUrlTile.java b/android/src/main/java/com/AirMaps/AirMapUrlTile.java index 5eb26f9b7..675a4629b 100644 --- a/android/src/main/java/com/AirMaps/AirMapUrlTile.java +++ b/android/src/main/java/com/AirMaps/AirMapUrlTile.java @@ -15,15 +15,15 @@ public class AirMapUrlTile extends AirMapFeature { class AIRMapUrlTileProvider extends UrlTileProvider { - private String url; - public AIRMapUrlTileProvider(int width, int height, String url) { + private String urlTemplate; + public AIRMapUrlTileProvider(int width, int height, String urlTemplate) { super(width, height); - this.url = url; + this.urlTemplate = urlTemplate; } @Override public synchronized URL getTileUrl(int x, int y, int zoom) { - String s = this.url + String s = this.urlTemplate .replace("{x}", Integer.toString(x)) .replace("{y}", Integer.toString(y)) .replace("{z}", Integer.toString(zoom)); @@ -36,8 +36,8 @@ public synchronized URL getTileUrl(int x, int y, int zoom) { return url; } - public void setUrl(String url) { - this.url = url; + public void setUrlTemplate(String urlTemplate) { + this.urlTemplate = urlTemplate; } } @@ -45,17 +45,17 @@ public void setUrl(String url) { private TileOverlay tileOverlay; private AIRMapUrlTileProvider tileProvider; - private String url; + private String urlTemplate; private float zIndex; public AirMapUrlTile(Context context) { super(context); } - public void setUrl(String url) { - this.url = url; + public void setUrlTemplate(String urlTemplate) { + this.urlTemplate = urlTemplate; if (tileProvider != null) { - tileProvider.setUrl(url); + tileProvider.setUrlTemplate(urlTemplate); } if (tileOverlay != null) { tileOverlay.clearTileCache(); @@ -79,7 +79,7 @@ public TileOverlayOptions getTileOverlayOptions() { private TileOverlayOptions createTileOverlayOptions() { TileOverlayOptions options = new TileOverlayOptions(); options.zIndex(zIndex); - this.tileProvider = new AIRMapUrlTileProvider(256, 256, this.url); + this.tileProvider = new AIRMapUrlTileProvider(256, 256, this.urlTemplate); options.tileProvider(this.tileProvider); return options; } diff --git a/android/src/main/java/com/AirMaps/AirMapUrlTileManager.java b/android/src/main/java/com/AirMaps/AirMapUrlTileManager.java index 8cba82b82..1f140e652 100644 --- a/android/src/main/java/com/AirMaps/AirMapUrlTileManager.java +++ b/android/src/main/java/com/AirMaps/AirMapUrlTileManager.java @@ -38,9 +38,9 @@ public AirMapUrlTile createViewInstance(ThemedReactContext context) { return new AirMapUrlTile(context); } - @ReactProp(name = "url") - public void setCenter(AirMapUrlTile view, String url) { - view.setUrl(url); + @ReactProp(name = "urlTemplate") + public void setUrlTemplate(AirMapUrlTile view, String urlTemplate) { + view.setUrlTemplate(urlTemplate); } @ReactProp(name = "zIndex", defaultFloat = -1.0f) diff --git a/components/MapView.js b/components/MapView.js index a55d4d726..1d4670ef7 100644 --- a/components/MapView.js +++ b/components/MapView.js @@ -6,7 +6,6 @@ import { Animated, requireNativeComponent, NativeModules, -<<<<<<< 70a6c8a927b90df86e7092acc6e026df1a58331c ColorPropType, findNodeHandle, } from 'react-native'; @@ -15,7 +14,7 @@ import MapPolyline from './MapPolyline'; import MapPolygon from './MapPolygon'; import MapCircle from './MapCircle'; import MapCallout from './MapCallout'; -import MapUrlTile './MapUrlTile'; +import MapUrlTile from './MapUrlTile'; const viewConfig = { uiViewClassName: 'AIRMap', diff --git a/example/examples/CustomTiles.js b/example/examples/CustomTiles.js index 6ac69bf87..0ab29bacf 100644 --- a/example/examples/CustomTiles.js +++ b/example/examples/CustomTiles.js @@ -42,7 +42,7 @@ var Overlays = React.createClass({ initialRegion={region} > From 89dd0c1faf1f41a0b944977fbda4dcc0cdc4b780 Mon Sep 17 00:00:00 2001 From: Spike Brehm Date: Tue, 20 Sep 2016 12:06:40 -0700 Subject: [PATCH 0066/1148] Fix some changes missed in rebase --- .../android/react/maps}/AirMapUrlTile.java | 3 +- .../react/maps}/AirMapUrlTileManager.java | 7 +- components/MapUrlTile.js | 64 +++++++++---------- example/examples/CustomTiles.js | 34 +++++----- 4 files changed, 49 insertions(+), 59 deletions(-) rename android/src/main/java/com/{AirMaps => airbnb/android/react/maps}/AirMapUrlTile.java (98%) rename android/src/main/java/com/{AirMaps => airbnb/android/react/maps}/AirMapUrlTileManager.java (91%) diff --git a/android/src/main/java/com/AirMaps/AirMapUrlTile.java b/android/src/main/java/com/airbnb/android/react/maps/AirMapUrlTile.java similarity index 98% rename from android/src/main/java/com/AirMaps/AirMapUrlTile.java rename to android/src/main/java/com/airbnb/android/react/maps/AirMapUrlTile.java index 675a4629b..691c2fd3c 100644 --- a/android/src/main/java/com/AirMaps/AirMapUrlTile.java +++ b/android/src/main/java/com/airbnb/android/react/maps/AirMapUrlTile.java @@ -1,4 +1,4 @@ -package com.AirMaps; +package com.airbnb.android.react.maps; import android.content.Context; @@ -9,7 +9,6 @@ import java.net.MalformedURLException; import java.net.URL; -import java.util.Locale; public class AirMapUrlTile extends AirMapFeature { diff --git a/android/src/main/java/com/AirMaps/AirMapUrlTileManager.java b/android/src/main/java/com/airbnb/android/react/maps/AirMapUrlTileManager.java similarity index 91% rename from android/src/main/java/com/AirMaps/AirMapUrlTileManager.java rename to android/src/main/java/com/airbnb/android/react/maps/AirMapUrlTileManager.java index 1f140e652..7ea0726dc 100644 --- a/android/src/main/java/com/AirMaps/AirMapUrlTileManager.java +++ b/android/src/main/java/com/airbnb/android/react/maps/AirMapUrlTileManager.java @@ -1,17 +1,14 @@ -package com.AirMaps; +package com.airbnb.android.react.maps; import android.content.Context; -import android.graphics.Color; import android.os.Build; import android.util.DisplayMetrics; import android.view.WindowManager; import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.ReadableMap; -import com.facebook.react.uimanager.annotations.ReactProp; import com.facebook.react.uimanager.ThemedReactContext; import com.facebook.react.uimanager.ViewGroupManager; -import com.google.android.gms.maps.model.LatLng; +import com.facebook.react.uimanager.annotations.ReactProp; public class AirMapUrlTileManager extends ViewGroupManager { private DisplayMetrics metrics; diff --git a/components/MapUrlTile.js b/components/MapUrlTile.js index 09f3c7fe2..3ab1a8488 100644 --- a/components/MapUrlTile.js +++ b/components/MapUrlTile.js @@ -1,44 +1,40 @@ - -var React = require('react-native'); -var { +import React, { PropTypes } from 'react'; +import { View, - NativeMethodsMixin, requireNativeComponent, - StyleSheet, - PropTypes, -} = React; - -var MapUrlTile = React.createClass({ - mixins: [NativeMethodsMixin], - - propTypes: { - ...View.propTypes, - - /** - * The url template of the tile server. The patterns {x} {y} {z} will be replaced at runtime - * For example, http://c.tile.openstreetmap.org/{z}/{x}/{y}.png - */ - urlTemplate: PropTypes.string.isRequired, - - /** - * The order in which this tile overlay is drawn with respect to other overlays. An overlay - * with a larger z-index is drawn over overlays with smaller z-indices. The order of overlays - * with the same z-index is arbitrary. The default zIndex is -1. - * - * @platform android - */ - zIndex: PropTypes.number, - }, - - render: function() { +} from 'react-native'; + +const propTypes = { + ...View.propTypes, + + /** + * The url template of the tile server. The patterns {x} {y} {z} will be replaced at runtime + * For example, http://c.tile.openstreetmap.org/{z}/{x}/{y}.png + */ + urlTemplate: PropTypes.string.isRequired, + + /** + * The order in which this tile overlay is drawn with respect to other overlays. An overlay + * with a larger z-index is drawn over overlays with smaller z-indices. The order of overlays + * with the same z-index is arbitrary. The default zIndex is -1. + * + * @platform android + */ + zIndex: PropTypes.number, +}; + +class MapUrlTile extends React.Component { + render() { return ( ); - }, -}); + } +} + +MapUrlTile.propTypes = propTypes; -var AIRMapUrlTile = requireNativeComponent('AIRMapUrlTile', MapUrlTile); +const AIRMapUrlTile = requireNativeComponent('AIRMapUrlTile', MapUrlTile); module.exports = MapUrlTile; diff --git a/example/examples/CustomTiles.js b/example/examples/CustomTiles.js index 0ab29bacf..6154f6303 100644 --- a/example/examples/CustomTiles.js +++ b/example/examples/CustomTiles.js @@ -1,28 +1,26 @@ -var React = require('react-native'); -var { +import React from 'react'; +import { StyleSheet, - PropTypes, View, Text, Dimensions, - TouchableOpacity, - Image, - } = React; +} from 'react-native'; -var MapView = require('react-native-maps'); +import MapView from 'react-native-maps'; -var { width, height } = Dimensions.get('window'); +const { width, height } = Dimensions.get('window'); const ASPECT_RATIO = width / height; const LATITUDE = 37.78825; const LONGITUDE = -122.4324; const LATITUDE_DELTA = 0.0922; const LONGITUDE_DELTA = LATITUDE_DELTA * ASPECT_RATIO; -const SPACE = 0.01; -var Overlays = React.createClass({ - getInitialState() { - return { +class CustomTiles extends React.Component { + constructor(props, context) { + super(props, context); + + this.state = { region: { latitude: LATITUDE, longitude: LONGITUDE, @@ -30,10 +28,10 @@ var Overlays = React.createClass({ longitudeDelta: LONGITUDE_DELTA, }, }; - }, + } render() { - const { region, circle, polygon, polyline } = this.state; + const { region } = this.state; return ( ); - }, -}); + } +} -var styles = StyleSheet.create({ +const styles = StyleSheet.create({ container: { position: 'absolute', top: 0, @@ -97,4 +95,4 @@ var styles = StyleSheet.create({ }, }); -module.exports = Overlays; +module.exports = CustomTiles; From d8b104a4e538f79d30ef40b85169ca1114dda36c Mon Sep 17 00:00:00 2001 From: Spike Brehm Date: Tue, 20 Sep 2016 14:30:57 -0700 Subject: [PATCH 0067/1148] Make MAP_TYPES constant, don't pass `none` mapType to iOS --- components/MapView.js | 27 ++++++++++++++++++--------- example/examples/CustomTiles.js | 4 ++-- example/examples/DisplayLatLng.js | 4 ++-- 3 files changed, 22 insertions(+), 13 deletions(-) diff --git a/components/MapView.js b/components/MapView.js index 1d4670ef7..59e4e5acf 100644 --- a/components/MapView.js +++ b/components/MapView.js @@ -16,6 +16,19 @@ import MapCircle from './MapCircle'; import MapCallout from './MapCallout'; import MapUrlTile from './MapUrlTile'; +const MAP_TYPES = { + STANDARD: 'standard', + SATELLITE: 'satellite', + HYBRID: 'hybrid', + TERRAIN: 'terrain', + NONE: 'none', +}; + +const ANDROID_ONLY_MAP_TYPES = [ + MAP_TYPES.TERRAIN, + MAP_TYPES.NONE, +]; + const viewConfig = { uiViewClassName: 'AIRMap', validAttributes: { @@ -172,13 +185,7 @@ const propTypes = { * - hybrid: satellite view with roads and points of interest overlayed * - terrain: (Android only) topographic view */ - mapType: PropTypes.oneOf([ - 'standard', - 'satellite', - 'hybrid', - 'terrain', - 'none', - ]), + mapType: PropTypes.oneOf(Object.values(MAP_TYPES)), /** * The region to be displayed by the map. @@ -452,8 +459,8 @@ class MapView extends React.Component { onMapReady: this._onMapReady, onLayout: this._onLayout, }; - if (Platform.OS === 'ios' && props.mapType === 'terrain') { - props.mapType = 'standard'; + if (Platform.OS === 'ios' && ANDROID_ONLY_MAP_TYPES.includes(props.mapType)) { + props.mapType = MAP_TYPES.STANDARD; } props.handlePanDrag = !!props.onPanDrag; } else { @@ -488,6 +495,8 @@ class MapView extends React.Component { MapView.propTypes = propTypes; MapView.viewConfig = viewConfig; +MapView.MAP_TYPES = MAP_TYPES; + const AIRMap = requireNativeComponent('AIRMap', MapView, { nativeOnly: { onChange: true, diff --git a/example/examples/CustomTiles.js b/example/examples/CustomTiles.js index 6154f6303..0ec74f3af 100644 --- a/example/examples/CustomTiles.js +++ b/example/examples/CustomTiles.js @@ -6,7 +6,7 @@ import { Dimensions, } from 'react-native'; -import MapView from 'react-native-maps'; +import MapView, { MAP_TYPES } from 'react-native-maps'; const { width, height } = Dimensions.get('window'); @@ -35,7 +35,7 @@ class CustomTiles extends React.Component { return ( diff --git a/example/examples/DisplayLatLng.js b/example/examples/DisplayLatLng.js index c4e8b2bb9..4a783163e 100644 --- a/example/examples/DisplayLatLng.js +++ b/example/examples/DisplayLatLng.js @@ -7,7 +7,7 @@ import { TouchableOpacity, } from 'react-native'; -import MapView from 'react-native-maps'; +import MapView, { MAP_TYPES } from 'react-native-maps'; const { width, height } = Dimensions.get('window'); @@ -57,7 +57,7 @@ class DisplayLatLng extends React.Component { { this.map = ref; }} - mapType="terrain" + mapType={MAP_TYPES.TERRAIN} style={styles.map} region={this.state.region} onRegionChange={region => this.onRegionChange(region)} From 89308d8a34e629e8e6afc9041024b9407f977d54 Mon Sep 17 00:00:00 2001 From: Fidan Hakaj Date: Sat, 17 Sep 2016 22:05:32 +0200 Subject: [PATCH 0068/1148] fix #453 --- .../android/react/maps/AirMapManager.java | 4 ++-- .../android/react/maps/AirMapModule.java | 22 ------------------- 2 files changed, 2 insertions(+), 24 deletions(-) delete mode 100644 android/src/main/java/com/airbnb/android/react/maps/AirMapModule.java diff --git a/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java b/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java index b91fa814c..211b27d14 100644 --- a/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java +++ b/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java @@ -62,13 +62,13 @@ protected AirMapView createViewInstance(ThemedReactContext context) { reactContext = context; try { - MapsInitializer.initialize(new AirMapModule(this.appContext).getActivity()); + MapsInitializer.initialize(this.appContext); } catch (RuntimeException e) { e.printStackTrace(); emitMapError("Map initialize error", "map_init_error"); } - return new AirMapView(context, this.appContext, this, this.googleMapOptions); + return new AirMapView(context, this.appContext.getCurrentActivity(), this, this.googleMapOptions); } @Override diff --git a/android/src/main/java/com/airbnb/android/react/maps/AirMapModule.java b/android/src/main/java/com/airbnb/android/react/maps/AirMapModule.java deleted file mode 100644 index e7e666b70..000000000 --- a/android/src/main/java/com/airbnb/android/react/maps/AirMapModule.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.airbnb.android.react.maps; - -import android.app.Activity; - -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.ReactContextBaseJavaModule; - -public class AirMapModule extends ReactContextBaseJavaModule { - - public AirMapModule(ReactApplicationContext reactContext) { - super(reactContext); - } - - @Override - public String getName() { - return "AirMapModule"; - } - - public Activity getActivity() { - return getCurrentActivity(); - } -} From f78c0ee674a2a67bc72f843779cd3eb0f16e1675 Mon Sep 17 00:00:00 2001 From: Gil Birman Date: Thu, 22 Sep 2016 10:03:08 -0700 Subject: [PATCH 0069/1148] Support Google Maps on iOS (#548) --- .gitignore | 2 + README.md | 2 + components/MapCallout.js | 18 +- components/MapCircle.js | 18 +- components/MapMarker.js | 28 +- components/MapPolygon.js | 18 +- components/MapPolyline.js | 18 +- components/MapView.js | 69 +- components/ProviderConstants.js | 2 + components/decorateMapComponent.js | 82 +++ docs/examples-setup.md | 21 + docs/installation.md | 31 +- docs/mapview.md | 1 + example/App.js | 65 +- example/examples/AnimatedMarkers.js | 5 + example/examples/AnimatedViews.js | 5 + example/examples/CachedMap.js | 5 + example/examples/Callouts.js | 24 +- example/examples/DefaultMarkers.js | 5 + example/examples/DisplayLatLng.js | 7 +- example/examples/DraggableMarkers.js | 29 +- example/examples/EventListener.js | 27 +- example/examples/FitToSuppliedMarkers.js | 5 + example/examples/LoadingMap.js | 5 + example/examples/MarkerTypes.js | 24 +- example/examples/Overlays.js | 5 + example/examples/PolygonCreator.js | 9 +- example/examples/PolylineCreator.js | 5 + example/examples/StaticMap.js | 118 ++++ example/examples/TakeSnapshot.js | 5 + example/examples/ViewsAsMarkers.js | 10 +- .../AirMapsExplorer.xcodeproj/project.pbxproj | 663 ++++++++---------- example/ios/AirMapsExplorer/AppDelegate.m | 4 + example/ios/Podfile | 50 ++ example/ios/Podfile.lock | 51 ++ example/package.json | 2 +- ios/AirGoogleMaps/AIRGMSMarker.h | 23 + ios/AirGoogleMaps/AIRGMSMarker.m | 12 + ios/AirGoogleMaps/AIRGoogleMap.h | 42 ++ ios/AirGoogleMaps/AIRGoogleMap.m | 208 ++++++ ios/AirGoogleMaps/AIRGoogleMapCallout.h | 15 + ios/AirGoogleMaps/AIRGoogleMapCallout.m | 15 + .../AIRGoogleMapCalloutManager.h | 12 + .../AIRGoogleMapCalloutManager.m | 25 + ios/AirGoogleMaps/AIRGoogleMapManager.h | 12 + ios/AirGoogleMaps/AIRGoogleMapManager.m | 174 +++++ ios/AirGoogleMaps/AIRGoogleMapMarker.h | 39 ++ ios/AirGoogleMaps/AIRGoogleMapMarker.m | 239 +++++++ ios/AirGoogleMaps/AIRGoogleMapMarkerManager.h | 12 + ios/AirGoogleMaps/AIRGoogleMapMarkerManager.m | 64 ++ ios/AirMaps.xcodeproj/project.pbxproj | 99 +++ .../contents.xcworkspacedata | 10 + ios/AirMaps/AIRMap.m | 11 +- ios/AirMaps/AIRMapUrlTile.h | 2 +- ios/AirMaps/Callout/SMCalloutView.h | 4 +- ios/Podfile | 21 + ios/Podfile.lock | 51 ++ react-native-google-maps.podspec | 16 + 58 files changed, 2098 insertions(+), 446 deletions(-) create mode 100644 components/ProviderConstants.js create mode 100644 components/decorateMapComponent.js create mode 100644 docs/examples-setup.md create mode 100644 example/examples/StaticMap.js create mode 100644 example/ios/Podfile create mode 100644 example/ios/Podfile.lock create mode 100644 ios/AirGoogleMaps/AIRGMSMarker.h create mode 100644 ios/AirGoogleMaps/AIRGMSMarker.m create mode 100644 ios/AirGoogleMaps/AIRGoogleMap.h create mode 100644 ios/AirGoogleMaps/AIRGoogleMap.m create mode 100644 ios/AirGoogleMaps/AIRGoogleMapCallout.h create mode 100644 ios/AirGoogleMaps/AIRGoogleMapCallout.m create mode 100644 ios/AirGoogleMaps/AIRGoogleMapCalloutManager.h create mode 100644 ios/AirGoogleMaps/AIRGoogleMapCalloutManager.m create mode 100644 ios/AirGoogleMaps/AIRGoogleMapManager.h create mode 100644 ios/AirGoogleMaps/AIRGoogleMapManager.m create mode 100644 ios/AirGoogleMaps/AIRGoogleMapMarker.h create mode 100644 ios/AirGoogleMaps/AIRGoogleMapMarker.m create mode 100644 ios/AirGoogleMaps/AIRGoogleMapMarkerManager.h create mode 100644 ios/AirGoogleMaps/AIRGoogleMapMarkerManager.m create mode 100644 ios/AirMaps.xcworkspace/contents.xcworkspacedata create mode 100644 ios/Podfile create mode 100644 ios/Podfile.lock create mode 100644 react-native-google-maps.podspec diff --git a/.gitignore b/.gitignore index 0253e8835..a2f0b339f 100644 --- a/.gitignore +++ b/.gitignore @@ -33,3 +33,5 @@ local.properties # node_modules/ npm-debug.log +Pods/ +AirMapsExplorer.xcworkspace/ diff --git a/README.md b/README.md index 40519bb5b..34ec9ef33 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,8 @@ React Native Map components for iOS + Android See [Installation Instructions](docs/installation.md). +See [Setup Instructions for the Included Example Project](docs/examples-setup.md). + ## Compatibility Due to the rapid changes being made in the React Native ecosystem, we are not officially going to diff --git a/components/MapCallout.js b/components/MapCallout.js index 3c15945a3..cf4bb9cef 100644 --- a/components/MapCallout.js +++ b/components/MapCallout.js @@ -1,9 +1,12 @@ import React, { PropTypes } from 'react'; import { View, - requireNativeComponent, StyleSheet, } from 'react-native'; +import decorateMapComponent, { + SUPPORTED, + USES_DEFAULT_IMPLEMENTATION, +} from './decorateMapComponent'; const propTypes = { ...View.propTypes, @@ -17,6 +20,7 @@ const defaultProps = { class MapCallout extends React.Component { render() { + const AIRMapCallout = this.getAirComponent(); return ; } } @@ -30,6 +34,12 @@ const styles = StyleSheet.create({ }, }); -const AIRMapCallout = requireNativeComponent('AIRMapCallout', MapCallout); - -module.exports = MapCallout; +module.exports = decorateMapComponent(MapCallout, { + componentType: 'Callout', + providers: { + google: { + ios: SUPPORTED, + android: USES_DEFAULT_IMPLEMENTATION, + }, + }, +}); diff --git a/components/MapCircle.js b/components/MapCircle.js index 42e87a0ae..054cd2b6b 100644 --- a/components/MapCircle.js +++ b/components/MapCircle.js @@ -1,8 +1,11 @@ import React, { PropTypes } from 'react'; import { View, - requireNativeComponent, } from 'react-native'; +import decorateMapComponent, { + USES_DEFAULT_IMPLEMENTATION, + NOT_SUPPORTED, +} from './decorateMapComponent'; const propTypes = { ...View.propTypes, @@ -123,6 +126,7 @@ const defaultProps = { class MapCircle extends React.Component { render() { + const AIRMapCircle = this.getAirComponent(); return ( ); @@ -132,6 +136,12 @@ class MapCircle extends React.Component { MapCircle.propTypes = propTypes; MapCircle.defaultProps = defaultProps; -const AIRMapCircle = requireNativeComponent('AIRMapCircle', MapCircle); - -module.exports = MapCircle; +module.exports = decorateMapComponent(MapCircle, { + componentType: 'Circle', + providers: { + google: { + ios: NOT_SUPPORTED, + android: USES_DEFAULT_IMPLEMENTATION, + }, + }, +}); diff --git a/components/MapMarker.js b/components/MapMarker.js index e03458a7f..45ed6c300 100644 --- a/components/MapMarker.js +++ b/components/MapMarker.js @@ -1,7 +1,6 @@ import React, { PropTypes } from 'react'; import { View, - requireNativeComponent, StyleSheet, Platform, NativeModules, @@ -10,9 +9,13 @@ import { } from 'react-native'; import resolveAssetSource from 'react-native/Libraries/Image/resolveAssetSource'; +import decorateMapComponent, { + SUPPORTED, + USES_DEFAULT_IMPLEMENTATION, +} from './decorateMapComponent'; const viewConfig = { - uiViewClassName: 'AIRMapMarker', + uiViewClassName: 'AIRMapMarker', validAttributes: { coordinate: true, }, @@ -226,16 +229,13 @@ class MapMarker extends React.Component { case 'android': NativeModules.UIManager.dispatchViewManagerCommand( this._getHandle(), - NativeModules.UIManager.AIRMapMarker.Commands[name], + this.getUIManagerCommand(name), args ); break; case 'ios': - NativeModules.AIRMapMarkerManager[name].apply( - NativeModules.AIRMapMarkerManager[name], - [this._getHandle(), ...args] - ); + this.getMapManagerCommand(name)(this._getHandle(), ...args); break; default: @@ -250,6 +250,8 @@ class MapMarker extends React.Component { image = image.uri; } + const AIRMapMarker = this.getAirComponent(); + return ( { this.marker = ref; }} @@ -272,8 +274,14 @@ const styles = StyleSheet.create({ }, }); -const AIRMapMarker = requireNativeComponent('AIRMapMarker', MapMarker); - MapMarker.Animated = Animated.createAnimatedComponent(MapMarker); -module.exports = MapMarker; +module.exports = decorateMapComponent(MapMarker, { + componentType: 'Marker', + providers: { + google: { + ios: SUPPORTED, + android: USES_DEFAULT_IMPLEMENTATION, + }, + }, +}); diff --git a/components/MapPolygon.js b/components/MapPolygon.js index 1bfe0928d..979cd54f7 100644 --- a/components/MapPolygon.js +++ b/components/MapPolygon.js @@ -1,8 +1,11 @@ import React, { PropTypes } from 'react'; import { View, - requireNativeComponent, } from 'react-native'; +import decorateMapComponent, { + USES_DEFAULT_IMPLEMENTATION, + NOT_SUPPORTED, +} from './decorateMapComponent'; const propTypes = { ...View.propTypes, @@ -128,6 +131,7 @@ const defaultProps = { class MapPolygon extends React.Component { render() { + const AIRMapPolygon = this.getAirComponent(); return ( ); @@ -137,6 +141,12 @@ class MapPolygon extends React.Component { MapPolygon.propTypes = propTypes; MapPolygon.defaultProps = defaultProps; -const AIRMapPolygon = requireNativeComponent('AIRMapPolygon', MapPolygon); - -module.exports = MapPolygon; +module.exports = decorateMapComponent(MapPolygon, { + componentType: 'Polygon', + providers: { + google: { + ios: NOT_SUPPORTED, + android: USES_DEFAULT_IMPLEMENTATION, + }, + }, +}); diff --git a/components/MapPolyline.js b/components/MapPolyline.js index 8a15ad3a5..067e706de 100644 --- a/components/MapPolyline.js +++ b/components/MapPolyline.js @@ -1,8 +1,11 @@ import React, { PropTypes } from 'react'; import { View, - requireNativeComponent, } from 'react-native'; +import decorateMapComponent, { + USES_DEFAULT_IMPLEMENTATION, + NOT_SUPPORTED, +} from './decorateMapComponent'; const propTypes = { ...View.propTypes, @@ -123,6 +126,7 @@ const defaultProps = { class MapPolyline extends React.Component { render() { + const AIRMapPolyline = this.getAirComponent(); return ( ); @@ -132,6 +136,12 @@ class MapPolyline extends React.Component { MapPolyline.propTypes = propTypes; MapPolyline.defaultProps = defaultProps; -const AIRMapPolyline = requireNativeComponent('AIRMapPolyline', MapPolyline); - -module.exports = MapPolyline; +module.exports = decorateMapComponent(MapPolyline, { + componentType: 'Polyline', + providers: { + google: { + ios: NOT_SUPPORTED, + android: USES_DEFAULT_IMPLEMENTATION, + }, + }, +}); diff --git a/components/MapView.js b/components/MapView.js index 59e4e5acf..7c12af0d5 100644 --- a/components/MapView.js +++ b/components/MapView.js @@ -15,6 +15,13 @@ import MapPolygon from './MapPolygon'; import MapCircle from './MapCircle'; import MapCallout from './MapCallout'; import MapUrlTile from './MapUrlTile'; +import { + contextTypes as childContextTypes, + getAirMapName, + googleMapIsInstalled, + createNotSupportedComponent, +} from './decorateMapComponent'; +import * as ProviderConstants from './ProviderConstants'; const MAP_TYPES = { STANDARD: 'standard', @@ -30,7 +37,7 @@ const ANDROID_ONLY_MAP_TYPES = [ ]; const viewConfig = { - uiViewClassName: 'AIRMap', + uiViewClassName: 'AIRMap', validAttributes: { region: true, }, @@ -38,6 +45,15 @@ const viewConfig = { const propTypes = { ...View.propTypes, + /** + * When provider is "google", we will use GoogleMaps. + * Any value other than "google" will default to using + * MapKit in iOS or GoogleMaps in android as the map provider. + */ + provider: PropTypes.oneOf([ + 'google', + ]), + /** * Used to style and layout the `MapView`. See `StyleSheet.js` and * `ViewStylePropTypes.js` for more info. @@ -341,6 +357,10 @@ class MapView extends React.Component { this._onLayout = this._onLayout.bind(this); } + getChildContext() { + return { provider: this.props.provider }; + } + componentDidMount() { const { region, initialRegion } = this.props; if (region && this.state.isReady) { @@ -421,6 +441,14 @@ class MapView extends React.Component { this._runCommand('takeSnapshot', [width, height, finalRegion, callback]); } + _uiManagerCommand(name) { + return NativeModules.UIManager[getAirMapName(this.props.provider)].Commands[name]; + } + + _mapManagerCommand(name) { + return NativeModules[`${getAirMapName(this.props.provider)}Manager`][name]; + } + _getHandle() { return findNodeHandle(this.map); } @@ -430,16 +458,13 @@ class MapView extends React.Component { case 'android': NativeModules.UIManager.dispatchViewManagerCommand( this._getHandle(), - NativeModules.UIManager.AIRMap.Commands[name], + this._uiManagerCommand(name), args ); break; case 'ios': - NativeModules.AIRMapManager[name].apply( - NativeModules.AIRMapManager[name], - [this._getHandle(), ...args] - ); + this._mapManagerCommand(name)(this._getHandle(), ...args); break; default: @@ -483,6 +508,8 @@ class MapView extends React.Component { ); } + const AIRMap = getAirMapComponent(this.props.provider); + return ( { this.map = ref; }} @@ -494,24 +521,36 @@ class MapView extends React.Component { MapView.propTypes = propTypes; MapView.viewConfig = viewConfig; +MapView.childContextTypes = childContextTypes; MapView.MAP_TYPES = MAP_TYPES; -const AIRMap = requireNativeComponent('AIRMap', MapView, { +const nativeComponent = Component => requireNativeComponent(Component, MapView, { nativeOnly: { onChange: true, onMapReady: true, handlePanDrag: true, }, }); +const airMaps = { + default: nativeComponent('AIRMap'), +}; +if (Platform.OS === 'android') { + airMaps.google = airMaps.default; +} else { + airMaps.google = googleMapIsInstalled ? nativeComponent('AIRGoogleMap') : + createNotSupportedComponent('react-native-maps: AirGoogleMaps dir must be added to your xCode project to support GoogleMaps on iOS.'); // eslint-disable-line max-len +} +const getAirMapComponent = provider => airMaps[provider || 'default']; -const AIRMapLite = requireNativeComponent('AIRMapLite', MapView, { - nativeOnly: { - onChange: true, - onMapReady: true, - handlePanDrag: true, - }, -}); +const AIRMapLite = NativeModules.UIManager.AIRMapLite && + requireNativeComponent('AIRMapLite', MapView, { + nativeOnly: { + onChange: true, + onMapReady: true, + handlePanDrag: true, + }, + }); MapView.Marker = MapMarker; MapView.Polyline = MapPolyline; @@ -519,6 +558,8 @@ MapView.Polygon = MapPolygon; MapView.Circle = MapCircle; MapView.UrlTile = MapUrlTile; MapView.Callout = MapCallout; +Object.assign(MapView, ProviderConstants); +MapView.ProviderPropType = PropTypes.oneOf(Object.values(ProviderConstants)); MapView.Animated = Animated.createAnimatedComponent(MapView); diff --git a/components/ProviderConstants.js b/components/ProviderConstants.js new file mode 100644 index 000000000..99e776721 --- /dev/null +++ b/components/ProviderConstants.js @@ -0,0 +1,2 @@ +export const PROVIDER_DEFAULT = null; +export const PROVIDER_GOOGLE = 'google'; diff --git a/components/decorateMapComponent.js b/components/decorateMapComponent.js new file mode 100644 index 000000000..5af86a427 --- /dev/null +++ b/components/decorateMapComponent.js @@ -0,0 +1,82 @@ +import { PropTypes } from 'react'; +import { + requireNativeComponent, + NativeModules, + Platform, +} from 'react-native'; +import { + PROVIDER_DEFAULT, + PROVIDER_GOOGLE, +} from './ProviderConstants'; + +export const SUPPORTED = 'SUPPORTED'; +export const USES_DEFAULT_IMPLEMENTATION = 'USES_DEFAULT_IMPLEMENTATION'; +export const NOT_SUPPORTED = 'NOT_SUPPORTED'; + +export function getAirMapName(provider) { + if (provider === PROVIDER_GOOGLE) return 'AIRGoogleMap'; + return 'AIRMap'; +} + +function getAirComponentName(provider, component) { + return `${getAirMapName(provider)}${component}`; +} + +export const contextTypes = { + provider: PropTypes.string, +}; + +export const createNotSupportedComponent = message => () => { + console.error(message); // eslint-disable-line no-console + return null; +}; + +export const googleMapIsInstalled = !!NativeModules.UIManager[getAirMapName(PROVIDER_GOOGLE)]; + +export default function decorateMapComponent(Component, { componentType, providers }) { + const components = {}; + + const getDefaultComponent = () => + requireNativeComponent(getAirComponentName(null, componentType), Component); + + Component.contextTypes = contextTypes; // eslint-disable-line no-param-reassign + + // eslint-disable-next-line no-param-reassign + Component.prototype.getAirComponent = function getAirComponent() { + const provider = this.context.provider || PROVIDER_DEFAULT; + if (components[provider]) return components[provider]; + + if (provider === PROVIDER_DEFAULT) { + components.default = getDefaultComponent(); + return components.default; + } + + const providerInfo = providers[provider]; + const platformSupport = providerInfo[Platform.OS]; + const componentName = getAirComponentName(provider, componentType); + if (platformSupport === NOT_SUPPORTED) { + components[provider] = createNotSupportedComponent(`react-native-maps: ${componentName} is not supported on ${Platform.OS}`); // eslint-disable-line max-len + } else if (platformSupport === SUPPORTED) { + if (provider !== PROVIDER_GOOGLE || (Platform.OS === 'ios' && googleMapIsInstalled)) { + components[provider] = requireNativeComponent(componentName, Component); + } + } else { // (platformSupport === USES_DEFAULT_IMPLEMENTATION) + if (!components.default) components.default = getDefaultComponent(); + components[provider] = components.default; + } + + return components[provider]; + }; + + Component.prototype.getUIManagerCommand = function getUIManagerCommand(name) { // eslint-disable-line no-param-reassign,max-len + return NativeModules.UIManager[getAirComponentName(this.context.provider, componentType)] + .Commands[name]; + }; + + Component.prototype.getMapManagerCommand = function getMapManagerCommand(name) { // eslint-disable-line no-param-reassign,max-len + const airComponentName = `${getAirComponentName(this.context.provider, componentType)}Manager`; + return NativeModules[airComponentName][name]; + }; + + return Component; +} diff --git a/docs/examples-setup.md b/docs/examples-setup.md new file mode 100644 index 000000000..dc55f7cf4 --- /dev/null +++ b/docs/examples-setup.md @@ -0,0 +1,21 @@ +# Examples Setup + +## iOS + +1. Install dependencies and open the workspace: + + cd example + npm install + cd ios + pod install + open AirMapsExplorer.xcworkspace + +2. Make sure the `AirMapsExplorer` target is selected and click `Run` + +## android + +1. Start your emulator + +2. Install via gradle: + + ./example/android/gradlew installDebug diff --git a/docs/installation.md b/docs/installation.md index 13f170750..57121005f 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -19,12 +19,35 @@ or do it manually as described below: ## iOS -### Cocoapods -To install using Cocoapods, simply insert the following line into your `Podfile` and run `pod install` +### Option 1: Cocoapods - Same as the included AirMapsExplorer example -`pod 'react-native-maps', :path => '../node_modules/react-native-maps'` +1. Setup your `Podfile` like the included `example/ios/Podfile` then run `pod install`. + (If you do not need `GoogleMaps` support for iOS, then you can probably completely skip this step.) +2. Open your in xCode workspace +3. Drag the following folder into your project: + - `node_modules/react-native-maps/ios/AirMaps/` +4. If you need `GoogleMaps` support also drag this folder into your project: + - `node_modules/react-native-maps/ios/AirGoogleMaps/` -### Manually +### Option 2: Cocoapods -- Untested Way +NOTE: If you actually get this to work, please open an issue to let us know. +This is now considered the **old way** because it is untested and if it does work at all, it +will only work if you **don't** have `use_frameworks!` in your `Podfile` + +To install using Cocoapods, simply insert the following line into your `Podfile`: + + pod 'react-native-maps', :path => '../node_modules/react-native-maps' + +If you need `GoogleMaps` support in iOS also add this line: + + pod 'react-native-google-maps', :path => '../node_modules/react-native-maps' + +Now if you need `GoogleMaps` support you will also have to add a bunch of other stuff to your +`Podfile`. See the **comments* in the included `example/ios/Podfile` which explain the rest. + +After your `Podfile` is setup properly, run `pod install`. + +### Option3: Manually 1. Open your project in XCode, right click on `Libraries` and click `Add Files to "Your Project Name"` Look under `node_modules/react-native-maps/ios` and add `AIRMaps.xcodeproj`. 2. Add `libAIRMaps.a` to `Build Phases -> Link Binary With Libraries. diff --git a/docs/mapview.md b/docs/mapview.md index c2015a469..a4a69b6a1 100644 --- a/docs/mapview.md +++ b/docs/mapview.md @@ -4,6 +4,7 @@ | Prop | Type | Default | Note | |---|---|---|---| +| `provider` | `string` | | The map framework to use.

Either `"google"` for GoogleMaps, otherwise `null` or `undefined` to use the native map framework (`MapKit` in iOS and `GoogleMaps` in android). | `region` | `Region` | | The region to be displayed by the map.

The region is defined by the center coordinates and the span of coordinates to display. | `initialRegion` | `Region` | | The initial region to be displayed by the map. Use this prop instead of `region` only if you don't want to control the viewport of the map besides the initial region.

Changing this prop after the component has mounted will not result in a region change.

This is similar to the `initialValue` prop of a text input. | `liteMode` | `Boolean` | `false` | Enable lite mode. **Note**: Android only. diff --git a/example/App.js b/example/App.js index d21ef0d4f..2052f25a0 100644 --- a/example/App.js +++ b/example/App.js @@ -1,12 +1,14 @@ import React from 'react'; import { + Platform, View, StyleSheet, TouchableOpacity, ScrollView, Text, + Switch, } from 'react-native'; - +import { PROVIDER_GOOGLE, PROVIDER_DEFAULT } from 'react-native-maps'; import DisplayLatLng from './examples/DisplayLatLng'; import ViewsAsMarkers from './examples/ViewsAsMarkers'; import EventListener from './examples/EventListener'; @@ -25,6 +27,17 @@ import TakeSnapshot from './examples/TakeSnapshot'; import FitToSuppliedMarkers from './examples/FitToSuppliedMarkers'; import LiteMapView from './examples/LiteMapView'; import CustomTiles from './examples/CustomTiles'; +import StaticMap from './examples/StaticMap'; + +function makeExampleMapper(useGoogleMaps) { + if (useGoogleMaps) { + return example => [ + example[0], + [example[1], example[3]].filter(Boolean).join(' '), + ]; + } + return example => example; +} class App extends React.Component { constructor(props) { @@ -32,6 +45,8 @@ class App extends React.Component { this.state = { Component: null, + showGoogleMapsSwitch: Platform.OS === 'ios', + useGoogleMaps: Platform.OS === 'android', }; } @@ -58,11 +73,29 @@ class App extends React.Component { ); } + renderGoogleSwitch() { + return ( + + Use GoogleMaps? + this.setState({ useGoogleMaps: value })} + style={{ marginBottom: 10 }} + value={this.state.useGoogleMaps} + /> + + ); + } + renderExamples(examples) { - const { Component } = this.state; + const { + Component, + showGoogleMapsSwitch, + useGoogleMaps, + } = this.state; + return ( - {Component && } + {Component && } {Component && this.renderBackButton()} {!Component && + {showGoogleMapsSwitch && this.renderGoogleSwitch()} {examples.map(example => this.renderExample(example))} } @@ -79,25 +113,30 @@ class App extends React.Component { render() { return this.renderExamples([ - [DisplayLatLng, 'Tracking Position'], - [ViewsAsMarkers, 'Arbitrary Views as Markers'], - [EventListener, 'Events'], - [MarkerTypes, 'Image Based Markers'], - [DraggableMarkers, 'Draggable Markers'], + // [, , , ] + [StaticMap, 'StaticMap', true], + [DisplayLatLng, 'Tracking Position', true, '(incomplete)'], + [ViewsAsMarkers, 'Arbitrary Views as Markers', true], + [EventListener, 'Events', true, '(incomplete)'], + [MarkerTypes, 'Image Based Markers', true], + [DraggableMarkers, 'Draggable Markers', true], [PolygonCreator, 'Polygon Creator'], [PolylineCreator, 'Polyline Creator'], [AnimatedViews, 'Animating with MapViews'], [AnimatedMarkers, 'Animated Marker Position'], - [Callouts, 'Custom Callouts'], - [Overlays, 'Circles, Polygons, and Polylines'], - [DefaultMarkers, 'Default Markers'], - [TakeSnapshot, 'Take Snapshot'], + [Callouts, 'Custom Callouts', true], + [Overlays, 'Circles, Polygons, and Polylines', true, '(ios error)'], + [DefaultMarkers, 'Default Markers', true], + [TakeSnapshot, 'Take Snapshot', true, '(incomplete)'], [CachedMap, 'Cached Map'], [LoadingMap, 'Map with loading'], [FitToSuppliedMarkers, 'Focus Map On Markers'], [LiteMapView, 'Android Lite MapView'], [CustomTiles, 'Custom Tiles'], - ]); + ] + .filter(example => example[2] || !this.state.useGoogleMaps) + .map(makeExampleMapper(this.state.useGoogleMaps)) + ); } } diff --git a/example/examples/AnimatedMarkers.js b/example/examples/AnimatedMarkers.js index 49f89f9a1..8c5150e6f 100644 --- a/example/examples/AnimatedMarkers.js +++ b/example/examples/AnimatedMarkers.js @@ -42,6 +42,7 @@ class AnimatedMarkers extends React.Component { return ( {region.name} { this.marker1 = ref; }} coordinate={markers[0].coordinate} - title="This is a title" - description="This is a description" + title="This is a native view" + description="Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation" // eslint-disable-line max-len /> - + + This is a plain view @@ -89,9 +90,9 @@ class Callouts extends React.Component { calloutOffset={{ x: -8, y: 28 }} calloutAnchor={{ x: 0.5, y: 0.4 }} > - + - This is a custom callout bubble view + This is a custom callout bubble view @@ -114,7 +115,18 @@ class Callouts extends React.Component { } } +Callouts.propTypes = { + provider: MapView.ProviderPropType, +}; + const styles = StyleSheet.create({ + customView: { + width: 140, + height: 100, + }, + plainView: { + width: 60, + }, container: { ...StyleSheet.absoluteFillObject, justifyContent: 'flex-end', diff --git a/example/examples/DefaultMarkers.js b/example/examples/DefaultMarkers.js index 0f6e686a0..628384561 100644 --- a/example/examples/DefaultMarkers.js +++ b/example/examples/DefaultMarkers.js @@ -53,6 +53,7 @@ class DefaultMarkers extends React.Component { return ( this.onMapPress(e)} @@ -75,6 +76,10 @@ class DefaultMarkers extends React.Component { } } +DefaultMarkers.propTypes = { + provider: MapView.ProviderPropType, +}; + const styles = StyleSheet.create({ container: { ...StyleSheet.absoluteFillObject, diff --git a/example/examples/DisplayLatLng.js b/example/examples/DisplayLatLng.js index 4a783163e..573617d41 100644 --- a/example/examples/DisplayLatLng.js +++ b/example/examples/DisplayLatLng.js @@ -56,10 +56,11 @@ class DisplayLatLng extends React.Component { return ( { this.map = ref; }} mapType={MAP_TYPES.TERRAIN} style={styles.map} - region={this.state.region} + initialRegion={this.state.region} onRegionChange={region => this.onRegionChange(region)} /> @@ -87,6 +88,10 @@ class DisplayLatLng extends React.Component { } } +DisplayLatLng.propTypes = { + provider: MapView.ProviderPropType, +}; + const styles = StyleSheet.create({ container: { ...StyleSheet.absoluteFillObject, diff --git a/example/examples/DraggableMarkers.js b/example/examples/DraggableMarkers.js index c3a21127f..17ec862e2 100644 --- a/example/examples/DraggableMarkers.js +++ b/example/examples/DraggableMarkers.js @@ -17,6 +17,10 @@ const LATITUDE_DELTA = 0.0922; const LONGITUDE_DELTA = LATITUDE_DELTA * ASPECT_RATIO; const SPACE = 0.01; +function log(eventName, e) { + console.log(eventName, e.nativeEvent); +} + class MarkerTypes extends React.Component { constructor(props) { super(props); @@ -37,6 +41,7 @@ class MarkerTypes extends React.Component { return ( console.log('onSelect', e)} - onDrag={(e) => console.log('onDrag', e)} - onDragStart={(e) => console.log('onDragStart', e)} - onDragEnd={(e) => console.log('onDragEnd', e)} - onPress={(e) => console.log('onPress', e)} + onSelect={(e) => log('onSelect', e)} + onDrag={(e) => log('onDrag', e)} + onDragStart={(e) => log('onDragStart', e)} + onDragEnd={(e) => log('onDragEnd', e)} + onPress={(e) => log('onPress', e)} draggable > console.log('onSelect', e)} - onDrag={(e) => console.log('onDrag', e)} - onDragStart={(e) => console.log('onDragStart', e)} - onDragEnd={(e) => console.log('onDragEnd', e)} - onPress={(e) => console.log('onPress', e)} + onSelect={(e) => log('onSelect', e)} + onDrag={(e) => log('onDrag', e)} + onDragStart={(e) => log('onDragStart', e)} + onDragEnd={(e) => log('onDragEnd', e)} + onPress={(e) => log('onPress', e)} draggable /> @@ -71,6 +76,10 @@ class MarkerTypes extends React.Component { } } +MarkerTypes.propTypes = { + provider: MapView.ProviderPropType, +}; + const styles = StyleSheet.create({ container: { ...StyleSheet.absoluteFillObject, diff --git a/example/examples/EventListener.js b/example/examples/EventListener.js index 2226233a4..85b6dbcf5 100644 --- a/example/examples/EventListener.js +++ b/example/examples/EventListener.js @@ -6,7 +6,6 @@ import { Dimensions, ScrollView, } from 'react-native'; - import MapView from 'react-native-maps'; import PriceMarker from './PriceMarker'; @@ -41,7 +40,7 @@ Event.propTypes = { // eslint-disable-next-line react/no-multi-comp -class DisplayLatLng extends React.Component { +class EventListener extends React.Component { constructor(props) { super(props); @@ -80,6 +79,7 @@ class DisplayLatLng extends React.Component { return ( + + { this.map = ref; }} style={styles.map} initialRegion={{ @@ -148,6 +149,10 @@ class FocusOnMarkers extends React.Component { } } +FocusOnMarkers.propTypes = { + provider: MapView.ProviderPropType, +}; + const styles = StyleSheet.create({ container: { ...StyleSheet.absoluteFillObject, diff --git a/example/examples/LoadingMap.js b/example/examples/LoadingMap.js index 28b45e3f7..a7cca9fe8 100644 --- a/example/examples/LoadingMap.js +++ b/example/examples/LoadingMap.js @@ -36,6 +36,7 @@ class LoadingMap extends React.Component { return ( this.setState({ marker1: !this.state.marker1 })} coordinate={{ latitude: LATITUDE + SPACE, longitude: LONGITUDE + SPACE, }} centerOffset={{ x: -18, y: -60 }} anchor={{ x: 0.69, y: 1 }} - image={flagBlueImg} + image={this.state.marker1 ? flagBlueImg : flagPinkImg} > X this.setState({ marker2: !this.state.marker2 })} coordinate={{ latitude: LATITUDE - SPACE, longitude: LONGITUDE - SPACE, }} centerOffset={{ x: -42, y: -60 }} anchor={{ x: 0.84, y: 1 }} - image={flagPinkImg} + image={this.state.marker2 ? flagBlueImg : flagPinkImg} /> @@ -58,6 +68,10 @@ class MarkerTypes extends React.Component { } } +MarkerTypes.propTypes = { + provider: MapView.ProviderPropType, +}; + const styles = StyleSheet.create({ container: { ...StyleSheet.absoluteFillObject, @@ -68,8 +82,8 @@ const styles = StyleSheet.create({ ...StyleSheet.absoluteFillObject, }, marker: { - marginLeft: 33, - marginTop: 18, + marginLeft: 46, + marginTop: 33, fontWeight: 'bold', }, }); diff --git a/example/examples/Overlays.js b/example/examples/Overlays.js index 8e777f433..8006abbbc 100644 --- a/example/examples/Overlays.js +++ b/example/examples/Overlays.js @@ -75,6 +75,7 @@ class Overlays extends React.Component { return ( @@ -107,6 +108,10 @@ class Overlays extends React.Component { } } +Overlays.propTypes = { + provider: MapView.ProviderPropType, +}; + const styles = StyleSheet.create({ container: { ...StyleSheet.absoluteFillObject, diff --git a/example/examples/PolygonCreator.js b/example/examples/PolygonCreator.js index 93c3ef09d..605651c58 100644 --- a/example/examples/PolygonCreator.js +++ b/example/examples/PolygonCreator.js @@ -18,7 +18,7 @@ const LATITUDE_DELTA = 0.0922; const LONGITUDE_DELTA = LATITUDE_DELTA * ASPECT_RATIO; let id = 0; -class DisplayLatLng extends React.Component { +class PolygonCreator extends React.Component { constructor(props) { super(props); @@ -77,6 +77,7 @@ class DisplayLatLng extends React.Component { return ( this.onPress(e)} @@ -115,6 +116,10 @@ class DisplayLatLng extends React.Component { } } +PolygonCreator.propTypes = { + provider: MapView.ProviderPropType, +}; + const styles = StyleSheet.create({ container: { ...StyleSheet.absoluteFillObject, @@ -147,4 +152,4 @@ const styles = StyleSheet.create({ }, }); -module.exports = DisplayLatLng; +module.exports = PolygonCreator; diff --git a/example/examples/PolylineCreator.js b/example/examples/PolylineCreator.js index 6bc7398d2..f3fbcd4a6 100644 --- a/example/examples/PolylineCreator.js +++ b/example/examples/PolylineCreator.js @@ -68,6 +68,7 @@ class PolylineCreator extends React.Component { return ( + + Clicking + and + dragging + the + map + will + cause + the + + + + parent + ScrollView + to + scroll. + When + using + a Google + Map + this only + works + if you + disable: + scroll, + zoom, + pitch, + rotate. + ... + It + would + be + nice + to + have + an + option + that + still + allows + zooming. + + + ); + } +} + +StaticMap.propTypes = { + provider: MapView.ProviderPropType, +}; + +const styles = StyleSheet.create({ + container: { + ...StyleSheet.absoluteFillObject, + justifyContent: 'flex-end', + alignItems: 'center', + }, + scrollview: { + alignItems: 'center', + paddingVertical: 40, + }, + map: { + width: 250, + height: 250, + }, +}); + +module.exports = StaticMap; diff --git a/example/examples/TakeSnapshot.js b/example/examples/TakeSnapshot.js index 8d8388c38..26022a4d5 100644 --- a/example/examples/TakeSnapshot.js +++ b/example/examples/TakeSnapshot.js @@ -45,6 +45,7 @@ class MarkerTypes extends React.Component { return ( { this.map = ref; }} style={styles.map} initialRegion={{ @@ -98,6 +99,10 @@ class MarkerTypes extends React.Component { } } +MarkerTypes.propTypes = { + provider: MapView.ProviderPropType, +}; + const styles = StyleSheet.create({ container: { ...StyleSheet.absoluteFillObject, diff --git a/example/examples/ViewsAsMarkers.js b/example/examples/ViewsAsMarkers.js index 7d7857d04..610699883 100644 --- a/example/examples/ViewsAsMarkers.js +++ b/example/examples/ViewsAsMarkers.js @@ -6,7 +6,6 @@ import { Dimensions, TouchableOpacity, } from 'react-native'; - import MapView from 'react-native-maps'; import PriceMarker from './PriceMarker'; @@ -18,7 +17,7 @@ const LONGITUDE = -122.4324; const LATITUDE_DELTA = 0.0922; const LONGITUDE_DELTA = LATITUDE_DELTA * ASPECT_RATIO; -class DisplayLatLng extends React.Component { +class ViewsAsMarkers extends React.Component { constructor(props) { super(props); @@ -49,6 +48,7 @@ class DisplayLatLng extends React.Component { return ( @@ -75,6 +75,10 @@ class DisplayLatLng extends React.Component { } } +ViewsAsMarkers.propTypes = { + provider: MapView.ProviderPropType, +}; + const styles = StyleSheet.create({ container: { ...StyleSheet.absoluteFillObject, @@ -107,4 +111,4 @@ const styles = StyleSheet.create({ }, }); -module.exports = DisplayLatLng; +module.exports = ViewsAsMarkers; diff --git a/example/ios/AirMapsExplorer.xcodeproj/project.pbxproj b/example/ios/AirMapsExplorer.xcodeproj/project.pbxproj index c36dd459a..2ed33f2e3 100644 --- a/example/ios/AirMapsExplorer.xcodeproj/project.pbxproj +++ b/example/ios/AirMapsExplorer.xcodeproj/project.pbxproj @@ -7,60 +7,42 @@ objects = { /* Begin PBXBuildFile section */ - 00C302E51ABCBA2D00DB3ED1 /* libRCTActionSheet.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302AC1ABCB8CE00DB3ED1 /* libRCTActionSheet.a */; }; - 00C302E71ABCBA2D00DB3ED1 /* libRCTGeolocation.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302BA1ABCB90400DB3ED1 /* libRCTGeolocation.a */; }; - 00C302E81ABCBA2D00DB3ED1 /* libRCTImage.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302C01ABCB91800DB3ED1 /* libRCTImage.a */; }; - 00C302E91ABCBA2D00DB3ED1 /* libRCTNetwork.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302DC1ABCB9D200DB3ED1 /* libRCTNetwork.a */; }; - 00C302EA1ABCBA2D00DB3ED1 /* libRCTVibration.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302E41ABCB9EE00DB3ED1 /* libRCTVibration.a */; }; - 00E356F31AD99517003FC87E /* AirMapsExplorerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 00E356F21AD99517003FC87E /* AirMapsExplorerTests.m */; }; - 11E015091C4AE70F008E4ED9 /* libAirMaps.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 11E015081C4AE706008E4ED9 /* libAirMaps.a */; }; - 133E29F31AD74F7200F7D852 /* libRCTLinking.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 78C398B91ACF4ADC00677621 /* libRCTLinking.a */; }; - 139105C61AF99C1200B5F7CC /* libRCTSettings.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 139105C11AF99BAD00B5F7CC /* libRCTSettings.a */; }; - 139FDEF61B0652A700C62182 /* libRCTWebSocket.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 139FDEF41B06529B00C62182 /* libRCTWebSocket.a */; }; 13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.m */; }; 13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB11A68108700A75B9A /* LaunchScreen.xib */; }; 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; }; 13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; }; - 146834051AC3E58100842450 /* libReact.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 146834041AC3E56700842450 /* libReact.a */; }; - 832341BD1AAA6AB300B99B32 /* libRCTText.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 832341B51AAA6A8300B99B32 /* libRCTText.a */; }; + 213CA8EA1D89F66A008623EC /* AIRGMSMarker.m in Sources */ = {isa = PBXBuildFile; fileRef = 213CA8DD1D89F66A008623EC /* AIRGMSMarker.m */; }; + 213CA8EB1D89F66A008623EC /* AIRGoogleMap.m in Sources */ = {isa = PBXBuildFile; fileRef = 213CA8DF1D89F66A008623EC /* AIRGoogleMap.m */; }; + 213CA8EC1D89F66A008623EC /* AIRGoogleMapCallout.m in Sources */ = {isa = PBXBuildFile; fileRef = 213CA8E11D89F66A008623EC /* AIRGoogleMapCallout.m */; }; + 213CA8ED1D89F66A008623EC /* AIRGoogleMapCalloutManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 213CA8E31D89F66A008623EC /* AIRGoogleMapCalloutManager.m */; }; + 213CA8EE1D89F66A008623EC /* AIRGoogleMapManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 213CA8E51D89F66A008623EC /* AIRGoogleMapManager.m */; }; + 213CA8EF1D89F66A008623EC /* AIRGoogleMapMarker.m in Sources */ = {isa = PBXBuildFile; fileRef = 213CA8E71D89F66A008623EC /* AIRGoogleMapMarker.m */; }; + 213CA8F01D89F66A008623EC /* AIRGoogleMapMarkerManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 213CA8E91D89F66A008623EC /* AIRGoogleMapMarkerManager.m */; }; + 2166AB291D82EC56007538D7 /* AIRMap.m in Sources */ = {isa = PBXBuildFile; fileRef = 2166AAFC1D82EC56007538D7 /* AIRMap.m */; }; + 2166AB2A1D82EC56007538D7 /* AIRMapCallout.m in Sources */ = {isa = PBXBuildFile; fileRef = 2166AAFE1D82EC56007538D7 /* AIRMapCallout.m */; }; + 2166AB2B1D82EC56007538D7 /* AIRMapCalloutManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 2166AB001D82EC56007538D7 /* AIRMapCalloutManager.m */; }; + 2166AB2C1D82EC56007538D7 /* AIRMapCircle.m in Sources */ = {isa = PBXBuildFile; fileRef = 2166AB021D82EC56007538D7 /* AIRMapCircle.m */; }; + 2166AB2D1D82EC56007538D7 /* AIRMapCircleManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 2166AB041D82EC56007538D7 /* AIRMapCircleManager.m */; }; + 2166AB2E1D82EC56007538D7 /* AIRMapCoordinate.m in Sources */ = {isa = PBXBuildFile; fileRef = 2166AB061D82EC56007538D7 /* AIRMapCoordinate.m */; }; + 2166AB2F1D82EC56007538D7 /* AIRMapManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 2166AB081D82EC56007538D7 /* AIRMapManager.m */; }; + 2166AB301D82EC56007538D7 /* AIRMapMarker.m in Sources */ = {isa = PBXBuildFile; fileRef = 2166AB0A1D82EC56007538D7 /* AIRMapMarker.m */; }; + 2166AB311D82EC56007538D7 /* AIRMapMarkerManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 2166AB0C1D82EC56007538D7 /* AIRMapMarkerManager.m */; }; + 2166AB321D82EC56007538D7 /* AIRMapPolygon.m in Sources */ = {isa = PBXBuildFile; fileRef = 2166AB0E1D82EC56007538D7 /* AIRMapPolygon.m */; }; + 2166AB331D82EC56007538D7 /* AIRMapPolygonManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 2166AB101D82EC56007538D7 /* AIRMapPolygonManager.m */; }; + 2166AB341D82EC56007538D7 /* AIRMapPolyline.m in Sources */ = {isa = PBXBuildFile; fileRef = 2166AB121D82EC56007538D7 /* AIRMapPolyline.m */; }; + 2166AB351D82EC56007538D7 /* AIRMapPolylineManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 2166AB141D82EC56007538D7 /* AIRMapPolylineManager.m */; }; + 2166AB361D82EC56007538D7 /* SMCalloutView.m in Sources */ = {isa = PBXBuildFile; fileRef = 2166AB171D82EC56007538D7 /* SMCalloutView.m */; }; + 2166AB3E1D82EC56007538D7 /* RCTConvert+MoreMapKit.m in Sources */ = {isa = PBXBuildFile; fileRef = 2166AB281D82EC56007538D7 /* RCTConvert+MoreMapKit.m */; }; + 21D346651D933B8C002BAD8A /* AIRMapUrlTile.m in Sources */ = {isa = PBXBuildFile; fileRef = 21D346621D933B8C002BAD8A /* AIRMapUrlTile.m */; }; + 21D346661D933B8C002BAD8A /* AIRMapUrlTileManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 21D346641D933B8C002BAD8A /* AIRMapUrlTileManager.m */; }; + 21E6570A1D77591400B75EE5 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 21E657091D77591400B75EE5 /* SystemConfiguration.framework */; }; + 21E6570C1D77591A00B75EE5 /* MobileCoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 21E6570B1D77591A00B75EE5 /* MobileCoreServices.framework */; }; + 21E6570E1D77591F00B75EE5 /* MapKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 21E6570D1D77591F00B75EE5 /* MapKit.framework */; }; + 21E657101D77594C00B75EE5 /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 21E6570F1D77594C00B75EE5 /* AudioToolbox.framework */; }; + C27EBA2BED74D74958F60ABC /* Pods_AirMapsExplorer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7C91D72410F775D78CACEBA8 /* Pods_AirMapsExplorer.framework */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ - 00C302AB1ABCB8CE00DB3ED1 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 134814201AA4EA6300B7C361; - remoteInfo = RCTActionSheet; - }; - 00C302B91ABCB90400DB3ED1 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 00C302B51ABCB90400DB3ED1 /* RCTGeolocation.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 134814201AA4EA6300B7C361; - remoteInfo = RCTGeolocation; - }; - 00C302BF1ABCB91800DB3ED1 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 00C302BB1ABCB91800DB3ED1 /* RCTImage.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 58B5115D1A9E6B3D00147676; - remoteInfo = RCTImage; - }; - 00C302DB1ABCB9D200DB3ED1 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 00C302D31ABCB9D200DB3ED1 /* RCTNetwork.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 58B511DB1A9E6C8500147676; - remoteInfo = RCTNetwork; - }; - 00C302E31ABCB9EE00DB3ED1 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 00C302DF1ABCB9EE00DB3ED1 /* RCTVibration.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 832C81801AAF6DEF007FA2F7; - remoteInfo = RCTVibration; - }; 00E356F41AD99517003FC87E /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 83CBB9F71A601CBA00E9B192 /* Project object */; @@ -68,63 +50,11 @@ remoteGlobalIDString = 13B07F861A680F5B00A75B9A; remoteInfo = AirMapsExplorer; }; - 11E015071C4AE706008E4ED9 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 11E015031C4AE706008E4ED9 /* AirMaps.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 11FA5C511C4A1296003AC2EE; - remoteInfo = AirMaps; - }; - 139105C01AF99BAD00B5F7CC /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 139105B61AF99BAD00B5F7CC /* RCTSettings.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 134814201AA4EA6300B7C361; - remoteInfo = RCTSettings; - }; - 139FDEF31B06529B00C62182 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 3C86DF461ADF2C930047B81A; - remoteInfo = RCTWebSocket; - }; - 146834031AC3E56700842450 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 83CBBA2E1A601D0E00E9B192; - remoteInfo = React; - }; - 78C398B81ACF4ADC00677621 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 134814201AA4EA6300B7C361; - remoteInfo = RCTLinking; - }; - 832341B41AAA6A8300B99B32 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 58B5119B1A9E6C1200147676; - remoteInfo = RCTText; - }; /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ 008F07F21AC5B25A0029DE68 /* main.jsbundle */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = main.jsbundle; sourceTree = ""; }; - 00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTActionSheet.xcodeproj; path = "../node_modules/react-native/Libraries/ActionSheetIOS/RCTActionSheet.xcodeproj"; sourceTree = ""; }; - 00C302B51ABCB90400DB3ED1 /* RCTGeolocation.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTGeolocation.xcodeproj; path = "../node_modules/react-native/Libraries/Geolocation/RCTGeolocation.xcodeproj"; sourceTree = ""; }; - 00C302BB1ABCB91800DB3ED1 /* RCTImage.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTImage.xcodeproj; path = "../node_modules/react-native/Libraries/Image/RCTImage.xcodeproj"; sourceTree = ""; }; - 00C302D31ABCB9D200DB3ED1 /* RCTNetwork.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTNetwork.xcodeproj; path = "../node_modules/react-native/Libraries/Network/RCTNetwork.xcodeproj"; sourceTree = ""; }; - 00C302DF1ABCB9EE00DB3ED1 /* RCTVibration.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTVibration.xcodeproj; path = "../node_modules/react-native/Libraries/Vibration/RCTVibration.xcodeproj"; sourceTree = ""; }; 00E356EE1AD99517003FC87E /* AirMapsExplorerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = AirMapsExplorerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - 00E356F11AD99517003FC87E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 00E356F21AD99517003FC87E /* AirMapsExplorerTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AirMapsExplorerTests.m; sourceTree = ""; }; - 11E015031C4AE706008E4ED9 /* AirMaps.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = AirMaps.xcodeproj; path = "../node_modules/react-native-maps/ios/AirMaps.xcodeproj"; sourceTree = ""; }; - 139105B61AF99BAD00B5F7CC /* RCTSettings.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTSettings.xcodeproj; path = "../node_modules/react-native/Libraries/Settings/RCTSettings.xcodeproj"; sourceTree = ""; }; - 139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTWebSocket.xcodeproj; path = "../node_modules/react-native/Libraries/WebSocket/RCTWebSocket.xcodeproj"; sourceTree = ""; }; 13B07F961A680F5B00A75B9A /* AirMapsExplorer.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = AirMapsExplorer.app; sourceTree = BUILT_PRODUCTS_DIR; }; 13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = AirMapsExplorer/AppDelegate.h; sourceTree = ""; }; 13B07FB01A68108700A75B9A /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AppDelegate.m; path = AirMapsExplorer/AppDelegate.m; sourceTree = ""; }; @@ -132,9 +62,66 @@ 13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = AirMapsExplorer/Images.xcassets; sourceTree = ""; }; 13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = AirMapsExplorer/Info.plist; sourceTree = ""; }; 13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = AirMapsExplorer/main.m; sourceTree = ""; }; - 146833FF1AC3E56700842450 /* React.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = React.xcodeproj; path = "../node_modules/react-native/React/React.xcodeproj"; sourceTree = ""; }; - 78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTLinking.xcodeproj; path = "../node_modules/react-native/Libraries/LinkingIOS/RCTLinking.xcodeproj"; sourceTree = ""; }; - 832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTText.xcodeproj; path = "../node_modules/react-native/Libraries/Text/RCTText.xcodeproj"; sourceTree = ""; }; + 213CA8DC1D89F66A008623EC /* AIRGMSMarker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRGMSMarker.h; sourceTree = ""; }; + 213CA8DD1D89F66A008623EC /* AIRGMSMarker.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRGMSMarker.m; sourceTree = ""; }; + 213CA8DE1D89F66A008623EC /* AIRGoogleMap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRGoogleMap.h; sourceTree = ""; }; + 213CA8DF1D89F66A008623EC /* AIRGoogleMap.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRGoogleMap.m; sourceTree = ""; }; + 213CA8E01D89F66A008623EC /* AIRGoogleMapCallout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRGoogleMapCallout.h; sourceTree = ""; }; + 213CA8E11D89F66A008623EC /* AIRGoogleMapCallout.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRGoogleMapCallout.m; sourceTree = ""; }; + 213CA8E21D89F66A008623EC /* AIRGoogleMapCalloutManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRGoogleMapCalloutManager.h; sourceTree = ""; }; + 213CA8E31D89F66A008623EC /* AIRGoogleMapCalloutManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRGoogleMapCalloutManager.m; sourceTree = ""; }; + 213CA8E41D89F66A008623EC /* AIRGoogleMapManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRGoogleMapManager.h; sourceTree = ""; }; + 213CA8E51D89F66A008623EC /* AIRGoogleMapManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRGoogleMapManager.m; sourceTree = ""; }; + 213CA8E61D89F66A008623EC /* AIRGoogleMapMarker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRGoogleMapMarker.h; sourceTree = ""; }; + 213CA8E71D89F66A008623EC /* AIRGoogleMapMarker.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRGoogleMapMarker.m; sourceTree = ""; }; + 213CA8E81D89F66A008623EC /* AIRGoogleMapMarkerManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRGoogleMapMarkerManager.h; sourceTree = ""; }; + 213CA8E91D89F66A008623EC /* AIRGoogleMapMarkerManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRGoogleMapMarkerManager.m; sourceTree = ""; }; + 2166AAF01D8233EC007538D7 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; + 2166AAF21D8233F9007538D7 /* CoreLocation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreLocation.framework; path = System/Library/Frameworks/CoreLocation.framework; sourceTree = SDKROOT; }; + 2166AAF41D823402007538D7 /* CoreText.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreText.framework; path = System/Library/Frameworks/CoreText.framework; sourceTree = SDKROOT; }; + 2166AAF61D823407007538D7 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; + 2166AAF81D82E9D0007538D7 /* React.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = React.framework; path = "Pods/../build/Debug-iphoneos/React.framework"; sourceTree = ""; }; + 2166AAFB1D82EC56007538D7 /* AIRMap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRMap.h; sourceTree = ""; }; + 2166AAFC1D82EC56007538D7 /* AIRMap.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRMap.m; sourceTree = ""; }; + 2166AAFD1D82EC56007538D7 /* AIRMapCallout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRMapCallout.h; sourceTree = ""; }; + 2166AAFE1D82EC56007538D7 /* AIRMapCallout.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRMapCallout.m; sourceTree = ""; }; + 2166AAFF1D82EC56007538D7 /* AIRMapCalloutManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRMapCalloutManager.h; sourceTree = ""; }; + 2166AB001D82EC56007538D7 /* AIRMapCalloutManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRMapCalloutManager.m; sourceTree = ""; }; + 2166AB011D82EC56007538D7 /* AIRMapCircle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRMapCircle.h; sourceTree = ""; }; + 2166AB021D82EC56007538D7 /* AIRMapCircle.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRMapCircle.m; sourceTree = ""; }; + 2166AB031D82EC56007538D7 /* AIRMapCircleManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRMapCircleManager.h; sourceTree = ""; }; + 2166AB041D82EC56007538D7 /* AIRMapCircleManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRMapCircleManager.m; sourceTree = ""; }; + 2166AB051D82EC56007538D7 /* AIRMapCoordinate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRMapCoordinate.h; sourceTree = ""; }; + 2166AB061D82EC56007538D7 /* AIRMapCoordinate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRMapCoordinate.m; sourceTree = ""; }; + 2166AB071D82EC56007538D7 /* AIRMapManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRMapManager.h; sourceTree = ""; }; + 2166AB081D82EC56007538D7 /* AIRMapManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRMapManager.m; sourceTree = ""; }; + 2166AB091D82EC56007538D7 /* AIRMapMarker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRMapMarker.h; sourceTree = ""; }; + 2166AB0A1D82EC56007538D7 /* AIRMapMarker.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRMapMarker.m; sourceTree = ""; }; + 2166AB0B1D82EC56007538D7 /* AIRMapMarkerManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRMapMarkerManager.h; sourceTree = ""; }; + 2166AB0C1D82EC56007538D7 /* AIRMapMarkerManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRMapMarkerManager.m; sourceTree = ""; }; + 2166AB0D1D82EC56007538D7 /* AIRMapPolygon.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRMapPolygon.h; sourceTree = ""; }; + 2166AB0E1D82EC56007538D7 /* AIRMapPolygon.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRMapPolygon.m; sourceTree = ""; }; + 2166AB0F1D82EC56007538D7 /* AIRMapPolygonManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRMapPolygonManager.h; sourceTree = ""; }; + 2166AB101D82EC56007538D7 /* AIRMapPolygonManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRMapPolygonManager.m; sourceTree = ""; }; + 2166AB111D82EC56007538D7 /* AIRMapPolyline.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRMapPolyline.h; sourceTree = ""; }; + 2166AB121D82EC56007538D7 /* AIRMapPolyline.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRMapPolyline.m; sourceTree = ""; }; + 2166AB131D82EC56007538D7 /* AIRMapPolylineManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRMapPolylineManager.h; sourceTree = ""; }; + 2166AB141D82EC56007538D7 /* AIRMapPolylineManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRMapPolylineManager.m; sourceTree = ""; }; + 2166AB161D82EC56007538D7 /* SMCalloutView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SMCalloutView.h; sourceTree = ""; }; + 2166AB171D82EC56007538D7 /* SMCalloutView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SMCalloutView.m; sourceTree = ""; }; + 2166AB271D82EC56007538D7 /* RCTConvert+MoreMapKit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "RCTConvert+MoreMapKit.h"; sourceTree = ""; }; + 2166AB281D82EC56007538D7 /* RCTConvert+MoreMapKit.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "RCTConvert+MoreMapKit.m"; sourceTree = ""; }; + 21D346611D933B8C002BAD8A /* AIRMapUrlTile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRMapUrlTile.h; sourceTree = ""; }; + 21D346621D933B8C002BAD8A /* AIRMapUrlTile.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRMapUrlTile.m; sourceTree = ""; }; + 21D346631D933B8C002BAD8A /* AIRMapUrlTileManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRMapUrlTileManager.h; sourceTree = ""; }; + 21D346641D933B8C002BAD8A /* AIRMapUrlTileManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRMapUrlTileManager.m; sourceTree = ""; }; + 21E657091D77591400B75EE5 /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; + 21E6570B1D77591A00B75EE5 /* MobileCoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MobileCoreServices.framework; path = System/Library/Frameworks/MobileCoreServices.framework; sourceTree = SDKROOT; }; + 21E6570D1D77591F00B75EE5 /* MapKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MapKit.framework; path = System/Library/Frameworks/MapKit.framework; sourceTree = SDKROOT; }; + 21E6570F1D77594C00B75EE5 /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = System/Library/Frameworks/AudioToolbox.framework; sourceTree = SDKROOT; }; + 2451EE03458E9BDA5F49B446 /* Pods-AirMapsExplorer.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AirMapsExplorer.debug.xcconfig"; path = "Pods/Target Support Files/Pods-AirMapsExplorer/Pods-AirMapsExplorer.debug.xcconfig"; sourceTree = ""; }; + 39293F18DE5A673E1BD8D397 /* Pods-AirMapsExplorer.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AirMapsExplorer.release.xcconfig"; path = "Pods/Target Support Files/Pods-AirMapsExplorer/Pods-AirMapsExplorer.release.xcconfig"; sourceTree = ""; }; + 7C91D72410F775D78CACEBA8 /* Pods_AirMapsExplorer.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_AirMapsExplorer.framework; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -149,102 +136,32 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 11E015091C4AE70F008E4ED9 /* libAirMaps.a in Frameworks */, - 146834051AC3E58100842450 /* libReact.a in Frameworks */, - 00C302E51ABCBA2D00DB3ED1 /* libRCTActionSheet.a in Frameworks */, - 00C302E71ABCBA2D00DB3ED1 /* libRCTGeolocation.a in Frameworks */, - 00C302E81ABCBA2D00DB3ED1 /* libRCTImage.a in Frameworks */, - 133E29F31AD74F7200F7D852 /* libRCTLinking.a in Frameworks */, - 00C302E91ABCBA2D00DB3ED1 /* libRCTNetwork.a in Frameworks */, - 139105C61AF99C1200B5F7CC /* libRCTSettings.a in Frameworks */, - 832341BD1AAA6AB300B99B32 /* libRCTText.a in Frameworks */, - 00C302EA1ABCBA2D00DB3ED1 /* libRCTVibration.a in Frameworks */, - 139FDEF61B0652A700C62182 /* libRCTWebSocket.a in Frameworks */, + 21E657101D77594C00B75EE5 /* AudioToolbox.framework in Frameworks */, + 21E6570E1D77591F00B75EE5 /* MapKit.framework in Frameworks */, + 21E6570C1D77591A00B75EE5 /* MobileCoreServices.framework in Frameworks */, + 21E6570A1D77591400B75EE5 /* SystemConfiguration.framework in Frameworks */, + C27EBA2BED74D74958F60ABC /* Pods_AirMapsExplorer.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ - 00C302A81ABCB8CE00DB3ED1 /* Products */ = { - isa = PBXGroup; - children = ( - 00C302AC1ABCB8CE00DB3ED1 /* libRCTActionSheet.a */, - ); - name = Products; - sourceTree = ""; - }; - 00C302B61ABCB90400DB3ED1 /* Products */ = { - isa = PBXGroup; - children = ( - 00C302BA1ABCB90400DB3ED1 /* libRCTGeolocation.a */, - ); - name = Products; - sourceTree = ""; - }; - 00C302BC1ABCB91800DB3ED1 /* Products */ = { + 051AB288C799B62BE091B88A /* Frameworks */ = { isa = PBXGroup; children = ( - 00C302C01ABCB91800DB3ED1 /* libRCTImage.a */, - ); - name = Products; - sourceTree = ""; - }; - 00C302D41ABCB9D200DB3ED1 /* Products */ = { - isa = PBXGroup; - children = ( - 00C302DC1ABCB9D200DB3ED1 /* libRCTNetwork.a */, - ); - name = Products; - sourceTree = ""; - }; - 00C302E01ABCB9EE00DB3ED1 /* Products */ = { - isa = PBXGroup; - children = ( - 00C302E41ABCB9EE00DB3ED1 /* libRCTVibration.a */, - ); - name = Products; - sourceTree = ""; - }; - 00E356EF1AD99517003FC87E /* AirMapsExplorerTests */ = { - isa = PBXGroup; - children = ( - 00E356F21AD99517003FC87E /* AirMapsExplorerTests.m */, - 00E356F01AD99517003FC87E /* Supporting Files */, - ); - path = AirMapsExplorerTests; - sourceTree = ""; - }; - 00E356F01AD99517003FC87E /* Supporting Files */ = { - isa = PBXGroup; - children = ( - 00E356F11AD99517003FC87E /* Info.plist */, - ); - name = "Supporting Files"; - sourceTree = ""; - }; - 11E015041C4AE706008E4ED9 /* Products */ = { - isa = PBXGroup; - children = ( - 11E015081C4AE706008E4ED9 /* libAirMaps.a */, - ); - name = Products; - sourceTree = ""; - }; - 139105B71AF99BAD00B5F7CC /* Products */ = { - isa = PBXGroup; - children = ( - 139105C11AF99BAD00B5F7CC /* libRCTSettings.a */, - ); - name = Products; - sourceTree = ""; - }; - 139FDEE71B06529A00C62182 /* Products */ = { - isa = PBXGroup; - children = ( - 139FDEF41B06529B00C62182 /* libRCTWebSocket.a */, - ); - name = Products; + 2166AAF81D82E9D0007538D7 /* React.framework */, + 2166AAF61D823407007538D7 /* CoreGraphics.framework */, + 2166AAF41D823402007538D7 /* CoreText.framework */, + 2166AAF21D8233F9007538D7 /* CoreLocation.framework */, + 2166AAF01D8233EC007538D7 /* QuartzCore.framework */, + 21E6570F1D77594C00B75EE5 /* AudioToolbox.framework */, + 21E6570D1D77591F00B75EE5 /* MapKit.framework */, + 21E6570B1D77591A00B75EE5 /* MobileCoreServices.framework */, + 21E657091D77591400B75EE5 /* SystemConfiguration.framework */, + 7C91D72410F775D78CACEBA8 /* Pods_AirMapsExplorer.framework */, + ); + name = Frameworks; sourceTree = ""; }; 13B07FAE1A68108700A75B9A /* AirMapsExplorer */ = { @@ -261,55 +178,96 @@ name = AirMapsExplorer; sourceTree = ""; }; - 146834001AC3E56700842450 /* Products */ = { + 213CA8DB1D89F66A008623EC /* AirGoogleMaps */ = { isa = PBXGroup; children = ( - 146834041AC3E56700842450 /* libReact.a */, - ); - name = Products; + 213CA8DC1D89F66A008623EC /* AIRGMSMarker.h */, + 213CA8DD1D89F66A008623EC /* AIRGMSMarker.m */, + 213CA8DE1D89F66A008623EC /* AIRGoogleMap.h */, + 213CA8DF1D89F66A008623EC /* AIRGoogleMap.m */, + 213CA8E01D89F66A008623EC /* AIRGoogleMapCallout.h */, + 213CA8E11D89F66A008623EC /* AIRGoogleMapCallout.m */, + 213CA8E21D89F66A008623EC /* AIRGoogleMapCalloutManager.h */, + 213CA8E31D89F66A008623EC /* AIRGoogleMapCalloutManager.m */, + 213CA8E41D89F66A008623EC /* AIRGoogleMapManager.h */, + 213CA8E51D89F66A008623EC /* AIRGoogleMapManager.m */, + 213CA8E61D89F66A008623EC /* AIRGoogleMapMarker.h */, + 213CA8E71D89F66A008623EC /* AIRGoogleMapMarker.m */, + 213CA8E81D89F66A008623EC /* AIRGoogleMapMarkerManager.h */, + 213CA8E91D89F66A008623EC /* AIRGoogleMapMarkerManager.m */, + ); + name = AirGoogleMaps; + path = ../../ios/AirGoogleMaps; sourceTree = ""; }; - 78C398B11ACF4ADC00677621 /* Products */ = { + 2166AAFA1D82EC56007538D7 /* AirMaps */ = { isa = PBXGroup; children = ( - 78C398B91ACF4ADC00677621 /* libRCTLinking.a */, - ); - name = Products; + 2166AAFB1D82EC56007538D7 /* AIRMap.h */, + 2166AAFC1D82EC56007538D7 /* AIRMap.m */, + 2166AAFD1D82EC56007538D7 /* AIRMapCallout.h */, + 2166AAFE1D82EC56007538D7 /* AIRMapCallout.m */, + 2166AAFF1D82EC56007538D7 /* AIRMapCalloutManager.h */, + 2166AB001D82EC56007538D7 /* AIRMapCalloutManager.m */, + 2166AB011D82EC56007538D7 /* AIRMapCircle.h */, + 2166AB021D82EC56007538D7 /* AIRMapCircle.m */, + 2166AB031D82EC56007538D7 /* AIRMapCircleManager.h */, + 2166AB041D82EC56007538D7 /* AIRMapCircleManager.m */, + 2166AB051D82EC56007538D7 /* AIRMapCoordinate.h */, + 2166AB061D82EC56007538D7 /* AIRMapCoordinate.m */, + 2166AB071D82EC56007538D7 /* AIRMapManager.h */, + 2166AB081D82EC56007538D7 /* AIRMapManager.m */, + 2166AB091D82EC56007538D7 /* AIRMapMarker.h */, + 2166AB0A1D82EC56007538D7 /* AIRMapMarker.m */, + 2166AB0B1D82EC56007538D7 /* AIRMapMarkerManager.h */, + 2166AB0C1D82EC56007538D7 /* AIRMapMarkerManager.m */, + 2166AB0D1D82EC56007538D7 /* AIRMapPolygon.h */, + 2166AB0E1D82EC56007538D7 /* AIRMapPolygon.m */, + 2166AB0F1D82EC56007538D7 /* AIRMapPolygonManager.h */, + 2166AB101D82EC56007538D7 /* AIRMapPolygonManager.m */, + 2166AB111D82EC56007538D7 /* AIRMapPolyline.h */, + 2166AB121D82EC56007538D7 /* AIRMapPolyline.m */, + 2166AB131D82EC56007538D7 /* AIRMapPolylineManager.h */, + 2166AB141D82EC56007538D7 /* AIRMapPolylineManager.m */, + 21D346611D933B8C002BAD8A /* AIRMapUrlTile.h */, + 21D346621D933B8C002BAD8A /* AIRMapUrlTile.m */, + 21D346631D933B8C002BAD8A /* AIRMapUrlTileManager.h */, + 21D346641D933B8C002BAD8A /* AIRMapUrlTileManager.m */, + 2166AB151D82EC56007538D7 /* Callout */, + 2166AB271D82EC56007538D7 /* RCTConvert+MoreMapKit.h */, + 2166AB281D82EC56007538D7 /* RCTConvert+MoreMapKit.m */, + ); + name = AirMaps; + path = ../../ios/AirMaps; sourceTree = ""; }; - 832341AE1AAA6A7D00B99B32 /* Libraries */ = { + 2166AB151D82EC56007538D7 /* Callout */ = { isa = PBXGroup; children = ( - 11E015031C4AE706008E4ED9 /* AirMaps.xcodeproj */, - 146833FF1AC3E56700842450 /* React.xcodeproj */, - 00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */, - 00C302B51ABCB90400DB3ED1 /* RCTGeolocation.xcodeproj */, - 00C302BB1ABCB91800DB3ED1 /* RCTImage.xcodeproj */, - 78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */, - 00C302D31ABCB9D200DB3ED1 /* RCTNetwork.xcodeproj */, - 139105B61AF99BAD00B5F7CC /* RCTSettings.xcodeproj */, - 832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */, - 00C302DF1ABCB9EE00DB3ED1 /* RCTVibration.xcodeproj */, - 139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */, - ); - name = Libraries; + 2166AB161D82EC56007538D7 /* SMCalloutView.h */, + 2166AB171D82EC56007538D7 /* SMCalloutView.m */, + ); + path = Callout; sourceTree = ""; }; - 832341B11AAA6A8300B99B32 /* Products */ = { + 76083FA9A1B0F1AEF4D2FCE7 /* Pods */ = { isa = PBXGroup; children = ( - 832341B51AAA6A8300B99B32 /* libRCTText.a */, + 2451EE03458E9BDA5F49B446 /* Pods-AirMapsExplorer.debug.xcconfig */, + 39293F18DE5A673E1BD8D397 /* Pods-AirMapsExplorer.release.xcconfig */, ); - name = Products; + name = Pods; sourceTree = ""; }; 83CBB9F61A601CBA00E9B192 = { isa = PBXGroup; children = ( + 213CA8DB1D89F66A008623EC /* AirGoogleMaps */, + 2166AAFA1D82EC56007538D7 /* AirMaps */, 13B07FAE1A68108700A75B9A /* AirMapsExplorer */, - 832341AE1AAA6A7D00B99B32 /* Libraries */, - 00E356EF1AD99517003FC87E /* AirMapsExplorerTests */, 83CBBA001A601CBA00E9B192 /* Products */, + 76083FA9A1B0F1AEF4D2FCE7 /* Pods */, + 051AB288C799B62BE091B88A /* Frameworks */, ); indentWidth = 2; sourceTree = ""; @@ -349,10 +307,16 @@ isa = PBXNativeTarget; buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "AirMapsExplorer" */; buildPhases = ( + DEE1DC9F05F890EC3C87C39A /* Check Pods Manifest.lock */, + 53BB7F61AC8C3BE47A838FC0 /* 📦 Check Pods Manifest.lock */, 13B07F871A680F5B00A75B9A /* Sources */, 13B07F8C1A680F5B00A75B9A /* Frameworks */, 13B07F8E1A680F5B00A75B9A /* Resources */, 00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */, + D71F7E633EDE287637BD0861 /* 📦 Embed Pods Frameworks */, + 1ED7E90E82F1447B3BDF7F89 /* 📦 Copy Pods Resources */, + 39894B48A7C87B9F345BABA2 /* Embed Pods Frameworks */, + 82539956530080D9C27BC6A0 /* Copy Pods Resources */, ); buildRules = ( ); @@ -389,52 +353,6 @@ mainGroup = 83CBB9F61A601CBA00E9B192; productRefGroup = 83CBBA001A601CBA00E9B192 /* Products */; projectDirPath = ""; - projectReferences = ( - { - ProductGroup = 11E015041C4AE706008E4ED9 /* Products */; - ProjectRef = 11E015031C4AE706008E4ED9 /* AirMaps.xcodeproj */; - }, - { - ProductGroup = 00C302A81ABCB8CE00DB3ED1 /* Products */; - ProjectRef = 00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */; - }, - { - ProductGroup = 00C302B61ABCB90400DB3ED1 /* Products */; - ProjectRef = 00C302B51ABCB90400DB3ED1 /* RCTGeolocation.xcodeproj */; - }, - { - ProductGroup = 00C302BC1ABCB91800DB3ED1 /* Products */; - ProjectRef = 00C302BB1ABCB91800DB3ED1 /* RCTImage.xcodeproj */; - }, - { - ProductGroup = 78C398B11ACF4ADC00677621 /* Products */; - ProjectRef = 78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */; - }, - { - ProductGroup = 00C302D41ABCB9D200DB3ED1 /* Products */; - ProjectRef = 00C302D31ABCB9D200DB3ED1 /* RCTNetwork.xcodeproj */; - }, - { - ProductGroup = 139105B71AF99BAD00B5F7CC /* Products */; - ProjectRef = 139105B61AF99BAD00B5F7CC /* RCTSettings.xcodeproj */; - }, - { - ProductGroup = 832341B11AAA6A8300B99B32 /* Products */; - ProjectRef = 832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */; - }, - { - ProductGroup = 00C302E01ABCB9EE00DB3ED1 /* Products */; - ProjectRef = 00C302DF1ABCB9EE00DB3ED1 /* RCTVibration.xcodeproj */; - }, - { - ProductGroup = 139FDEE71B06529A00C62182 /* Products */; - ProjectRef = 139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */; - }, - { - ProductGroup = 146834001AC3E56700842450 /* Products */; - ProjectRef = 146833FF1AC3E56700842450 /* React.xcodeproj */; - }, - ); projectRoot = ""; targets = ( 13B07F861A680F5B00A75B9A /* AirMapsExplorer */, @@ -443,86 +361,6 @@ }; /* End PBXProject section */ -/* Begin PBXReferenceProxy section */ - 00C302AC1ABCB8CE00DB3ED1 /* libRCTActionSheet.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libRCTActionSheet.a; - remoteRef = 00C302AB1ABCB8CE00DB3ED1 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 00C302BA1ABCB90400DB3ED1 /* libRCTGeolocation.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libRCTGeolocation.a; - remoteRef = 00C302B91ABCB90400DB3ED1 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 00C302C01ABCB91800DB3ED1 /* libRCTImage.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libRCTImage.a; - remoteRef = 00C302BF1ABCB91800DB3ED1 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 00C302DC1ABCB9D200DB3ED1 /* libRCTNetwork.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libRCTNetwork.a; - remoteRef = 00C302DB1ABCB9D200DB3ED1 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 00C302E41ABCB9EE00DB3ED1 /* libRCTVibration.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libRCTVibration.a; - remoteRef = 00C302E31ABCB9EE00DB3ED1 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 11E015081C4AE706008E4ED9 /* libAirMaps.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libAirMaps.a; - remoteRef = 11E015071C4AE706008E4ED9 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 139105C11AF99BAD00B5F7CC /* libRCTSettings.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libRCTSettings.a; - remoteRef = 139105C01AF99BAD00B5F7CC /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 139FDEF41B06529B00C62182 /* libRCTWebSocket.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libRCTWebSocket.a; - remoteRef = 139FDEF31B06529B00C62182 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 146834041AC3E56700842450 /* libReact.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libReact.a; - remoteRef = 146834031AC3E56700842450 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 78C398B91ACF4ADC00677621 /* libRCTLinking.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libRCTLinking.a; - remoteRef = 78C398B81ACF4ADC00677621 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 832341B51AAA6A8300B99B32 /* libRCTText.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libRCTText.a; - remoteRef = 832341B41AAA6A8300B99B32 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; -/* End PBXReferenceProxy section */ - /* Begin PBXResourcesBuildPhase section */ 00E356EC1AD99517003FC87E /* Resources */ = { isa = PBXResourcesBuildPhase; @@ -557,6 +395,96 @@ shellPath = /bin/sh; shellScript = "../node_modules/react-native/packager/react-native-xcode.sh"; }; + 1ED7E90E82F1447B3BDF7F89 /* 📦 Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "📦 Copy Pods Resources"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-AirMapsExplorer/Pods-AirMapsExplorer-resources.sh\"\n"; + showEnvVarsInLog = 0; + }; + 39894B48A7C87B9F345BABA2 /* Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Embed Pods Frameworks"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-AirMapsExplorer/Pods-AirMapsExplorer-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + 53BB7F61AC8C3BE47A838FC0 /* 📦 Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "📦 Check Pods Manifest.lock"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n"; + showEnvVarsInLog = 0; + }; + 82539956530080D9C27BC6A0 /* Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Copy Pods Resources"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-AirMapsExplorer/Pods-AirMapsExplorer-resources.sh\"\n"; + showEnvVarsInLog = 0; + }; + D71F7E633EDE287637BD0861 /* 📦 Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "📦 Embed Pods Frameworks"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-AirMapsExplorer/Pods-AirMapsExplorer-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + DEE1DC9F05F890EC3C87C39A /* Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Check Pods Manifest.lock"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n"; + showEnvVarsInLog = 0; + }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ @@ -564,7 +492,6 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 00E356F31AD99517003FC87E /* AirMapsExplorerTests.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -572,8 +499,32 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 2166AB2D1D82EC56007538D7 /* AIRMapCircleManager.m in Sources */, + 21D346651D933B8C002BAD8A /* AIRMapUrlTile.m in Sources */, + 2166AB2A1D82EC56007538D7 /* AIRMapCallout.m in Sources */, + 213CA8F01D89F66A008623EC /* AIRGoogleMapMarkerManager.m in Sources */, + 213CA8EF1D89F66A008623EC /* AIRGoogleMapMarker.m in Sources */, + 2166AB2C1D82EC56007538D7 /* AIRMapCircle.m in Sources */, + 213CA8ED1D89F66A008623EC /* AIRGoogleMapCalloutManager.m in Sources */, + 21D346661D933B8C002BAD8A /* AIRMapUrlTileManager.m in Sources */, + 213CA8EC1D89F66A008623EC /* AIRGoogleMapCallout.m in Sources */, + 213CA8EB1D89F66A008623EC /* AIRGoogleMap.m in Sources */, + 2166AB301D82EC56007538D7 /* AIRMapMarker.m in Sources */, + 2166AB321D82EC56007538D7 /* AIRMapPolygon.m in Sources */, 13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */, + 2166AB3E1D82EC56007538D7 /* RCTConvert+MoreMapKit.m in Sources */, 13B07FC11A68108700A75B9A /* main.m in Sources */, + 2166AB331D82EC56007538D7 /* AIRMapPolygonManager.m in Sources */, + 213CA8EE1D89F66A008623EC /* AIRGoogleMapManager.m in Sources */, + 2166AB2B1D82EC56007538D7 /* AIRMapCalloutManager.m in Sources */, + 2166AB361D82EC56007538D7 /* SMCalloutView.m in Sources */, + 2166AB351D82EC56007538D7 /* AIRMapPolylineManager.m in Sources */, + 2166AB291D82EC56007538D7 /* AIRMap.m in Sources */, + 2166AB2E1D82EC56007538D7 /* AIRMapCoordinate.m in Sources */, + 213CA8EA1D89F66A008623EC /* AIRGMSMarker.m in Sources */, + 2166AB341D82EC56007538D7 /* AIRMapPolyline.m in Sources */, + 2166AB2F1D82EC56007538D7 /* AIRMapManager.m in Sources */, + 2166AB311D82EC56007538D7 /* AIRMapMarkerManager.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -641,9 +592,15 @@ }; 13B07F941A680F5B00A75B9A /* Debug */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 2451EE03458E9BDA5F49B446 /* Pods-AirMapsExplorer.debug.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; DEAD_CODE_STRIPPING = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/build/Debug-iphoneos", + ); + GCC_TREAT_WARNINGS_AS_ERRORS = YES; HEADER_SEARCH_PATHS = ( "$(inherited)", /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, @@ -651,10 +608,6 @@ ); INFOPLIST_FILE = AirMapsExplorer/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - OTHER_LDFLAGS = ( - "-ObjC", - "-lc++", - ); PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = AirMapsExplorer; }; @@ -662,8 +615,14 @@ }; 13B07F951A680F5B00A75B9A /* Release */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 39293F18DE5A673E1BD8D397 /* Pods-AirMapsExplorer.release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/build/Debug-iphoneos", + ); + GCC_TREAT_WARNINGS_AS_ERRORS = YES; HEADER_SEARCH_PATHS = ( "$(inherited)", /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, @@ -671,10 +630,6 @@ ); INFOPLIST_FILE = AirMapsExplorer/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - OTHER_LDFLAGS = ( - "-ObjC", - "-lc++", - ); PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = AirMapsExplorer; }; @@ -720,7 +675,7 @@ /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, "$(SRCROOT)/../node_modules/react-native/React/**", ); - IPHONEOS_DEPLOYMENT_TARGET = 7.0; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -760,7 +715,7 @@ /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, "$(SRCROOT)/../node_modules/react-native/React/**", ); - IPHONEOS_DEPLOYMENT_TARGET = 7.0; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; VALIDATE_PRODUCT = YES; diff --git a/example/ios/AirMapsExplorer/AppDelegate.m b/example/ios/AirMapsExplorer/AppDelegate.m index c6c639d03..91ae54c48 100644 --- a/example/ios/AirMapsExplorer/AppDelegate.m +++ b/example/ios/AirMapsExplorer/AppDelegate.m @@ -11,12 +11,16 @@ #import "RCTRootView.h" +#import + @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { NSURL *jsCodeLocation; + [GMSServices provideAPIKey:@"AIzaSyAeHIC4IG7XKT2Ls5Ti_YZV-6DHQk6dVHE"]; + /** * Loading JavaScript code - uncomment the one you want. * diff --git a/example/ios/Podfile b/example/ios/Podfile new file mode 100644 index 000000000..085aad454 --- /dev/null +++ b/example/ios/Podfile @@ -0,0 +1,50 @@ +# You Podfile should look similar to this file. Whether you use_frameworks! or not, the following configuration should work. +# +# However if you DO NOT use_frameworks! and you prefer to install pods instead of +# dragging the AirMaps directory into your project, refer to the comments below (steps 1~4) + +source 'https://github.com/CocoaPods/Specs.git' + +platform :ios, '8.0' +use_frameworks! + +target 'AirMapsExplorer' do + pod 'React', path: '../node_modules/react-native', :subspecs => [ + 'Core', + 'RCTActionSheet', + 'RCTGeolocation', + 'RCTImage', + 'RCTLinkingIOS', + 'RCTNetwork', + 'RCTSettings', + 'RCTText', + 'RCTVibration', + 'RCTWebSocket' + ] + +# when not using frameworks we can do this instead of including the source files in our project (1/4): +# pod 'react-native-maps', path: '../../' +# pod 'react-native-google-maps', path: '../../' # <~~ if you need GoogleMaps support on iOS + +# when not using frameworks we can remove this line (2/4): + pod 'GoogleMaps' # <~~ remove this line if you do not want to support GoogleMaps on iOS +end + +# when not using frameworks this might be necessary, but try without it first and see if `pod install` works (3/4): +# THIS IS ONLY NECESSARY IF YOU NEED GoogleMaps SUPPORT +# pre_install do |installer| + # # copied from https://github.com/CocoaPods/CocoaPods/issues/2926 + # # workaround for https://github.com/CocoaPods/CocoaPods/issues/3289 + # def installer.verify_no_static_framework_transitive_dependencies; end +# end + +# when not using frameworks (4/4): +# THIS IS ONLY NECESSARY IF YOU NEED GoogleMaps SUPPORT +# #Crud, this shouldn't be necessary, but https://github.com/CocoaPods/CocoaPods/issues/5429 +# post_install do |installer| +# installer.pods_project.targets.each do |target| +# target.build_configurations.each do |config| +# config.build_settings['CLANG_ENABLE_MODULES'] = 'NO' +# end +# end +# end diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock new file mode 100644 index 000000000..9314559fd --- /dev/null +++ b/example/ios/Podfile.lock @@ -0,0 +1,51 @@ +PODS: + - GoogleMaps (2.0.1): + - GoogleMaps/Maps (= 2.0.1) + - GoogleMaps/Base (2.0.1) + - GoogleMaps/Maps (2.0.1): + - GoogleMaps/Base (= 2.0.1) + - React/Core (0.32.0): + - React/CSSLayout + - React/CSSLayout (0.32.0) + - React/RCTActionSheet (0.32.0): + - React/Core + - React/RCTGeolocation (0.32.0): + - React/Core + - React/RCTImage (0.32.0): + - React/Core + - React/RCTNetwork + - React/RCTLinkingIOS (0.32.0): + - React/Core + - React/RCTNetwork (0.32.0): + - React/Core + - React/RCTSettings (0.32.0): + - React/Core + - React/RCTText (0.32.0): + - React/Core + - React/RCTVibration (0.32.0): + - React/Core + - React/RCTWebSocket (0.32.0): + - React/Core + +DEPENDENCIES: + - GoogleMaps + - React/Core (from `../node_modules/react-native`) + - React/RCTActionSheet (from `../node_modules/react-native`) + - React/RCTGeolocation (from `../node_modules/react-native`) + - React/RCTImage (from `../node_modules/react-native`) + - React/RCTLinkingIOS (from `../node_modules/react-native`) + - React/RCTNetwork (from `../node_modules/react-native`) + - React/RCTSettings (from `../node_modules/react-native`) + - React/RCTText (from `../node_modules/react-native`) + - React/RCTVibration (from `../node_modules/react-native`) + - React/RCTWebSocket (from `../node_modules/react-native`) + +EXTERNAL SOURCES: + React: + :path: "../node_modules/react-native" + +SPEC CHECKSUMS: + GoogleMaps: f09da64fc987c1aa29394567c3cab5a3df83c402 + React: 0245b401173a94a5fba0f440aab3fb2f79b738f3 + +COCOAPODS: 0.39.0 diff --git a/example/package.json b/example/package.json index a379ea9a2..788629857 100644 --- a/example/package.json +++ b/example/package.json @@ -10,7 +10,7 @@ }, "dependencies": { "react": "15.3.0", - "react-native": "^0.32.0", + "react-native": "0.32.0", "react-native-maps": "../" }, "devDependencies": { diff --git a/ios/AirGoogleMaps/AIRGMSMarker.h b/ios/AirGoogleMaps/AIRGMSMarker.h new file mode 100644 index 000000000..baf89341d --- /dev/null +++ b/ios/AirGoogleMaps/AIRGMSMarker.h @@ -0,0 +1,23 @@ +// +// AIRGMSMarker.h +// AirMaps +// +// Created by Gil Birman on 9/5/16. +// + +#import +#import "UIView+React.h" + +@class AIRGoogleMapMarker; + +@interface AIRGMSMarker : GMSMarker +@property (nonatomic, strong) NSString *identifier; +@property (nonatomic, weak) AIRGoogleMapMarker *fakeMarker; +@property (nonatomic, copy) RCTBubblingEventBlock onPress; +@end + + +@protocol AIRGMSMarkerDelegate +@required +-(void)didTapMarker; +@end diff --git a/ios/AirGoogleMaps/AIRGMSMarker.m b/ios/AirGoogleMaps/AIRGMSMarker.m new file mode 100644 index 000000000..4e7fdfb09 --- /dev/null +++ b/ios/AirGoogleMaps/AIRGMSMarker.m @@ -0,0 +1,12 @@ +// +// AIRGMSMarker.m +// AirMaps +// +// Created by Gil Birman on 9/5/16. +// + +#import "AIRGMSMarker.h" + +@implementation AIRGMSMarker + +@end diff --git a/ios/AirGoogleMaps/AIRGoogleMap.h b/ios/AirGoogleMaps/AIRGoogleMap.h new file mode 100644 index 000000000..ae3b36d34 --- /dev/null +++ b/ios/AirGoogleMaps/AIRGoogleMap.h @@ -0,0 +1,42 @@ +// +// AIRGoogleMap.h +// AirMaps +// +// Created by Gil Birman on 9/1/16. +// + +#import +#import "RCTComponent.h" +#import +#import +#import "RCTConvert+MapKit.h" +#import "AIRGMSMarker.h" + +@interface AIRGoogleMap : GMSMapView + +// TODO: don't use MK region? +@property (nonatomic, assign) MKCoordinateRegion initialRegion; +@property (nonatomic, assign) MKCoordinateRegion region; +@property (nonatomic, copy) RCTBubblingEventBlock onPress; +@property (nonatomic, copy) RCTBubblingEventBlock onLongPress; +@property (nonatomic, copy) RCTBubblingEventBlock onMarkerPress; +@property (nonatomic, copy) RCTBubblingEventBlock onChange; +@property (nonatomic, copy) RCTDirectEventBlock onRegionChange; +@property (nonatomic, copy) RCTDirectEventBlock onRegionChangeComplete; +@property (nonatomic, strong) NSMutableArray *markers; + +@property (nonatomic, assign) BOOL showsBuildings; +@property (nonatomic, assign) BOOL showsTraffic; +@property (nonatomic, assign) BOOL showsCompass; +@property (nonatomic, assign) BOOL scrollEnabled; +@property (nonatomic, assign) BOOL zoomEnabled; +@property (nonatomic, assign) BOOL rotateEnabled; +@property (nonatomic, assign) BOOL pitchEnabled; + +- (BOOL)didTapMarker:(GMSMarker *)marker; +- (void)didTapAtCoordinate:(CLLocationCoordinate2D)coordinate; +- (void)didLongPressAtCoordinate:(CLLocationCoordinate2D)coordinate; +- (void)didChangeCameraPosition:(GMSCameraPosition *)position; +- (void)idleAtCameraPosition:(GMSCameraPosition *)position; + +@end diff --git a/ios/AirGoogleMaps/AIRGoogleMap.m b/ios/AirGoogleMaps/AIRGoogleMap.m new file mode 100644 index 000000000..d38188d56 --- /dev/null +++ b/ios/AirGoogleMaps/AIRGoogleMap.m @@ -0,0 +1,208 @@ +// +// AIRGoogleMap.m +// AirMaps +// +// Created by Gil Birman on 9/1/16. +// + +#import "AIRGoogleMap.h" +#import "AIRGoogleMapMarker.h" +#import +#import +#import "RCTConvert+MapKit.h" +#import "UIView+React.h" + +id cameraPositionAsJSON(GMSCameraPosition *position) { + // todo: convert zoom to delta lat/lng + return @{ + @"latitude": [NSNumber numberWithDouble:position.target.latitude], + @"longitude": [NSNumber numberWithDouble:position.target.longitude], + @"zoom": [NSNumber numberWithDouble:position.zoom], + }; +} + +GMSCameraPosition* makeGMSCameraPositionFromMKCoordinateRegionOfMap(GMSMapView *map, MKCoordinateRegion region) { + float latitudeDelta = region.span.latitudeDelta * 0.5; + float longitudeDelta = region.span.longitudeDelta * 0.5; + + CLLocationCoordinate2D a = CLLocationCoordinate2DMake(region.center.latitude + latitudeDelta, + region.center.longitude + longitudeDelta); + CLLocationCoordinate2D b = CLLocationCoordinate2DMake(region.center.latitude - latitudeDelta, + region.center.longitude - longitudeDelta); + GMSCoordinateBounds *bounds = [[GMSCoordinateBounds alloc] initWithCoordinate:a coordinate:b]; + return [map cameraForBounds:bounds insets:UIEdgeInsetsZero]; +} + +@interface AIRGoogleMap () + +- (id)eventFromCoordinate:(CLLocationCoordinate2D)coordinate; + +@end + +@implementation AIRGoogleMap +{ + NSMutableArray *_reactSubviews; + BOOL _initialRegionSet; +} + +- (instancetype)init +{ + if ((self = [super init])) { + _reactSubviews = [NSMutableArray new]; + _markers = [NSMutableArray array]; + _initialRegionSet = false; + } + return self; +} +- (id)eventFromCoordinate:(CLLocationCoordinate2D)coordinate { + + CGPoint touchPoint = [self.projection pointForCoordinate:coordinate]; + + return @{ + @"coordinate": @{ + @"latitude": @(coordinate.latitude), + @"longitude": @(coordinate.longitude), + }, + @"position": @{ + @"x": @(touchPoint.x), + @"y": @(touchPoint.y), + }, + }; +} + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wobjc-missing-super-calls" +- (void)insertReactSubview:(id)subview atIndex:(NSInteger)atIndex { + // Our desired API is to pass up markers/overlays as children to the mapview component. + // This is where we intercept them and do the appropriate underlying mapview action. + if ([subview isKindOfClass:[AIRGoogleMapMarker class]]) { + AIRGoogleMapMarker *marker = (AIRGoogleMapMarker*)subview; + marker.realMarker.map = self; + [self.markers addObject:marker]; + } + [_reactSubviews insertObject:(UIView *)subview atIndex:(NSUInteger) atIndex]; +} +#pragma clang diagnostic pop + + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wobjc-missing-super-calls" +- (void)removeReactSubview:(id)subview { + // similarly, when the children are being removed we have to do the appropriate + // underlying mapview action here. + if ([subview isKindOfClass:[AIRGoogleMapMarker class]]) { + AIRGoogleMapMarker *marker = (AIRGoogleMapMarker*)subview; + marker.realMarker.map = nil; + [self.markers removeObject:marker]; + } + [_reactSubviews removeObject:(UIView *)subview]; +} +#pragma clang diagnostic pop + +- (void)setInitialRegion:(MKCoordinateRegion)initialRegion { + if (_initialRegionSet) return; + _initialRegionSet = true; + self.camera = makeGMSCameraPositionFromMKCoordinateRegionOfMap(self, initialRegion); +} + +- (void)setRegion:(MKCoordinateRegion)region { + // TODO: The JS component is repeatedly setting region unnecessarily. We might want to deal with that in here. + self.camera = makeGMSCameraPositionFromMKCoordinateRegionOfMap(self, region); +} + +- (BOOL)didTapMarker:(GMSMarker *)marker { + AIRGMSMarker *airMarker = (AIRGMSMarker *)marker; + + id event = @{@"action": @"marker-press", + @"id": airMarker.identifier ?: @"unknown", + }; + + if (airMarker.onPress) airMarker.onPress(event); + if (self.onMarkerPress) self.onMarkerPress(event); + + // TODO: not sure why this is necessary + [self setSelectedMarker:marker]; + return NO; +} + +- (void)didTapAtCoordinate:(CLLocationCoordinate2D)coordinate { + if (!self.onPress) return; + self.onPress([self eventFromCoordinate:coordinate]); +} + +- (void)didLongPressAtCoordinate:(CLLocationCoordinate2D)coordinate { + if (!self.onLongPress) return; + self.onLongPress([self eventFromCoordinate:coordinate]); +} + +- (void)didChangeCameraPosition:(GMSCameraPosition *)position { + id event = @{@"continuous": @YES, + @"region": cameraPositionAsJSON(position), + }; + if (self.onChange) self.onChange(event); +} + +- (void)idleAtCameraPosition:(GMSCameraPosition *)position { + id event = @{@"continuous": @NO, + @"region": cameraPositionAsJSON(position), + }; + if (self.onChange) self.onChange(event); // complete +} + + +- (void)setScrollEnabled:(BOOL)scrollEnabled { + self.settings.scrollGestures = scrollEnabled; +} + +- (BOOL)scrollEnabled { + return self.settings.scrollGestures; +} + +- (void)setZoomEnabled:(BOOL)zoomEnabled { + self.settings.zoomGestures = zoomEnabled; +} + +- (BOOL)zoomEnabled { + return self.settings.zoomGestures; +} + +- (void)setRotateEnabled:(BOOL)rotateEnabled { + self.settings.rotateGestures = rotateEnabled; +} + +- (BOOL)rotateEnabled { + return self.settings.rotateGestures; +} + +- (void)setPitchEnabled:(BOOL)pitchEnabled { + self.settings.tiltGestures = pitchEnabled; +} + +- (BOOL)pitchEnabled { + return self.settings.tiltGestures; +} + +- (void)setShowsTraffic:(BOOL)showsTraffic { + self.trafficEnabled = showsTraffic; +} + +- (BOOL)showsTraffic { + return self.trafficEnabled; +} + +- (void)setShowsBuildings:(BOOL)showsBuildings { + self.buildingsEnabled = showsBuildings; +} + +- (BOOL)showsBuildings { + return self.buildingsEnabled; +} + +- (void)setShowsCompass:(BOOL)showsCompass { + self.settings.compassButton = showsCompass; +} + +- (BOOL)showsCompass { + return self.settings.compassButton; +} +@end diff --git a/ios/AirGoogleMaps/AIRGoogleMapCallout.h b/ios/AirGoogleMaps/AIRGoogleMapCallout.h new file mode 100644 index 000000000..61558e6bc --- /dev/null +++ b/ios/AirGoogleMaps/AIRGoogleMapCallout.h @@ -0,0 +1,15 @@ +// +// AIRGoogleMapCallout.h +// AirMaps +// +// Created by Gil Birman on 9/6/16. +// +// + +#import +#import "RCTView.h" + +@interface AIRGoogleMapCallout : UIView +@property (nonatomic, assign) BOOL tooltip; +@property (nonatomic, copy) RCTBubblingEventBlock onPress; +@end diff --git a/ios/AirGoogleMaps/AIRGoogleMapCallout.m b/ios/AirGoogleMaps/AIRGoogleMapCallout.m new file mode 100644 index 000000000..c64a6e03b --- /dev/null +++ b/ios/AirGoogleMaps/AIRGoogleMapCallout.m @@ -0,0 +1,15 @@ +// +// AIRGoogleMapCallout.m +// AirMaps +// +// Created by Gil Birman on 9/6/16. +// +// + +#import "AIRGoogleMapCallout.h" +#import "RCTUtils.h" +#import "RCTView.h" +#import "RCTBridge.h" + +@implementation AIRGoogleMapCallout +@end diff --git a/ios/AirGoogleMaps/AIRGoogleMapCalloutManager.h b/ios/AirGoogleMaps/AIRGoogleMapCalloutManager.h new file mode 100644 index 000000000..be0e1a72f --- /dev/null +++ b/ios/AirGoogleMaps/AIRGoogleMapCalloutManager.h @@ -0,0 +1,12 @@ +// +// AIRGoogleMapCalloutManager.h +// AirMaps +// +// Created by Gil Birman on 9/6/16. +// +// +#import "RCTViewManager.h" + +@interface AIRGoogleMapCalloutManager : RCTViewManager + +@end diff --git a/ios/AirGoogleMaps/AIRGoogleMapCalloutManager.m b/ios/AirGoogleMaps/AIRGoogleMapCalloutManager.m new file mode 100644 index 000000000..9a2a20998 --- /dev/null +++ b/ios/AirGoogleMaps/AIRGoogleMapCalloutManager.m @@ -0,0 +1,25 @@ +// +// AIRGoogleMapCalloutManager.m +// AirMaps +// +// Created by Gil Birman on 9/6/16. +// +// + +#import "AIRGoogleMapCalloutManager.h" +#import "AIRGoogleMapCallout.h" +#import "RCTView.h" + +@implementation AIRGoogleMapCalloutManager +RCT_EXPORT_MODULE() + +- (UIView *)view +{ + AIRGoogleMapCallout *callout = [AIRGoogleMapCallout new]; + return callout; +} + +RCT_EXPORT_VIEW_PROPERTY(tooltip, BOOL) +RCT_EXPORT_VIEW_PROPERTY(onPress, RCTBubblingEventBlock) + +@end diff --git a/ios/AirGoogleMaps/AIRGoogleMapManager.h b/ios/AirGoogleMaps/AIRGoogleMapManager.h new file mode 100644 index 000000000..b726eae65 --- /dev/null +++ b/ios/AirGoogleMaps/AIRGoogleMapManager.h @@ -0,0 +1,12 @@ +// +// AIRGoogleMapManager.h +// AirMaps +// +// Created by Gil Birman on 9/1/16. +// + +#import "RCTViewManager.h" + +@interface AIRGoogleMapManager : RCTViewManager + +@end diff --git a/ios/AirGoogleMaps/AIRGoogleMapManager.m b/ios/AirGoogleMaps/AIRGoogleMapManager.m new file mode 100644 index 000000000..d42a29724 --- /dev/null +++ b/ios/AirGoogleMaps/AIRGoogleMapManager.m @@ -0,0 +1,174 @@ +// +// AIRGoogleMapManager.m +// AirMaps +// +// Created by Gil Birman on 9/1/16. +// + + +#import "AIRGoogleMapManager.h" +#import "RCTViewManager.h" +#import "RCTBridge.h" +#import "RCTUIManager.h" +#import "RCTConvert+CoreLocation.h" +#import "RCTConvert+MapKit.h" +#import "RCTEventDispatcher.h" +#import "AIRGoogleMap.h" +#import "UIView+React.h" +#import "AIRMapMarker.h" +#import "RCTViewManager.h" +#import "RCTConvert.h" +#import "AIRMapPolyline.h" +#import "AIRMapPolygon.h" +#import "AIRMapCircle.h" +#import "SMCalloutView.h" +#import "AIRGoogleMapMarker.h" + +#import + +static NSString *const RCTMapViewKey = @"MapView"; + + +@interface AIRGoogleMapManager() + +@end + +@implementation AIRGoogleMapManager + +RCT_EXPORT_MODULE() + +- (UIView *)view +{ + AIRGoogleMap *map = [AIRGoogleMap new]; + map.delegate = self; + return map; +} + +RCT_EXPORT_VIEW_PROPERTY(initialRegion, MKCoordinateRegion) +RCT_EXPORT_VIEW_PROPERTY(region, MKCoordinateRegion) +RCT_EXPORT_VIEW_PROPERTY(showsBuildings, BOOL) +RCT_EXPORT_VIEW_PROPERTY(showsCompass, BOOL) +//RCT_EXPORT_VIEW_PROPERTY(showsScale, BOOL) // Not supported by GoogleMaps +RCT_EXPORT_VIEW_PROPERTY(showsTraffic, BOOL) +RCT_EXPORT_VIEW_PROPERTY(zoomEnabled, BOOL) +RCT_EXPORT_VIEW_PROPERTY(rotateEnabled, BOOL) +RCT_EXPORT_VIEW_PROPERTY(scrollEnabled, BOOL) +RCT_EXPORT_VIEW_PROPERTY(pitchEnabled, BOOL) +RCT_EXPORT_VIEW_PROPERTY(onPress, RCTBubblingEventBlock) +RCT_EXPORT_VIEW_PROPERTY(onLongPress, RCTBubblingEventBlock) +RCT_EXPORT_VIEW_PROPERTY(onChange, RCTBubblingEventBlock) +RCT_EXPORT_VIEW_PROPERTY(onMarkerPress, RCTDirectEventBlock) +RCT_EXPORT_VIEW_PROPERTY(onRegionChange, RCTDirectEventBlock) +RCT_EXPORT_VIEW_PROPERTY(onRegionChangeComplete, RCTDirectEventBlock) + +RCT_EXPORT_METHOD(fitToElements:(nonnull NSNumber *)reactTag + animated:(BOOL)animated) +{ + [self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary *viewRegistry) { + id view = viewRegistry[reactTag]; + if (![view isKindOfClass:[AIRGoogleMap class]]) { + RCTLogError(@"Invalid view returned from registry, expecting AIRGoogleMap, got: %@", view); + } else { + AIRGoogleMap *mapView = (AIRGoogleMap *)view; + + CLLocationCoordinate2D myLocation = ((AIRGoogleMapMarker *)(mapView.markers.firstObject)).realMarker.position; + GMSCoordinateBounds *bounds = [[GMSCoordinateBounds alloc] initWithCoordinate:myLocation coordinate:myLocation]; + + for (AIRGoogleMapMarker *marker in mapView.markers) + bounds = [bounds includingCoordinate:marker.realMarker.position]; + + [mapView animateWithCameraUpdate:[GMSCameraUpdate fitBounds:bounds withPadding:55.0f]]; + } + }]; +} + +RCT_EXPORT_METHOD(takeSnapshot:(nonnull NSNumber *)reactTag + withWidth:(nonnull NSNumber *)width + withHeight:(nonnull NSNumber *)height + withRegion:(MKCoordinateRegion)region + withCallback:(RCTResponseSenderBlock)callback) +{ + [self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary *viewRegistry) { + id view = viewRegistry[reactTag]; + if (![view isKindOfClass:[AIRGoogleMap class]]) { + RCTLogError(@"Invalid view returned from registry, expecting AIRMap, got: %@", view); + } else { + AIRGoogleMap *mapView = (AIRGoogleMap *)view; + + // TODO: currently we are ignoring width, height, region + + UIGraphicsBeginImageContextWithOptions(mapView.frame.size, YES, 0.0f); + [mapView.layer renderInContext:UIGraphicsGetCurrentContext()]; + UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + + NSTimeInterval timeStamp = [[NSDate date] timeIntervalSince1970]; + NSString *pathComponent = [NSString stringWithFormat:@"Documents/snapshot-%.20lf.png", timeStamp]; + NSString *filePath = [NSHomeDirectory() stringByAppendingPathComponent: pathComponent]; + + NSData *data = UIImagePNGRepresentation(image); + [data writeToFile:filePath atomically:YES]; + NSDictionary *snapshotData = @{ + @"uri": filePath, + @"data": [data base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithCarriageReturn] + }; + callback(@[[NSNull null], snapshotData]); + } + }]; +} + + +- (BOOL)mapView:(GMSMapView *)mapView didTapMarker:(GMSMarker *)marker { + AIRGoogleMap *googleMapView = (AIRGoogleMap *)mapView; + return [googleMapView didTapMarker:marker]; +} + +- (void)mapView:(GMSMapView *)mapView didTapAtCoordinate:(CLLocationCoordinate2D)coordinate { + AIRGoogleMap *googleMapView = (AIRGoogleMap *)mapView; + [googleMapView didTapAtCoordinate:coordinate]; +} + +- (void)mapView:(GMSMapView *)mapView didLongPressAtCoordinate:(CLLocationCoordinate2D)coordinate { + AIRGoogleMap *googleMapView = (AIRGoogleMap *)mapView; + [googleMapView didLongPressAtCoordinate:coordinate]; +} + +- (void)mapView:(GMSMapView *)mapView didChangeCameraPosition:(GMSCameraPosition *)position { + AIRGoogleMap *googleMapView = (AIRGoogleMap *)mapView; + [googleMapView didChangeCameraPosition:position]; +} + +- (void)mapView:(GMSMapView *)mapView idleAtCameraPosition:(GMSCameraPosition *)position { + AIRGoogleMap *googleMapView = (AIRGoogleMap *)mapView; + [googleMapView idleAtCameraPosition:position]; +} + +- (UIView *)mapView:(GMSMapView *)mapView markerInfoWindow:(GMSMarker *)marker { + AIRGMSMarker *aMarker = (AIRGMSMarker *)marker; + return [aMarker.fakeMarker markerInfoWindow];} + +- (UIView *)mapView:(GMSMapView *)mapView markerInfoContents:(GMSMarker *)marker { + AIRGMSMarker *aMarker = (AIRGMSMarker *)marker; + return [aMarker.fakeMarker markerInfoContents]; +} + +- (void)mapView:(GMSMapView *)mapView didTapInfoWindowOfMarker:(GMSMarker *)marker { + AIRGMSMarker *aMarker = (AIRGMSMarker *)marker; + [aMarker.fakeMarker didTapInfoWindowOfMarker:aMarker]; +} + +- (void)mapView:(GMSMapView *)mapView didBeginDraggingMarker:(GMSMarker *)marker { + AIRGMSMarker *aMarker = (AIRGMSMarker *)marker; + [aMarker.fakeMarker didBeginDraggingMarker:aMarker]; +} + +- (void)mapView:(GMSMapView *)mapView didEndDraggingMarker:(GMSMarker *)marker { + AIRGMSMarker *aMarker = (AIRGMSMarker *)marker; + [aMarker.fakeMarker didEndDraggingMarker:aMarker]; +} + +- (void)mapView:(GMSMapView *)mapView didDragMarker:(GMSMarker *)marker { + AIRGMSMarker *aMarker = (AIRGMSMarker *)marker; + [aMarker.fakeMarker didDragMarker:aMarker]; +} +@end diff --git a/ios/AirGoogleMaps/AIRGoogleMapMarker.h b/ios/AirGoogleMaps/AIRGoogleMapMarker.h new file mode 100644 index 000000000..db1c929b6 --- /dev/null +++ b/ios/AirGoogleMaps/AIRGoogleMapMarker.h @@ -0,0 +1,39 @@ +// +// AIRGoogleMapMarker.h +// AirMaps +// +// Created by Gil Birman on 9/2/16. +// + +#import +#import "AIRGMSMarker.h" +#import "RCTBridge.h" +#import "AIRGoogleMap.h" +#import "AIRGoogleMapCallout.h" + +@interface AIRGoogleMapMarker : UIView + +@property (nonatomic, weak) RCTBridge *bridge; +@property (nonatomic, strong) AIRGoogleMapCallout *calloutView; +@property (nonatomic, strong) NSString *identifier; +@property (nonatomic, assign) CLLocationCoordinate2D coordinate; +@property (nonatomic, strong) AIRGMSMarker* realMarker; +@property (nonatomic, copy) RCTBubblingEventBlock onPress; +@property (nonatomic, copy) RCTDirectEventBlock onDragStart; +@property (nonatomic, copy) RCTDirectEventBlock onDrag; +@property (nonatomic, copy) RCTDirectEventBlock onDragEnd; +@property (nonatomic, copy) NSString *imageSrc; +@property (nonatomic, copy) NSString *title; +@property (nonatomic, copy) NSString *subtitle; +@property (nonatomic, strong) UIColor *pinColor; +@property (nonatomic, assign) BOOL draggable; + +- (void)showCalloutView; +- (void)hideCalloutView; +- (UIView *)markerInfoContents; +- (UIView *)markerInfoWindow; +- (void)didTapInfoWindowOfMarker:(AIRGMSMarker *)marker; +- (void)didBeginDraggingMarker:(AIRGMSMarker *)marker; +- (void)didEndDraggingMarker:(AIRGMSMarker *)marker; +- (void)didDragMarker:(AIRGMSMarker *)marker; +@end diff --git a/ios/AirGoogleMaps/AIRGoogleMapMarker.m b/ios/AirGoogleMaps/AIRGoogleMapMarker.m new file mode 100644 index 000000000..676fff59e --- /dev/null +++ b/ios/AirGoogleMaps/AIRGoogleMapMarker.m @@ -0,0 +1,239 @@ +// +// AIRGoogleMapMarker.m +// AirMaps +// +// Created by Gil Birman on 9/2/16. +// + +#import "AIRGoogleMapMarker.h" +#import +#import "AIRGMSMarker.h" +#import "AIRGoogleMapCallout.h" +#import "RCTImageLoader.h" +#import "RCTUtils.h" + +CGRect unionRect(CGRect a, CGRect b) { + return CGRectMake( + MIN(a.origin.x, b.origin.x), + MIN(a.origin.y, b.origin.y), + MAX(a.size.width, b.size.width), + MAX(a.size.height, b.size.height)); +} + +@interface AIRGoogleMapMarker () +- (id)eventFromMarker:(AIRGMSMarker*)marker; +@end + +@implementation AIRGoogleMapMarker { + RCTImageLoaderCancellationBlock _reloadImageCancellationBlock; + __weak UIImageView *_iconImageView; +} + +- (instancetype)init +{ + if ((self = [super init])) { + _realMarker = [[AIRGMSMarker alloc] init]; + _realMarker.fakeMarker = self; + } + return self; +} + +- (id)eventFromMarker:(AIRGMSMarker*)marker { + + CLLocationCoordinate2D coordinate = marker.position; + CGPoint position = [self.realMarker.map.projection pointForCoordinate:coordinate]; + +return @{ + @"id": marker.identifier ?: @"unknown", + @"position": @{ + @"x": @(position.x), + @"y": @(position.y), + }, + @"coordinate": @{ + @"latitude": @(coordinate.latitude), + @"longitude": @(coordinate.longitude), + } + }; +} + +- (void)insertReactSubview:(id)subview atIndex:(NSInteger)atIndex { + if ([subview isKindOfClass:[AIRGoogleMapCallout class]]) { + self.calloutView = (AIRGoogleMapCallout *)subview; + } else { + // Custom UIView Marker + // NOTE: Originally I tried creating a new UIView here to encapsulate subview, + // but it would not sizeToFit properly. Not sure why. + [super insertReactSubview:(UIView*)subview atIndex:atIndex]; + [self sizeToFit]; + + // TODO: how to handle this circular reference properly? + _realMarker.iconView = self; + } +} + +- (void)removeReactSubview:(id)subview { + if ([subview isKindOfClass:[AIRGoogleMapCallout class]]) { + self.calloutView = nil; + } else { + [super removeReactSubview:(UIView*)subview]; + } +} + +- (void)showCalloutView { + [_realMarker.map setSelectedMarker:_realMarker]; +} + +- (void)hideCalloutView { + [_realMarker.map setSelectedMarker:Nil]; +} + +- (UIView *)markerInfoContents { + if (self.calloutView && !self.calloutView.tooltip) { + return self.calloutView; + } + return nil; +} + +- (UIView *)markerInfoWindow { + if (self.calloutView && self.calloutView.tooltip) { + return self.calloutView; + } + return nil; +} + +- (void)didTapInfoWindowOfMarker:(AIRGMSMarker *)marker { + if (self.calloutView && self.calloutView.onPress) { + id event = @{@"action": @"marker-overlay-press", + @"id": self.identifier ?: @"unknown", + }; + self.calloutView.onPress(event); + } +} + +- (void)didBeginDraggingMarker:(AIRGMSMarker *)marker { + if (!self.onDragStart) return; + self.onDragStart([self eventFromMarker:marker]); +} + +- (void)didEndDraggingMarker:(AIRGMSMarker *)marker { + if (!self.onDragEnd) return; + self.onDragEnd([self eventFromMarker:marker]); +} + +- (void)didDragMarker:(AIRGMSMarker *)marker { + if (!self.onDrag) return; + self.onDrag([self eventFromMarker:marker]); +} + +- (void)setCoordinate:(CLLocationCoordinate2D)coordinate { + _realMarker.position = coordinate; +} + +- (CLLocationCoordinate2D)coordinate { + return _realMarker.position; +} + +- (void)setIdentifier:(NSString *)identifier { + _realMarker.identifier = identifier; +} + +- (NSString *)identifier { + return _realMarker.identifier; +} + +- (void)setOnPress:(RCTBubblingEventBlock)onPress { + _realMarker.onPress = onPress; +} + +- (RCTBubblingEventBlock)onPress { + return _realMarker.onPress; +} + +- (void)setImageSrc:(NSString *)imageSrc +{ + + _imageSrc = imageSrc; + + if (_reloadImageCancellationBlock) { + _reloadImageCancellationBlock(); + _reloadImageCancellationBlock = nil; + } + + _reloadImageCancellationBlock = [_bridge.imageLoader loadImageWithURLRequest:[RCTConvert NSURLRequest:_imageSrc] + size:self.bounds.size + scale:RCTScreenScale() + clipped:YES + resizeMode:RCTResizeModeCenter + progressBlock:nil + completionBlock:^(NSError *error, UIImage *image) { + if (error) { + // TODO(lmr): do something with the error? + NSLog(@"%@", error); + } + dispatch_async(dispatch_get_main_queue(), ^{ + + if (_iconImageView) { + // TODO: doesn't work because image is blank (WHY??) + [_iconImageView setImage:image]; + return; + } + + UIImageView *imageView = [[UIImageView alloc] initWithImage:image]; + + // TODO: w,h or pixel density could be a prop. + float density = 1; + float w = image.size.width/density; + float h = image.size.height/density; + CGRect bounds = CGRectMake(0, 0, w, h); + + imageView.contentMode = UIViewContentModeScaleAspectFit; + [imageView setFrame:bounds]; + + // NOTE: sizeToFit doesn't work instead. Not sure why. + // TODO: Doing it this way is not ideal because it causes things to reshuffle + // when the image loads IF the image is larger than the UIView. + // Shouldn't required images have size info automatically via RN? + CGRect selfBounds = unionRect(bounds, self.bounds); + [self setFrame:selfBounds]; + + _iconImageView = imageView; + + [super insertSubview:imageView atIndex:0]; + _realMarker.iconView = self; + + // TODO: This could be a prop + //_realMarker.groundAnchor = CGPointMake(0.75, 1); + }); + }]; +} + +- (void)setTitle:(NSString *)title { + _realMarker.title = [title copy]; +} + +- (NSString *)title { + return _realMarker.title; +} + +- (void)setSubtitle:(NSString *)subtitle { + _realMarker.snippet = subtitle; +} + +- (NSString *)subtitle { + return _realMarker.snippet; +} + +- (void)setPinColor:(UIColor *)pinColor { + _pinColor = pinColor; + _realMarker.icon = [GMSMarker markerImageWithColor:pinColor]; +} + +- (void)setDraggable:(BOOL)draggable { + _realMarker.draggable = draggable; +} + +- (BOOL)draggable { + return _realMarker.draggable; +} + +@end diff --git a/ios/AirGoogleMaps/AIRGoogleMapMarkerManager.h b/ios/AirGoogleMaps/AIRGoogleMapMarkerManager.h new file mode 100644 index 000000000..657f6b044 --- /dev/null +++ b/ios/AirGoogleMaps/AIRGoogleMapMarkerManager.h @@ -0,0 +1,12 @@ +// +// AIRGoogleMapMarkerManager.h +// AirMaps +// +// Created by Gil Birman on 9/2/16. +// + +#import "RCTViewManager.h" + +@interface AIRGoogleMapMarkerManager : RCTViewManager + +@end diff --git a/ios/AirGoogleMaps/AIRGoogleMapMarkerManager.m b/ios/AirGoogleMaps/AIRGoogleMapMarkerManager.m new file mode 100644 index 000000000..43dfd900f --- /dev/null +++ b/ios/AirGoogleMaps/AIRGoogleMapMarkerManager.m @@ -0,0 +1,64 @@ +// +// AIRGoogleMapMarkerManager.m +// AirMaps +// +// Created by Gil Birman on 9/2/16. +// + +#import "AIRGoogleMapMarkerManager.h" +#import "AIRGoogleMapMarker.h" +#import +#import "RCTConvert+MapKit.h" +#import "RCTUIManager.h" + +@implementation AIRGoogleMapMarkerManager + +RCT_EXPORT_MODULE() + +- (UIView *)view +{ + AIRGoogleMapMarker *marker = [AIRGoogleMapMarker new]; +// UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(_handleTap:)]; +// // setting this to NO allows the parent MapView to continue receiving marker selection events +// tapGestureRecognizer.cancelsTouchesInView = NO; +// [marker addGestureRecognizer:tapGestureRecognizer]; + marker.bridge = self.bridge; + return marker; +} + +RCT_EXPORT_VIEW_PROPERTY(identifier, NSString) +RCT_EXPORT_VIEW_PROPERTY(coordinate, CLLocationCoordinate2D) +RCT_EXPORT_VIEW_PROPERTY(onPress, RCTBubblingEventBlock) +RCT_REMAP_VIEW_PROPERTY(image, imageSrc, NSString) +RCT_EXPORT_VIEW_PROPERTY(title, NSString) +RCT_REMAP_VIEW_PROPERTY(description, subtitle, NSString) +RCT_EXPORT_VIEW_PROPERTY(pinColor, UIColor) +RCT_EXPORT_VIEW_PROPERTY(draggable, BOOL) +RCT_EXPORT_VIEW_PROPERTY(onDragStart, RCTDirectEventBlock) +RCT_EXPORT_VIEW_PROPERTY(onDrag, RCTDirectEventBlock) +RCT_EXPORT_VIEW_PROPERTY(onDragEnd, RCTDirectEventBlock) + +RCT_EXPORT_METHOD(showCallout:(nonnull NSNumber *)reactTag) +{ + [self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary *viewRegistry) { + id view = viewRegistry[reactTag]; + if (![view isKindOfClass:[AIRGoogleMapMarker class]]) { + RCTLogError(@"Invalid view returned from registry, expecting AIRMap, got: %@", view); + } else { + [(AIRGoogleMapMarker *) view showCalloutView]; + } + }]; +} + +RCT_EXPORT_METHOD(hideCallout:(nonnull NSNumber *)reactTag) +{ + [self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary *viewRegistry) { + id view = viewRegistry[reactTag]; + if (![view isKindOfClass:[AIRGoogleMapMarker class]]) { + RCTLogError(@"Invalid view returned from registry, expecting AIRMap, got: %@", view); + } else { + [(AIRGoogleMapMarker *) view hideCalloutView]; + } + }]; +} +@end diff --git a/ios/AirMaps.xcodeproj/project.pbxproj b/ios/AirMaps.xcodeproj/project.pbxproj index 56d021703..274cb11f3 100644 --- a/ios/AirMaps.xcodeproj/project.pbxproj +++ b/ios/AirMaps.xcodeproj/project.pbxproj @@ -24,6 +24,12 @@ 1125B2F21C4AD445007D0023 /* SMCalloutView.m in Sources */ = {isa = PBXBuildFile; fileRef = 1125B2F11C4AD445007D0023 /* SMCalloutView.m */; }; DA6C26381C9E2AFE0035349F /* AIRMapUrlTile.m in Sources */ = {isa = PBXBuildFile; fileRef = DA6C26371C9E2AFE0035349F /* AIRMapUrlTile.m */; settings = {ASSET_TAGS = (); }; }; DA6C263E1C9E324A0035349F /* AIRMapUrlTileManager.m in Sources */ = {isa = PBXBuildFile; fileRef = DA6C263D1C9E324A0035349F /* AIRMapUrlTileManager.m */; settings = {ASSET_TAGS = (); }; }; + 215D95711D7A27BF000DF827 /* AIRGoogleMapMarker.m in Sources */ = {isa = PBXBuildFile; fileRef = 215D95701D7A27BF000DF827 /* AIRGoogleMapMarker.m */; }; + 216133031D7A2F880024C623 /* AIRGoogleMapMarkerManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 216133021D7A2F880024C623 /* AIRGoogleMapMarkerManager.m */; }; + 216133061D7E64D90024C623 /* AIRGMSMarker.m in Sources */ = {isa = PBXBuildFile; fileRef = 216133051D7E64D90024C623 /* AIRGMSMarker.m */; }; + 21E657271D78DAE600B75EE5 /* AIRGoogleMapManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 21E657261D78DAE600B75EE5 /* AIRGoogleMapManager.m */; }; + 21E6572A1D78E03E00B75EE5 /* AIRGoogleMap.m in Sources */ = {isa = PBXBuildFile; fileRef = 21E657291D78E03E00B75EE5 /* AIRGoogleMap.m */; }; + BA9CB783B2222EB8372E95C3 /* libPods-AirMaps.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 6F3FD30B4FC9B3779A288DC7 /* libPods-AirMaps.a */; }; /* End PBXBuildFile section */ /* Begin PBXCopyFilesBuildPhase section */ @@ -74,6 +80,19 @@ DA6C26371C9E2AFE0035349F /* AIRMapUrlTile.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRMapUrlTile.m; sourceTree = ""; }; DA6C263C1C9E324A0035349F /* AIRMapUrlTileManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRMapUrlTileManager.h; sourceTree = ""; }; DA6C263D1C9E324A0035349F /* AIRMapUrlTileManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRMapUrlTileManager.m; sourceTree = ""; }; + 215D956F1D7A27BF000DF827 /* AIRGoogleMapMarker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AIRGoogleMapMarker.h; path = Google/AIRGoogleMapMarker.h; sourceTree = ""; }; + 215D95701D7A27BF000DF827 /* AIRGoogleMapMarker.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AIRGoogleMapMarker.m; path = Google/AIRGoogleMapMarker.m; sourceTree = ""; }; + 216133011D7A2F880024C623 /* AIRGoogleMapMarkerManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AIRGoogleMapMarkerManager.h; path = Google/AIRGoogleMapMarkerManager.h; sourceTree = ""; }; + 216133021D7A2F880024C623 /* AIRGoogleMapMarkerManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AIRGoogleMapMarkerManager.m; path = Google/AIRGoogleMapMarkerManager.m; sourceTree = ""; }; + 216133041D7E64D90024C623 /* AIRGMSMarker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AIRGMSMarker.h; path = Google/AIRGMSMarker.h; sourceTree = ""; }; + 216133051D7E64D90024C623 /* AIRGMSMarker.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AIRGMSMarker.m; path = Google/AIRGMSMarker.m; sourceTree = ""; }; + 21E657251D78DAE600B75EE5 /* AIRGoogleMapManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AIRGoogleMapManager.h; path = Google/AIRGoogleMapManager.h; sourceTree = ""; }; + 21E657261D78DAE600B75EE5 /* AIRGoogleMapManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AIRGoogleMapManager.m; path = Google/AIRGoogleMapManager.m; sourceTree = ""; }; + 21E657281D78E03E00B75EE5 /* AIRGoogleMap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AIRGoogleMap.h; path = Google/AIRGoogleMap.h; sourceTree = ""; }; + 21E657291D78E03E00B75EE5 /* AIRGoogleMap.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AIRGoogleMap.m; path = Google/AIRGoogleMap.m; sourceTree = ""; }; + 6F3FD30B4FC9B3779A288DC7 /* libPods-AirMaps.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-AirMaps.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + 8CCE0467700E33644F88F948 /* Pods-AirMaps.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AirMaps.debug.xcconfig"; path = "Pods/Target Support Files/Pods-AirMaps/Pods-AirMaps.debug.xcconfig"; sourceTree = ""; }; + D22E28ACFEBD663EF2744EFE /* Pods-AirMaps.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AirMaps.release.xcconfig"; path = "Pods/Target Support Files/Pods-AirMaps/Pods-AirMaps.release.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -81,6 +100,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + BA9CB783B2222EB8372E95C3 /* libPods-AirMaps.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -92,6 +112,8 @@ children = ( 11FA5C531C4A1296003AC2EE /* AirMaps */, 11FA5C521C4A1296003AC2EE /* Products */, + 6F0AEBE80A623FE41FDC8708 /* Pods */, + 4712B0CE6DC6BF94D04BA69A /* Frameworks */, ); sourceTree = ""; }; @@ -106,6 +128,7 @@ 11FA5C531C4A1296003AC2EE /* AirMaps */ = { isa = PBXGroup; children = ( + 21E657241D78DA9600B75EE5 /* Google */, 1125B2BD1C4AD3DA007D0023 /* AIRMap.h */, 1125B2BE1C4AD3DA007D0023 /* AIRMap.m */, 1125B2BF1C4AD3DA007D0023 /* AIRMapCallout.h */, @@ -144,6 +167,40 @@ path = AirMaps; sourceTree = ""; }; + 21E657241D78DA9600B75EE5 /* Google */ = { + isa = PBXGroup; + children = ( + 21E657251D78DAE600B75EE5 /* AIRGoogleMapManager.h */, + 21E657261D78DAE600B75EE5 /* AIRGoogleMapManager.m */, + 21E657281D78E03E00B75EE5 /* AIRGoogleMap.h */, + 21E657291D78E03E00B75EE5 /* AIRGoogleMap.m */, + 215D956F1D7A27BF000DF827 /* AIRGoogleMapMarker.h */, + 215D95701D7A27BF000DF827 /* AIRGoogleMapMarker.m */, + 216133011D7A2F880024C623 /* AIRGoogleMapMarkerManager.h */, + 216133021D7A2F880024C623 /* AIRGoogleMapMarkerManager.m */, + 216133041D7E64D90024C623 /* AIRGMSMarker.h */, + 216133051D7E64D90024C623 /* AIRGMSMarker.m */, + ); + name = Google; + sourceTree = ""; + }; + 4712B0CE6DC6BF94D04BA69A /* Frameworks */ = { + isa = PBXGroup; + children = ( + 6F3FD30B4FC9B3779A288DC7 /* libPods-AirMaps.a */, + ); + name = Frameworks; + sourceTree = ""; + }; + 6F0AEBE80A623FE41FDC8708 /* Pods */ = { + isa = PBXGroup; + children = ( + 8CCE0467700E33644F88F948 /* Pods-AirMaps.debug.xcconfig */, + D22E28ACFEBD663EF2744EFE /* Pods-AirMaps.release.xcconfig */, + ); + name = Pods; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -151,9 +208,11 @@ isa = PBXNativeTarget; buildConfigurationList = 11FA5C5A1C4A1296003AC2EE /* Build configuration list for PBXNativeTarget "AirMaps" */; buildPhases = ( + 213F4612EFB9C7C068108D23 /* Check Pods Manifest.lock */, 11FA5C4D1C4A1296003AC2EE /* Sources */, 11FA5C4E1C4A1296003AC2EE /* Frameworks */, 11FA5C4F1C4A1296003AC2EE /* CopyFiles */, + 93CACE9D409FFE530662D7C9 /* Copy Pods Resources */, ); buildRules = ( ); @@ -195,6 +254,39 @@ }; /* End PBXProject section */ +/* Begin PBXShellScriptBuildPhase section */ + 213F4612EFB9C7C068108D23 /* Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Check Pods Manifest.lock"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n"; + showEnvVarsInLog = 0; + }; + 93CACE9D409FFE530662D7C9 /* Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Copy Pods Resources"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-AirMaps/Pods-AirMaps-resources.sh\"\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + /* Begin PBXSourcesBuildPhase section */ 11FA5C4D1C4A1296003AC2EE /* Sources */ = { isa = PBXSourcesBuildPhase; @@ -202,10 +294,14 @@ files = ( 1125B2E31C4AD3DA007D0023 /* AIRMapPolygon.m in Sources */, 1125B2E41C4AD3DA007D0023 /* AIRMapPolygonManager.m in Sources */, + 21E6572A1D78E03E00B75EE5 /* AIRGoogleMap.m in Sources */, + 21E657271D78DAE600B75EE5 /* AIRGoogleMapManager.m in Sources */, 1125B2DB1C4AD3DA007D0023 /* AIRMapCallout.m in Sources */, 1125B2E01C4AD3DA007D0023 /* AIRMapManager.m in Sources */, + 216133061D7E64D90024C623 /* AIRGMSMarker.m in Sources */, 1125B2E61C4AD3DA007D0023 /* AIRMapPolylineManager.m in Sources */, 1125B2DD1C4AD3DA007D0023 /* AIRMapCircle.m in Sources */, + 215D95711D7A27BF000DF827 /* AIRGoogleMapMarker.m in Sources */, 1125B2E51C4AD3DA007D0023 /* AIRMapPolyline.m in Sources */, DA6C263E1C9E324A0035349F /* AIRMapUrlTileManager.m in Sources */, 1125B2DA1C4AD3DA007D0023 /* AIRMap.m in Sources */, @@ -213,6 +309,7 @@ 1125B2DF1C4AD3DA007D0023 /* AIRMapCoordinate.m in Sources */, 1125B2F21C4AD445007D0023 /* SMCalloutView.m in Sources */, 1125B2E11C4AD3DA007D0023 /* AIRMapMarker.m in Sources */, + 216133031D7A2F880024C623 /* AIRGoogleMapMarkerManager.m in Sources */, 1125B2E21C4AD3DA007D0023 /* AIRMapMarkerManager.m in Sources */, DA6C26381C9E2AFE0035349F /* AIRMapUrlTile.m in Sources */, 1125B2DE1C4AD3DA007D0023 /* AIRMapCircleManager.m in Sources */, @@ -307,6 +404,7 @@ }; 11FA5C5B1C4A1296003AC2EE /* Debug */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 8CCE0467700E33644F88F948 /* Pods-AirMaps.debug.xcconfig */; buildSettings = { HEADER_SEARCH_PATHS = ( "$(SRCROOT)/../../react-native/React/**", @@ -321,6 +419,7 @@ }; 11FA5C5C1C4A1296003AC2EE /* Release */ = { isa = XCBuildConfiguration; + baseConfigurationReference = D22E28ACFEBD663EF2744EFE /* Pods-AirMaps.release.xcconfig */; buildSettings = { HEADER_SEARCH_PATHS = ( "$(SRCROOT)/../../react-native/React/**", diff --git a/ios/AirMaps.xcworkspace/contents.xcworkspacedata b/ios/AirMaps.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..e49e5f4d1 --- /dev/null +++ b/ios/AirMaps.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/ios/AirMaps/AIRMap.m b/ios/AirMaps/AIRMap.m index 1cb2bc640..9efe1b4aa 100644 --- a/ios/AirMaps/AIRMap.m +++ b/ios/AirMaps/AIRMap.m @@ -88,6 +88,8 @@ - (void)dealloc [_regionChangeObserveTimer invalidate]; } +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wobjc-missing-super-calls" - (void)insertReactSubview:(id)subview atIndex:(NSInteger)atIndex { // Our desired API is to pass up markers/overlays as children to the mapview component. // This is where we intercept them and do the appropriate underlying mapview action. @@ -106,7 +108,10 @@ - (void)insertReactSubview:(id)subview atIndex:(NSInteger)atIndex } [_reactSubviews insertObject:(UIView *)subview atIndex:(NSUInteger) atIndex]; } +#pragma clang diagnostic pop +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wobjc-missing-super-calls" - (void)removeReactSubview:(id)subview { // similarly, when the children are being removed we have to do the appropriate // underlying mapview action here. @@ -123,10 +128,14 @@ - (void)removeReactSubview:(id)subview { } [_reactSubviews removeObject:(UIView *)subview]; } +#pragma clang diagnostic pop +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wobjc-missing-super-calls" - (NSArray> *)reactSubviews { - return _reactSubviews; + return _reactSubviews; } +#pragma clang diagnostic pop #pragma mark Overrides for Callout behavior diff --git a/ios/AirMaps/AIRMapUrlTile.h b/ios/AirMaps/AIRMapUrlTile.h index 1b1493c66..184fe2231 100644 --- a/ios/AirMaps/AIRMapUrlTile.h +++ b/ios/AirMaps/AIRMapUrlTile.h @@ -29,7 +29,7 @@ @property(nonatomic, readonly) CLLocationCoordinate2D coordinate; @property(nonatomic, readonly) MKMapRect boundingMapRect; -- (BOOL)intersectsMapRect:(MKMapRect)mapRect; +//- (BOOL)intersectsMapRect:(MKMapRect)mapRect; - (BOOL)canReplaceMapContent; @end diff --git a/ios/AirMaps/Callout/SMCalloutView.h b/ios/AirMaps/Callout/SMCalloutView.h index 11643fd29..a1e911469 100644 --- a/ios/AirMaps/Callout/SMCalloutView.h +++ b/ios/AirMaps/Callout/SMCalloutView.h @@ -40,7 +40,7 @@ extern NSTimeInterval const kSMCalloutViewRepositionDelayForUIScrollView; // Callout view. // -@interface SMCalloutView : UIView +@interface SMCalloutView : UIView @property (nonatomic, weak, nullable) id delegate; /// title/titleView relationship mimics UINavigationBar. @@ -197,4 +197,4 @@ extern NSTimeInterval const kSMCalloutViewRepositionDelayForUIScrollView; - (void)calloutViewDidDisappear:(SMCalloutView *)calloutView; NS_ASSUME_NONNULL_END -@end \ No newline at end of file +@end diff --git a/ios/Podfile b/ios/Podfile new file mode 100644 index 000000000..72cc083d7 --- /dev/null +++ b/ios/Podfile @@ -0,0 +1,21 @@ +# Uncomment this line to define a global platform for your project +platform :ios, '8.0' +# Uncomment this line if you're using Swift +# use_frameworks! + +target 'AirMaps' do + pod 'React', path: '../example/node_modules/react-native', :subspecs => [ + 'Core', + 'RCTActionSheet', + 'RCTGeolocation', + 'RCTImage', + 'RCTLinkingIOS', + 'RCTNetwork', + 'RCTSettings', + 'RCTText', + 'RCTVibration', + 'RCTWebSocket' + ] + + pod 'GoogleMaps' +end diff --git a/ios/Podfile.lock b/ios/Podfile.lock new file mode 100644 index 000000000..cafccccf9 --- /dev/null +++ b/ios/Podfile.lock @@ -0,0 +1,51 @@ +PODS: + - GoogleMaps (2.0.1): + - GoogleMaps/Maps (= 2.0.1) + - GoogleMaps/Base (2.0.1) + - GoogleMaps/Maps (2.0.1): + - GoogleMaps/Base (= 2.0.1) + - React/Core (0.32.0): + - React/CSSLayout + - React/CSSLayout (0.32.0) + - React/RCTActionSheet (0.32.0): + - React/Core + - React/RCTGeolocation (0.32.0): + - React/Core + - React/RCTImage (0.32.0): + - React/Core + - React/RCTNetwork + - React/RCTLinkingIOS (0.32.0): + - React/Core + - React/RCTNetwork (0.32.0): + - React/Core + - React/RCTSettings (0.32.0): + - React/Core + - React/RCTText (0.32.0): + - React/Core + - React/RCTVibration (0.32.0): + - React/Core + - React/RCTWebSocket (0.32.0): + - React/Core + +DEPENDENCIES: + - GoogleMaps + - React/Core (from `../example/node_modules/react-native`) + - React/RCTActionSheet (from `../example/node_modules/react-native`) + - React/RCTGeolocation (from `../example/node_modules/react-native`) + - React/RCTImage (from `../example/node_modules/react-native`) + - React/RCTLinkingIOS (from `../example/node_modules/react-native`) + - React/RCTNetwork (from `../example/node_modules/react-native`) + - React/RCTSettings (from `../example/node_modules/react-native`) + - React/RCTText (from `../example/node_modules/react-native`) + - React/RCTVibration (from `../example/node_modules/react-native`) + - React/RCTWebSocket (from `../example/node_modules/react-native`) + +EXTERNAL SOURCES: + React: + :path: "../example/node_modules/react-native" + +SPEC CHECKSUMS: + GoogleMaps: f09da64fc987c1aa29394567c3cab5a3df83c402 + React: 0245b401173a94a5fba0f440aab3fb2f79b738f3 + +COCOAPODS: 0.39.0 diff --git a/react-native-google-maps.podspec b/react-native-google-maps.podspec new file mode 100644 index 000000000..9cf323e6e --- /dev/null +++ b/react-native-google-maps.podspec @@ -0,0 +1,16 @@ +Pod::Spec.new do |s| + s.name = "react-native-google-maps" + s.version = "0.8.2" + s.summary = "React Native Mapview component for iOS + Android" + + s.authors = { "intelligibabble" => "leland.m.richardson@gmail.com" } + s.homepage = "https://github.com/lelandrichardson/react-native-maps#readme" + s.license = "MIT" + s.platform = :ios, "8.0" + + s.source = { :git => "https://github.com/lelandrichardson/react-native-maps.git" } + s.source_files = "ios/AirMaps/**/*.{h,m}" + + s.dependency 'React' + s.dependency 'GoogleMaps', '2.0.1' +end From dc33d7b223b4acacf5cbfa64a667eb6e4a58fcab Mon Sep 17 00:00:00 2001 From: Spike Brehm Date: Thu, 22 Sep 2016 10:34:53 -0700 Subject: [PATCH 0070/1148] Fix list of examples on Android In #548, we added Google Maps support for iOS. We changed the example app to list examples based on whether they support Google Maps on iOS. The logic was such that on Android it only showed the examples that are iOS + Google Map compatible, however on Android this condition is irrelevant, this commit changes it to show all examples on Android, regardless. --- example/App.js | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/example/App.js b/example/App.js index 2052f25a0..fab128b1b 100644 --- a/example/App.js +++ b/example/App.js @@ -29,6 +29,9 @@ import LiteMapView from './examples/LiteMapView'; import CustomTiles from './examples/CustomTiles'; import StaticMap from './examples/StaticMap'; +const IOS = Platform.OS === 'ios'; +const ANDROID = Platform.OS === 'android'; + function makeExampleMapper(useGoogleMaps) { if (useGoogleMaps) { return example => [ @@ -45,8 +48,7 @@ class App extends React.Component { this.state = { Component: null, - showGoogleMapsSwitch: Platform.OS === 'ios', - useGoogleMaps: Platform.OS === 'android', + useGoogleMaps: ANDROID, }; } @@ -89,7 +91,6 @@ class App extends React.Component { renderExamples(examples) { const { Component, - showGoogleMapsSwitch, useGoogleMaps, } = this.state; @@ -103,7 +104,7 @@ class App extends React.Component { contentContainerStyle={styles.scrollview} showsVerticalScrollIndicator={false} > - {showGoogleMapsSwitch && this.renderGoogleSwitch()} + {IOS && this.renderGoogleSwitch()} {examples.map(example => this.renderExample(example))}
} @@ -113,7 +114,7 @@ class App extends React.Component { render() { return this.renderExamples([ - // [, , , ] + // [, , , ] [StaticMap, 'StaticMap', true], [DisplayLatLng, 'Tracking Position', true, '(incomplete)'], [ViewsAsMarkers, 'Arbitrary Views as Markers', true], @@ -134,8 +135,9 @@ class App extends React.Component { [LiteMapView, 'Android Lite MapView'], [CustomTiles, 'Custom Tiles'], ] - .filter(example => example[2] || !this.state.useGoogleMaps) - .map(makeExampleMapper(this.state.useGoogleMaps)) + // Filter out examples that are not yet supported for Google Maps on iOS. + .filter(example => ANDROID || (IOS && (example[2] || !this.state.useGoogleMaps))) + .map(makeExampleMapper(IOS && this.state.useGoogleMaps)) ); } } From 06f152a8368fbb85d35f3d7c86717d77af21e997 Mon Sep 17 00:00:00 2001 From: Naoufal Kadhom Date: Tue, 6 Sep 2016 19:51:19 -0400 Subject: [PATCH 0071/1148] Add fitToCoordinates method --- components/MapView.js | 4 ++++ ios/AirMaps/AIRMapManager.m | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/components/MapView.js b/components/MapView.js index 7c12af0d5..c76f73d17 100644 --- a/components/MapView.js +++ b/components/MapView.js @@ -436,6 +436,10 @@ class MapView extends React.Component { this._runCommand('fitToSuppliedMarkers', [markers, animated]); } + fitToCoordinates(coordinates, edgePadding, animated) { + this._runCommand('fitToCoordinates', [coordinates, edgePadding, animated]); + } + takeSnapshot(width, height, region, callback) { const finalRegion = region || this.props.region || this.props.initialRegion; this._runCommand('takeSnapshot', [width, height, finalRegion, callback]); diff --git a/ios/AirMaps/AIRMapManager.m b/ios/AirMaps/AIRMapManager.m index 3ac5a693d..e79fe70dd 100644 --- a/ios/AirMaps/AIRMapManager.m +++ b/ios/AirMaps/AIRMapManager.m @@ -187,6 +187,42 @@ - (UIView *)view }]; } +RCT_EXPORT_METHOD(fitToCoordinates:(nonnull NSNumber *)reactTag + coordinates:(nonnull NSArray *)coordinates + edgePadding:(NSDictionary *)edgePadding + animated:(BOOL)animated) +{ + [self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary *viewRegistry) { + id view = viewRegistry[reactTag]; + if (![view isKindOfClass:[AIRMap class]]) { + RCTLogError(@"Invalid view returned from registry, expecting AIRMap, got: %@", view); + } else { + AIRMap *mapView = (AIRMap *)view; + + // Create Polyline with coordinates + CLLocationCoordinate2D coords[coordinates.count]; + for(int i = 0; i < coordinates.count; i++) + { + coords[i] = coordinates[i].coordinate; + } + MKPolyline *polyline = [MKPolyline polylineWithCoordinates:coords count:coordinates.count]; + + // Set Map viewport + if (!edgePadding) { + [mapView setVisibleMapRect:[polyline boundingMapRect] animated:animated]; + } else { + CGFloat top = [RCTConvert CGFloat:edgePadding[@"top"]]; + CGFloat right = [RCTConvert CGFloat:edgePadding[@"right"]]; + CGFloat bottom = [RCTConvert CGFloat:edgePadding[@"bottom"]]; + CGFloat left = [RCTConvert CGFloat:edgePadding[@"left"]]; + + [mapView setVisibleMapRect:[polyline boundingMapRect] edgePadding:UIEdgeInsetsMake(top, left, bottom, right) animated:animated]; + } + + } + }]; +} + RCT_EXPORT_METHOD(takeSnapshot:(nonnull NSNumber *)reactTag withWidth:(nonnull NSNumber *)width withHeight:(nonnull NSNumber *)height From 4b257e03bf154ccf09be6cf4b23547ef566580dd Mon Sep 17 00:00:00 2001 From: Naoufal Kadhom Date: Tue, 6 Sep 2016 19:51:31 -0400 Subject: [PATCH 0072/1148] Update docs --- docs/mapview.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/docs/mapview.md b/docs/mapview.md index a4a69b6a1..657b7edc8 100644 --- a/docs/mapview.md +++ b/docs/mapview.md @@ -57,6 +57,7 @@ | `animateToCoordinate` | `region: Coordinate`, `duration: Number` | | `fitToElements` | `animated: Boolean` | | `fitToSuppliedMarkers` | `markerIDs: String[]` | +| `fitToCoordinates` | `coordinates: Array, edgePadding: EdgePadding, animated: Boolean` | @@ -93,3 +94,12 @@ enum MapType : String { "terrain" //Android only } ``` + +``` +type EdgePadding { + top: Number, + right: Number, + bottom: Number, + left: Number +} +``` From a1991034a832096b82c096d9676011270cf8fd6c Mon Sep 17 00:00:00 2001 From: Naoufal Kadhom Date: Tue, 6 Sep 2016 19:51:37 -0400 Subject: [PATCH 0073/1148] Add example --- example/App.js | 2 + example/examples/FitToCoordinates.js | 119 +++++++++++++++++++++++++++ 2 files changed, 121 insertions(+) create mode 100644 example/examples/FitToCoordinates.js diff --git a/example/App.js b/example/App.js index fab128b1b..7fa21bce1 100644 --- a/example/App.js +++ b/example/App.js @@ -25,6 +25,7 @@ import CachedMap from './examples/CachedMap'; import LoadingMap from './examples/LoadingMap'; import TakeSnapshot from './examples/TakeSnapshot'; import FitToSuppliedMarkers from './examples/FitToSuppliedMarkers'; +import FitToCoordinates from './examples/FitToCoordinates'; import LiteMapView from './examples/LiteMapView'; import CustomTiles from './examples/CustomTiles'; import StaticMap from './examples/StaticMap'; @@ -132,6 +133,7 @@ class App extends React.Component { [CachedMap, 'Cached Map'], [LoadingMap, 'Map with loading'], [FitToSuppliedMarkers, 'Focus Map On Markers'], + [FitToCoordinates, 'Fit Map To Coordinates'], [LiteMapView, 'Android Lite MapView'], [CustomTiles, 'Custom Tiles'], ] diff --git a/example/examples/FitToCoordinates.js b/example/examples/FitToCoordinates.js new file mode 100644 index 000000000..651779295 --- /dev/null +++ b/example/examples/FitToCoordinates.js @@ -0,0 +1,119 @@ +import React from 'react'; +import { + StyleSheet, + View, + Dimensions, + TouchableOpacity, + Text, +} from 'react-native'; + +import MapView from 'react-native-maps'; + +const { width, height } = Dimensions.get('window'); + +const ASPECT_RATIO = width / height; +const LATITUDE = 37.78825; +const LONGITUDE = -122.4324; +const LATITUDE_DELTA = 0.0922; +const LONGITUDE_DELTA = LATITUDE_DELTA * ASPECT_RATIO; +const SPACE = 0.01; + +function createMarker(modifier = 1) { + return { + latitude: LATITUDE - (SPACE * modifier), + longitude: LONGITUDE - (SPACE * modifier), + }; +} + +const MARKERS = [ + createMarker(), + createMarker(2), + createMarker(3), + createMarker(4), +]; + +class FitToCoordinates extends React.Component { + fitBottomTwoMarkers() { + this.map.fitToCoordinates( + [MARKERS[2], MARKERS[3]], + { top: 40, right: 40, bottom: 40, left: 40 }, + true + ); + } + + fitAllMarkers() { + this.map.fitToCoordinates( + MARKERS, + { top: 40, right: 40, bottom: 40, left: 40 }, + true + ); + } + + render() { + return ( + + { this.map = ref; }} + style={styles.map} + initialRegion={{ + latitude: LATITUDE, + longitude: LONGITUDE, + latitudeDelta: LATITUDE_DELTA, + longitudeDelta: LONGITUDE_DELTA, + }} + > + {MARKERS.map((marker, i) => ( + + ))} + + + this.fitBottomTwoMarkers()} + style={[styles.bubble, styles.button]} + > + Fit Bottom Two Markers + + this.fitAllMarkers()} + style={[styles.bubble, styles.button]} + > + Fit All Markers + + + + ); + } +} + +const styles = StyleSheet.create({ + container: { + ...StyleSheet.absoluteFillObject, + justifyContent: 'flex-end', + alignItems: 'center', + }, + map: { + ...StyleSheet.absoluteFillObject, + }, + bubble: { + backgroundColor: 'rgba(255,255,255,0.7)', + paddingHorizontal: 18, + paddingVertical: 12, + borderRadius: 20, + }, + button: { + marginTop: 12, + paddingHorizontal: 12, + alignItems: 'center', + marginHorizontal: 10, + }, + buttonContainer: { + flexDirection: 'column', + marginVertical: 20, + backgroundColor: 'transparent', + }, +}); + +module.exports = FitToCoordinates; From bcfad6bd17a0207f59647441ed366e5354f2d366 Mon Sep 17 00:00:00 2001 From: Chris Knepper Date: Tue, 13 Sep 2016 00:30:53 -0400 Subject: [PATCH 0074/1148] -Port fitToCoordinates functionality over to Android --- .../android/react/maps/AirMapManager.java | 7 ++++- .../airbnb/android/react/maps/AirMapView.java | 27 +++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java b/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java index 211b27d14..b35737021 100644 --- a/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java +++ b/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java @@ -32,6 +32,7 @@ public class AirMapManager extends ViewGroupManager { private static final int ANIMATE_TO_COORDINATE = 2; private static final int FIT_TO_ELEMENTS = 3; private static final int FIT_TO_SUPPLIED_MARKERS = 4; + private static final int FIT_TO_COORDINATES = 5; private final Map MAP_TYPES = MapBuilder.of( "standard", GoogleMap.MAP_TYPE_NORMAL, @@ -218,6 +219,9 @@ public void receiveCommand(AirMapView view, int commandId, @Nullable ReadableArr case FIT_TO_SUPPLIED_MARKERS: view.fitToSuppliedMarkers(args.getArray(0), args.getBoolean(1)); break; + case FIT_TO_COORDINATES: + view.fitToCoordinates(args.getArray(0), args.getMap(1), args.getBoolean(2)); + break; } } @@ -251,7 +255,8 @@ public Map getCommandsMap() { "animateToRegion", ANIMATE_TO_REGION, "animateToCoordinate", ANIMATE_TO_COORDINATE, "fitToElements", FIT_TO_ELEMENTS, - "fitToSuppliedMarkers", FIT_TO_SUPPLIED_MARKERS + "fitToSuppliedMarkers", FIT_TO_SUPPLIED_MARKERS, + "fitToCoordinates", FIT_TO_COORDINATES ); } diff --git a/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java b/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java index a772aeff2..e0fa58f48 100644 --- a/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java +++ b/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java @@ -536,6 +536,33 @@ public void fitToSuppliedMarkers(ReadableArray markerIDsArray, boolean animated) } } + public void fitToCoordinates(ReadableArray coordinatesArray, ReadableMap edgePadding, boolean animated) { + //Log.d("AirMapView", "running thru the 6 with my woes"); + LatLngBounds.Builder builder = new LatLngBounds.Builder(); + + for (int i = 0; i < coordinatesArray.size(); i++) { + ReadableMap latLng = coordinatesArray.getMap(i); + Double lat = latLng.getDouble("latitude"); + Double lng = latLng.getDouble("longitude"); + builder.include(new LatLng(lat, lng)); + } + + LatLngBounds bounds = builder.build(); + CameraUpdate cu = CameraUpdateFactory.newLatLngBounds(bounds, 50); + + if(edgePadding != null) { + map.setPadding(edgePadding.getInt("left"), edgePadding.getInt("top"), edgePadding.getInt("right"), edgePadding.getInt("bottom")); + } + + if (animated) { + startMonitoringRegion(); + map.animateCamera(cu); + } else { + map.moveCamera(cu); + } + map.setPadding(0, 0, 0, 0); // Without this, the Google logo is moved up by the value of edgePadding.bottom + } + // InfoWindowAdapter interface @Override From d63e849244ef83db0dc01f0fec87af3a32f75b70 Mon Sep 17 00:00:00 2001 From: Chris Knepper Date: Tue, 13 Sep 2016 15:48:48 -0400 Subject: [PATCH 0075/1148] -Set constant for baseMapPadding used in newLatLngBounds calls -Remove extraenous comment --- .../com/airbnb/android/react/maps/AirMapView.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java b/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java index e0fa58f48..6f44294f4 100644 --- a/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java +++ b/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java @@ -58,6 +58,8 @@ public class AirMapView extends MapView implements GoogleMap.InfoWindowAdapter, private Boolean isMapLoaded = false; private Integer loadingBackgroundColor = null; private Integer loadingIndicatorColor = null; + private final int baseMapPadding = 50; + private LatLngBounds boundsToMove; private boolean showUserLocation = false; private boolean isMonitoringRegion = false; @@ -488,10 +490,9 @@ public void fitToElements(boolean animated) { } // TODO(lmr): may want to include shapes / etc. } - if (addedPosition) { LatLngBounds bounds = builder.build(); - CameraUpdate cu = CameraUpdateFactory.newLatLngBounds(bounds, 50); + CameraUpdate cu = CameraUpdateFactory.newLatLngBounds(bounds, baseMapPadding); if (animated) { startMonitoringRegion(); map.animateCamera(cu); @@ -526,7 +527,7 @@ public void fitToSuppliedMarkers(ReadableArray markerIDsArray, boolean animated) if (addedPosition) { LatLngBounds bounds = builder.build(); - CameraUpdate cu = CameraUpdateFactory.newLatLngBounds(bounds, 50); + CameraUpdate cu = CameraUpdateFactory.newLatLngBounds(bounds, baseMapPadding); if (animated) { startMonitoringRegion(); map.animateCamera(cu); @@ -537,7 +538,6 @@ public void fitToSuppliedMarkers(ReadableArray markerIDsArray, boolean animated) } public void fitToCoordinates(ReadableArray coordinatesArray, ReadableMap edgePadding, boolean animated) { - //Log.d("AirMapView", "running thru the 6 with my woes"); LatLngBounds.Builder builder = new LatLngBounds.Builder(); for (int i = 0; i < coordinatesArray.size(); i++) { @@ -548,9 +548,9 @@ public void fitToCoordinates(ReadableArray coordinatesArray, ReadableMap edgePad } LatLngBounds bounds = builder.build(); - CameraUpdate cu = CameraUpdateFactory.newLatLngBounds(bounds, 50); + CameraUpdate cu = CameraUpdateFactory.newLatLngBounds(bounds, baseMapPadding); - if(edgePadding != null) { + if (edgePadding != null) { map.setPadding(edgePadding.getInt("left"), edgePadding.getInt("top"), edgePadding.getInt("right"), edgePadding.getInt("bottom")); } From 36476025deed5faac2a469c2fa6076ad4e9802aa Mon Sep 17 00:00:00 2001 From: Naoufal Kadhom Date: Sat, 17 Sep 2016 12:46:17 -0400 Subject: [PATCH 0076/1148] Add default arguments to fitToCoordinates --- components/MapView.js | 6 +++++- ios/AirMaps/AIRMapManager.m | 20 ++++++++------------ 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/components/MapView.js b/components/MapView.js index c76f73d17..07f278777 100644 --- a/components/MapView.js +++ b/components/MapView.js @@ -436,7 +436,11 @@ class MapView extends React.Component { this._runCommand('fitToSuppliedMarkers', [markers, animated]); } - fitToCoordinates(coordinates, edgePadding, animated) { + fitToCoordinates( + coordinates = [], + edgePadding = { top: 0, right: 0, bottom: 0, left: 0 }, + animated = true + ) { this._runCommand('fitToCoordinates', [coordinates, edgePadding, animated]); } diff --git a/ios/AirMaps/AIRMapManager.m b/ios/AirMaps/AIRMapManager.m index e79fe70dd..1e9ab10be 100644 --- a/ios/AirMaps/AIRMapManager.m +++ b/ios/AirMaps/AIRMapManager.m @@ -189,8 +189,8 @@ - (UIView *)view RCT_EXPORT_METHOD(fitToCoordinates:(nonnull NSNumber *)reactTag coordinates:(nonnull NSArray *)coordinates - edgePadding:(NSDictionary *)edgePadding - animated:(BOOL)animated) + edgePadding:(nonnull NSDictionary *)edgePadding + animated:(nonnull BOOL)animated) { [self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary *viewRegistry) { id view = viewRegistry[reactTag]; @@ -208,16 +208,12 @@ - (UIView *)view MKPolyline *polyline = [MKPolyline polylineWithCoordinates:coords count:coordinates.count]; // Set Map viewport - if (!edgePadding) { - [mapView setVisibleMapRect:[polyline boundingMapRect] animated:animated]; - } else { - CGFloat top = [RCTConvert CGFloat:edgePadding[@"top"]]; - CGFloat right = [RCTConvert CGFloat:edgePadding[@"right"]]; - CGFloat bottom = [RCTConvert CGFloat:edgePadding[@"bottom"]]; - CGFloat left = [RCTConvert CGFloat:edgePadding[@"left"]]; - - [mapView setVisibleMapRect:[polyline boundingMapRect] edgePadding:UIEdgeInsetsMake(top, left, bottom, right) animated:animated]; - } + CGFloat top = [RCTConvert CGFloat:edgePadding[@"top"]]; + CGFloat right = [RCTConvert CGFloat:edgePadding[@"right"]]; + CGFloat bottom = [RCTConvert CGFloat:edgePadding[@"bottom"]]; + CGFloat left = [RCTConvert CGFloat:edgePadding[@"left"]]; + + [mapView setVisibleMapRect:[polyline boundingMapRect] edgePadding:UIEdgeInsetsMake(top, left, bottom, right) animated:animated]; } }]; From c8986d5946a4b182ad2e8075da7638d703071e53 Mon Sep 17 00:00:00 2001 From: Naoufal Kadhom Date: Sat, 17 Sep 2016 12:46:51 -0400 Subject: [PATCH 0077/1148] Add edgePadding example --- example/examples/FitToCoordinates.js | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/example/examples/FitToCoordinates.js b/example/examples/FitToCoordinates.js index 651779295..395cfe247 100644 --- a/example/examples/FitToCoordinates.js +++ b/example/examples/FitToCoordinates.js @@ -32,11 +32,21 @@ const MARKERS = [ createMarker(4), ]; +const DEFAULT_PADDING = { top: 40, right: 40, bottom: 40, left: 40 }; + class FitToCoordinates extends React.Component { + fitPadding() { + this.map.fitToCoordinates( + [MARKERS[2], MARKERS[3]], + { top: 100, right: 100, bottom: 100, left: 100 }, + true + ); + } + fitBottomTwoMarkers() { this.map.fitToCoordinates( [MARKERS[2], MARKERS[3]], - { top: 40, right: 40, bottom: 40, left: 40 }, + DEFAULT_PADDING, true ); } @@ -44,7 +54,7 @@ class FitToCoordinates extends React.Component { fitAllMarkers() { this.map.fitToCoordinates( MARKERS, - { top: 40, right: 40, bottom: 40, left: 40 }, + DEFAULT_PADDING, true ); } @@ -70,6 +80,12 @@ class FitToCoordinates extends React.Component { ))}
+ this.fitPadding()} + style={[styles.bubble, styles.button]} + > + Fit Bottom Two Markers with Padding + this.fitBottomTwoMarkers()} style={[styles.bubble, styles.button]} From f3dd70c0ec37c66a9f31619840adeb32f96db310 Mon Sep 17 00:00:00 2001 From: Naoufal Kadhom Date: Sat, 17 Sep 2016 13:57:48 -0400 Subject: [PATCH 0078/1148] Update README with example --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index 34ec9ef33..db9a4dffa 100644 --- a/README.md +++ b/README.md @@ -369,6 +369,12 @@ Pass an array of marker identifiers to have the map re-focus. ![](http://i.giphy.com/3o7qEbOQnO0yoXqKJ2.gif) ![](http://i.giphy.com/l41YdrQZ7m6Dz4h0c.gif) +### Zoom to Specified Coordinates + +Pass an array of coordinates to focus a map region on said coordinates. + +![](https://cloud.githubusercontent.com/assets/1627824/18609960/da5d9e06-7cdc-11e6-811e-34e255093df9.gif) + ### Troubleshooting #### My map is blank From 1e81b06a56524be219c0da43bac8d403ff2bc66f Mon Sep 17 00:00:00 2001 From: Naoufal Kadhom Date: Thu, 22 Sep 2016 19:51:14 -0400 Subject: [PATCH 0079/1148] Add an options argument --- components/MapView.js | 11 ++++++----- example/examples/FitToCoordinates.js | 27 ++++++++++++--------------- 2 files changed, 18 insertions(+), 20 deletions(-) diff --git a/components/MapView.js b/components/MapView.js index 07f278777..50683cd5a 100644 --- a/components/MapView.js +++ b/components/MapView.js @@ -436,11 +436,12 @@ class MapView extends React.Component { this._runCommand('fitToSuppliedMarkers', [markers, animated]); } - fitToCoordinates( - coordinates = [], - edgePadding = { top: 0, right: 0, bottom: 0, left: 0 }, - animated = true - ) { + fitToCoordinates(coordinates = [], options) { + const { + edgePadding = { top: 0, right: 0, bottom: 0, left: 0 }, + animated = true, + } = options; + this._runCommand('fitToCoordinates', [coordinates, edgePadding, animated]); } diff --git a/example/examples/FitToCoordinates.js b/example/examples/FitToCoordinates.js index 395cfe247..c6c42ad4e 100644 --- a/example/examples/FitToCoordinates.js +++ b/example/examples/FitToCoordinates.js @@ -36,27 +36,24 @@ const DEFAULT_PADDING = { top: 40, right: 40, bottom: 40, left: 40 }; class FitToCoordinates extends React.Component { fitPadding() { - this.map.fitToCoordinates( - [MARKERS[2], MARKERS[3]], - { top: 100, right: 100, bottom: 100, left: 100 }, - true - ); + this.map.fitToCoordinates([MARKERS[2], MARKERS[3]], { + edgePadding: { top: 100, right: 100, bottom: 100, left: 100 }, + animated: true, + }); } fitBottomTwoMarkers() { - this.map.fitToCoordinates( - [MARKERS[2], MARKERS[3]], - DEFAULT_PADDING, - true - ); + this.map.fitToCoordinates([MARKERS[2], MARKERS[3]], { + edgePadding: DEFAULT_PADDING, + animated: true, + }); } fitAllMarkers() { - this.map.fitToCoordinates( - MARKERS, - DEFAULT_PADDING, - true - ); + this.map.fitToCoordinates(MARKERS, { + edgePadding: DEFAULT_PADDING, + animated: true, + }); } render() { From 59b026dc6f77bd5bf42317dafb5e88f65f7afbde Mon Sep 17 00:00:00 2001 From: Cihan Bebek Date: Sat, 24 Sep 2016 14:55:44 +0900 Subject: [PATCH 0080/1148] Fix minor typo --- docs/installation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/installation.md b/docs/installation.md index 57121005f..07f6e2f98 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -23,7 +23,7 @@ or do it manually as described below: 1. Setup your `Podfile` like the included `example/ios/Podfile` then run `pod install`. (If you do not need `GoogleMaps` support for iOS, then you can probably completely skip this step.) -2. Open your in xCode workspace +2. Open your project in xCode workspace 3. Drag the following folder into your project: - `node_modules/react-native-maps/ios/AirMaps/` 4. If you need `GoogleMaps` support also drag this folder into your project: From 8fb1c21368b1a0c578abf4ed64c382c11d0436cf Mon Sep 17 00:00:00 2001 From: Cihan Bebek Date: Sat, 24 Sep 2016 15:03:27 +0900 Subject: [PATCH 0081/1148] Add relative links to Podfiles Add relative links to point at repo's example Podfile --- docs/installation.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/installation.md b/docs/installation.md index 57121005f..08f86567a 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -21,7 +21,7 @@ or do it manually as described below: ### Option 1: Cocoapods - Same as the included AirMapsExplorer example -1. Setup your `Podfile` like the included `example/ios/Podfile` then run `pod install`. +1. Setup your `Podfile` like the included [example/ios/Podfile](../example/ios/Podfile) then run `pod install`. (If you do not need `GoogleMaps` support for iOS, then you can probably completely skip this step.) 2. Open your in xCode workspace 3. Drag the following folder into your project: @@ -43,7 +43,7 @@ If you need `GoogleMaps` support in iOS also add this line: pod 'react-native-google-maps', :path => '../node_modules/react-native-maps' Now if you need `GoogleMaps` support you will also have to add a bunch of other stuff to your -`Podfile`. See the **comments* in the included `example/ios/Podfile` which explain the rest. +`Podfile`. See the **comments* in the included [example/ios/Podfile](../example/ios/Podfile) which explain the rest. After your `Podfile` is setup properly, run `pod install`. From d42a3b19dc561dfdf1e2a631112f92a1926a1379 Mon Sep 17 00:00:00 2001 From: IjzerenHein Date: Sun, 25 Sep 2016 13:18:04 +0200 Subject: [PATCH 0082/1148] Added support for AnimatedRegion without modifying the AnimatedImplementation.js of react-native --- README.md | 30 ++++++------ components/AnimatedRegion.js | 91 +++++++++++++++++------------------- components/MapView.js | 2 + 3 files changed, 59 insertions(+), 64 deletions(-) diff --git a/README.md b/README.md index db9a4dffa..c7bad724e 100644 --- a/README.md +++ b/README.md @@ -263,25 +263,16 @@ Enable lite mode on Android with `liteMode` prop. Ideal when having multiple map [`` Component API](docs/circle.md) - -## Using with the Animated API - -The API of this Map has been built with the intention of it being able to utilize the [Animated API](https://facebook.github.io/react-native/docs/animated.html). - -In order to get this to work, you will need to modify the `AnimatedImplementation.js` file in the -source of react-native with [this one](https://gist.github.com/lelandrichardson/c0d938e02301f9294465). - -Ideally this will be possible in the near future without this modification. - ### Animated Region -The MapView can accept an `Animated.Region` value as its `region` prop. This allows you to utilize -the Animated API to control the map's center and zoom. +The MapView can accept an `MapView.AnimatedRegion` value as its `region` prop. This allows you to utilize the Animated API to control the map's center and zoom. ```jsx +import MapView from 'react-native-maps'; + getInitialState() { return { - region: new Animated.Region({ + region: new MapView.AnimatedRegion({ latitude: LATITUDE, longitude: LONGITUDE, latitudeDelta: LATITUDE_DELTA, @@ -306,18 +297,27 @@ render() { ### Animated Marker Position -Markers can also accept an `Animated.Region` value as a coordinate. +Markers can also accept an `AnimatedRegion` value as a coordinate. ```jsx getInitialState() { return { - coordinate: new Animated.Region({ + coordinate: new MapView.AnimatedRegion({ latitude: LATITUDE, longitude: LONGITUDE, }), }; } +componentWillReceiveProps(nextProps) { + if (this.props.coordinate !== nextProps.coordinate) { + this.state.coordinate.timing({ + ...nextProps.coordinate, + duration: 500 + }).start(); + } +} + render() { return ( diff --git a/components/AnimatedRegion.js b/components/AnimatedRegion.js index 26ed81da4..c6a30926f 100644 --- a/components/AnimatedRegion.js +++ b/components/AnimatedRegion.js @@ -1,45 +1,38 @@ /* eslint-disable */ +import {Animated} from 'react-native'; -class AnimatedRegion extends AnimatedWithChildren { - // latitude: AnimatedValue; - // longitude: AnimatedValue; - // latitudeDelta: AnimatedValue; - // longitudeDelta: AnimatedValue; - // _listeners: {[key: string]: { - // latitude: string, - // longitude: string, - // latitudeDelta: string; - // longitudeDelta: string, - // }}; +const AnimatedWithChildren = Object.getPrototypeOf(Animated.ValueXY); +if (AnimatedWithChildren.name !== 'AnimatedWithChildren') console.error('AnimatedRegion could not obtain AnimatedWithChildren base class'); +// const __Animated = Object.getPrototypeOf(AnimatedWithChildren); +// if (__Animated.name !== 'Animated') console.error('AnimatedRegion could not obtain Animated base class'); +var _uniqueId = 1; + +export default class AnimatedMapRegion extends AnimatedWithChildren { constructor(valueIn) { super(); - const value = valueIn || { // probably want to come up with better defaults + var value = valueIn || { // probably want to come up with better defaults latitude: 0, longitude: 0, latitudeDelta: 0, - longitudeDelta: 0, + longitudeDelta: 0 }; - this.latitude = value.latitude instanceof Animated + this.latitude = value.latitude instanceof Animated.Value ? value.latitude - : new AnimatedValue(value.latitude); - this.longitude = value.longitude instanceof Animated + : new Animated.Value(value.latitude); + this.longitude = value.longitude instanceof Animated.Value ? value.longitude - : new AnimatedValue(value.longitude); - this.latitudeDelta = value.latitudeDelta instanceof Animated + : new Animated.Value(value.longitude); + this.latitudeDelta = value.latitudeDelta instanceof Animated.Value ? value.latitudeDelta - : new AnimatedValue(value.latitudeDelta); - this.longitudeDelta = value.longitudeDelta instanceof Animated + : new Animated.Value(value.latitudeDelta); + this.longitudeDelta = value.longitudeDelta instanceof Animated.Value ? value.longitudeDelta - : new AnimatedValue(value.longitudeDelta); + : new Animated.Value(value.longitudeDelta); this._listeners = {}; } setValue(value) { - // this.latitude.setValue(value.latitude); - // this.longitude.setValue(value.longitude); - // this.latitudeDelta.setValue(value.latitudeDelta); - // this.longitudeDelta.setValue(value.longitudeDelta); this.latitude._value = value.latitude; this.longitude._value = value.longitude; this.latitudeDelta._value = value.latitudeDelta; @@ -65,7 +58,7 @@ class AnimatedRegion extends AnimatedWithChildren { latitude: this.latitude.__getValue(), longitude: this.longitude.__getValue(), latitudeDelta: this.latitudeDelta.__getValue(), - longitudeDelta: this.longitudeDelta.__getValue(), + longitudeDelta: this.longitudeDelta.__getValue() }; } @@ -92,15 +85,15 @@ class AnimatedRegion extends AnimatedWithChildren { } addListener(callback) { - const id = String(_uniqueId++); - const jointCallback = ({ value: number }) => { + var id = String(_uniqueId++); + var jointCallback = (/*{value}*/) => { callback(this.__getValue()); }; this._listeners[id] = { latitude: this.latitude.addListener(jointCallback), longitude: this.longitude.addListener(jointCallback), latitudeDelta: this.latitudeDelta.addListener(jointCallback), - longitudeDelta: this.longitudeDelta.addListener(jointCallback), + longitudeDelta: this.longitudeDelta.addListener(jointCallback) }; return id; } @@ -114,60 +107,60 @@ class AnimatedRegion extends AnimatedWithChildren { } spring(config) { - const animations = []; + var animations = []; config.hasOwnProperty('latitude') && - animations.push(timing(this.latitude, { + animations.push(Animated.timing(this.latitude, { ...config, - toValue: config.latitude, + toValue: config.latitude })); config.hasOwnProperty('longitude') && - animations.push(timing(this.longitude, { + animations.push(Animated.timing(this.longitude, { ...config, - toValue: config.longitude, + toValue: config.longitude })); config.hasOwnProperty('latitudeDelta') && - animations.push(timing(this.latitudeDelta, { + animations.push(Animated.timing(this.latitudeDelta, { ...config, - toValue: config.latitudeDelta, + toValue: config.latitudeDelta })); config.hasOwnProperty('longitudeDelta') && - animations.push(timing(this.longitudeDelta, { + animations.push(Animated.timing(this.longitudeDelta, { ...config, - toValue: config.longitudeDelta, + toValue: config.longitudeDelta })); - return parallel(animations); + return Animated.parallel(animations); } timing(config) { - const animations = []; + var animations = []; config.hasOwnProperty('latitude') && - animations.push(timing(this.latitude, { + animations.push(Animated.timing(this.latitude, { ...config, - toValue: config.latitude, + toValue: config.latitude })); config.hasOwnProperty('longitude') && - animations.push(timing(this.longitude, { + animations.push(Animated.timing(this.longitude, { ...config, - toValue: config.longitude, + toValue: config.longitude })); config.hasOwnProperty('latitudeDelta') && - animations.push(timing(this.latitudeDelta, { + animations.push(Animated.timing(this.latitudeDelta, { ...config, - toValue: config.latitudeDelta, + toValue: config.latitudeDelta })); config.hasOwnProperty('longitudeDelta') && - animations.push(timing(this.longitudeDelta, { + animations.push(Animated.timing(this.longitudeDelta, { ...config, - toValue: config.longitudeDelta, + toValue: config.longitudeDelta })); - return parallel(animations); + return Animated.parallel(animations); } } diff --git a/components/MapView.js b/components/MapView.js index 50683cd5a..429a71133 100644 --- a/components/MapView.js +++ b/components/MapView.js @@ -15,6 +15,7 @@ import MapPolygon from './MapPolygon'; import MapCircle from './MapCircle'; import MapCallout from './MapCallout'; import MapUrlTile from './MapUrlTile'; +import AnimatedRegion from './AnimatedRegion'; import { contextTypes as childContextTypes, getAirMapName, @@ -571,5 +572,6 @@ Object.assign(MapView, ProviderConstants); MapView.ProviderPropType = PropTypes.oneOf(Object.values(ProviderConstants)); MapView.Animated = Animated.createAnimatedComponent(MapView); +MapView.AnimatedRegion = AnimatedRegion; module.exports = MapView; From c9055e5cd6c11ce2d78df23dad31a5f3c978b6a9 Mon Sep 17 00:00:00 2001 From: IjzerenHein Date: Sun, 25 Sep 2016 18:48:22 +0200 Subject: [PATCH 0083/1148] =?UTF-8?q?Wrapped=20getAnimatedWithChildren=20p?= =?UTF-8?q?rototype=20check=20in=20=5F=5FDEV=5F=5F=20to=20ensure=20it=20do?= =?UTF-8?q?esn=E2=80=99t=20break=20minification/obfuscation=20builds?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/AnimatedRegion.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/components/AnimatedRegion.js b/components/AnimatedRegion.js index c6a30926f..29356ca9e 100644 --- a/components/AnimatedRegion.js +++ b/components/AnimatedRegion.js @@ -2,7 +2,9 @@ import {Animated} from 'react-native'; const AnimatedWithChildren = Object.getPrototypeOf(Animated.ValueXY); -if (AnimatedWithChildren.name !== 'AnimatedWithChildren') console.error('AnimatedRegion could not obtain AnimatedWithChildren base class'); +if (__DEV__) { + if (AnimatedWithChildren.name !== 'AnimatedWithChildren') console.error('AnimatedRegion could not obtain AnimatedWithChildren base class'); +} // const __Animated = Object.getPrototypeOf(AnimatedWithChildren); // if (__Animated.name !== 'Animated') console.error('AnimatedRegion could not obtain Animated base class'); From 0d21b7a137cc7f383af3685156f84e58b31e22bf Mon Sep 17 00:00:00 2001 From: Simon Mitchell Date: Mon, 26 Sep 2016 14:23:20 +0100 Subject: [PATCH 0084/1148] Fixes compiler error on nonnull BOOL... --- ios/AirMaps/AIRMapManager.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ios/AirMaps/AIRMapManager.m b/ios/AirMaps/AIRMapManager.m index 1e9ab10be..98d823d27 100644 --- a/ios/AirMaps/AIRMapManager.m +++ b/ios/AirMaps/AIRMapManager.m @@ -190,7 +190,7 @@ - (UIView *)view RCT_EXPORT_METHOD(fitToCoordinates:(nonnull NSNumber *)reactTag coordinates:(nonnull NSArray *)coordinates edgePadding:(nonnull NSDictionary *)edgePadding - animated:(nonnull BOOL)animated) + animated:(BOOL)animated) { [self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary *viewRegistry) { id view = viewRegistry[reactTag]; From 219ce92db04f649d08e70bce680fa8f8307c92fd Mon Sep 17 00:00:00 2001 From: IjzerenHein Date: Mon, 26 Sep 2016 22:13:48 +0200 Subject: [PATCH 0085/1148] Added support for drawing polylines on snapshots --- ios/AirMaps.xcodeproj/project.pbxproj | 1 + ios/AirMaps/AIRMapManager.m | 6 +++++ ios/AirMaps/AIRMapPolyline.m | 39 +++++++++++++++++++++++++++ ios/AirMaps/AIRMapSnapshot.h | 17 ++++++++++++ 4 files changed, 63 insertions(+) create mode 100644 ios/AirMaps/AIRMapSnapshot.h diff --git a/ios/AirMaps.xcodeproj/project.pbxproj b/ios/AirMaps.xcodeproj/project.pbxproj index 274cb11f3..3db374149 100644 --- a/ios/AirMaps.xcodeproj/project.pbxproj +++ b/ios/AirMaps.xcodeproj/project.pbxproj @@ -155,6 +155,7 @@ 1125B2D31C4AD3DA007D0023 /* AIRMapPolyline.h */, 1125B2D51C4AD3DA007D0023 /* AIRMapPolylineManager.h */, 1125B2D61C4AD3DA007D0023 /* AIRMapPolylineManager.m */, + 21B6E2D21D99B886007E664F /* AIRMapSnapshot.h */, 1125B2F01C4AD445007D0023 /* SMCalloutView.h */, 1125B2F11C4AD445007D0023 /* SMCalloutView.m */, 1125B2D81C4AD3DA007D0023 /* RCTConvert+MoreMapKit.h */, diff --git a/ios/AirMaps/AIRMapManager.m b/ios/AirMaps/AIRMapManager.m index 1e9ab10be..3c1e1ad3b 100644 --- a/ios/AirMaps/AIRMapManager.m +++ b/ios/AirMaps/AIRMapManager.m @@ -284,6 +284,12 @@ - (void)takeMapSnapshot:(AIRMap *)mapView [pin.image drawAtPoint:point]; } } + + for (id overlay in mapView.overlays) { + if ([overlay respondsToSelector:@selector(drawToSnapshot:context:)]) { + [overlay drawToSnapshot:snapshot context:UIGraphicsGetCurrentContext()]; + } + } UIImage *compositeImage = UIGraphicsGetImageFromCurrentImageContext(); diff --git a/ios/AirMaps/AIRMapPolyline.m b/ios/AirMaps/AIRMapPolyline.m index b4aa57c27..5b28167fd 100644 --- a/ios/AirMaps/AIRMapPolyline.m +++ b/ios/AirMaps/AIRMapPolyline.m @@ -104,4 +104,43 @@ - (BOOL)canReplaceMapContent return NO; } + +#pragma mark AIRMapSnapshot implementation + +- (void) drawToSnapshot:(MKMapSnapshot *) snapshot context:(CGContextRef) context +{ + // Prepare context + CGContextSetStrokeColorWithColor(context, self.strokeColor.CGColor); + CGContextSetLineWidth(context, self.strokeWidth); + CGContextSetLineCap(context, self.lineCap); + CGContextSetLineJoin(context, self.lineJoin); + CGContextSetMiterLimit(context, self.miterLimit); + CGFloat dashes[self.lineDashPattern.count]; + for (NSUInteger i = 0; i < self.lineDashPattern.count; i++) { + dashes[i] = self.lineDashPattern[i].floatValue; + } + CGContextSetLineDash(context, self.lineDashPhase, dashes, self.lineDashPattern.count); + + // Begin path + CGContextBeginPath(context); + + // Get coordinates + CLLocationCoordinate2D coordinates[[self.polyline pointCount]]; + [self.polyline getCoordinates:coordinates range:NSMakeRange(0, [self.polyline pointCount])]; + + // Draw line segments + for(int i = 0; i < [self.polyline pointCount]; i++) { + CGPoint point = [snapshot pointForCoordinate:coordinates[i]]; + if (i == 0) { + CGContextMoveToPoint(context,point.x, point.y); + } + else{ + CGContextAddLineToPoint(context,point.x, point.y); + } + } + + // Finish path + CGContextStrokePath(context); +} + @end \ No newline at end of file diff --git a/ios/AirMaps/AIRMapSnapshot.h b/ios/AirMaps/AIRMapSnapshot.h new file mode 100644 index 000000000..49d363796 --- /dev/null +++ b/ios/AirMaps/AIRMapSnapshot.h @@ -0,0 +1,17 @@ +// +// AIRMapSnapshot.h +// AirMaps +// +// Created by Hein Rutjes on 26/09/16. +// Copyright © 2016 Christopher. All rights reserved. +// + +#ifndef AIRMapSnapshot_h +#define AIRMapSnapshot_h + +@protocol AIRMapSnapshot +@optional +- (void) drawToSnapshot:(MKMapSnapshot *) snapshot context:(CGContextRef) context; +@end + +#endif /* AIRMapSnapshot_h */ From 06c7986a622230012380536968326a225b9d276d Mon Sep 17 00:00:00 2001 From: Gil Birman Date: Tue, 27 Sep 2016 14:10:15 -0700 Subject: [PATCH 0086/1148] Update examples-setup.md --- docs/examples-setup.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/examples-setup.md b/docs/examples-setup.md index dc55f7cf4..abd86a1ed 100644 --- a/docs/examples-setup.md +++ b/docs/examples-setup.md @@ -4,11 +4,11 @@ 1. Install dependencies and open the workspace: - cd example - npm install - cd ios - pod install - open AirMapsExplorer.xcworkspace + cd example + npm install + cd ios + pod install + open AirMapsExplorer.xcworkspace 2. Make sure the `AirMapsExplorer` target is selected and click `Run` From 9b6e90a862366d19a68ddc0b806fa3b983aa29db Mon Sep 17 00:00:00 2001 From: Gil Birman Date: Tue, 27 Sep 2016 14:10:36 -0700 Subject: [PATCH 0087/1148] Update examples-setup.md --- docs/examples-setup.md | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/docs/examples-setup.md b/docs/examples-setup.md index abd86a1ed..35a8e6942 100644 --- a/docs/examples-setup.md +++ b/docs/examples-setup.md @@ -4,11 +4,13 @@ 1. Install dependencies and open the workspace: - cd example - npm install - cd ios - pod install - open AirMapsExplorer.xcworkspace +``` +cd example +npm install +cd ios +pod install +open AirMapsExplorer.xcworkspace +``` 2. Make sure the `AirMapsExplorer` target is selected and click `Run` @@ -18,4 +20,6 @@ 2. Install via gradle: - ./example/android/gradlew installDebug +``` +./example/android/gradlew installDebug +``` From ade4da891c2aab6376db8370330213db6571e802 Mon Sep 17 00:00:00 2001 From: Spike Brehm Date: Tue, 27 Sep 2016 16:25:19 -0700 Subject: [PATCH 0088/1148] Fix import of AIRMapSnapshot --- ios/AirMaps/AIRMapManager.m | 1 + 1 file changed, 1 insertion(+) diff --git a/ios/AirMaps/AIRMapManager.m b/ios/AirMaps/AIRMapManager.m index 6be5acbe2..c45711c3f 100644 --- a/ios/AirMaps/AIRMapManager.m +++ b/ios/AirMaps/AIRMapManager.m @@ -25,6 +25,7 @@ #import "AIRMapCircle.h" #import "SMCalloutView.h" #import "AIRMapUrlTile.h" +#import "AIRMapSnapshot.h" #import From 9613dd3970b6f623bd0be3408d151e8b275a5a85 Mon Sep 17 00:00:00 2001 From: gilbox Date: Tue, 27 Sep 2016 16:24:50 -0700 Subject: [PATCH 0089/1148] Fix/Remove AirMaps Pods issues --- ios/AirMaps.xcodeproj/project.pbxproj | 103 +----------------- .../contents.xcworkspacedata | 10 -- ios/Podfile | 21 ---- ios/Podfile.lock | 51 --------- 4 files changed, 2 insertions(+), 183 deletions(-) delete mode 100644 ios/AirMaps.xcworkspace/contents.xcworkspacedata delete mode 100644 ios/Podfile delete mode 100644 ios/Podfile.lock diff --git a/ios/AirMaps.xcodeproj/project.pbxproj b/ios/AirMaps.xcodeproj/project.pbxproj index 3db374149..4be12b6bc 100644 --- a/ios/AirMaps.xcodeproj/project.pbxproj +++ b/ios/AirMaps.xcodeproj/project.pbxproj @@ -22,14 +22,8 @@ 1125B2E61C4AD3DA007D0023 /* AIRMapPolylineManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 1125B2D61C4AD3DA007D0023 /* AIRMapPolylineManager.m */; }; 1125B2E71C4AD3DA007D0023 /* RCTConvert+MoreMapKit.m in Sources */ = {isa = PBXBuildFile; fileRef = 1125B2D91C4AD3DA007D0023 /* RCTConvert+MoreMapKit.m */; }; 1125B2F21C4AD445007D0023 /* SMCalloutView.m in Sources */ = {isa = PBXBuildFile; fileRef = 1125B2F11C4AD445007D0023 /* SMCalloutView.m */; }; - DA6C26381C9E2AFE0035349F /* AIRMapUrlTile.m in Sources */ = {isa = PBXBuildFile; fileRef = DA6C26371C9E2AFE0035349F /* AIRMapUrlTile.m */; settings = {ASSET_TAGS = (); }; }; - DA6C263E1C9E324A0035349F /* AIRMapUrlTileManager.m in Sources */ = {isa = PBXBuildFile; fileRef = DA6C263D1C9E324A0035349F /* AIRMapUrlTileManager.m */; settings = {ASSET_TAGS = (); }; }; - 215D95711D7A27BF000DF827 /* AIRGoogleMapMarker.m in Sources */ = {isa = PBXBuildFile; fileRef = 215D95701D7A27BF000DF827 /* AIRGoogleMapMarker.m */; }; - 216133031D7A2F880024C623 /* AIRGoogleMapMarkerManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 216133021D7A2F880024C623 /* AIRGoogleMapMarkerManager.m */; }; - 216133061D7E64D90024C623 /* AIRGMSMarker.m in Sources */ = {isa = PBXBuildFile; fileRef = 216133051D7E64D90024C623 /* AIRGMSMarker.m */; }; - 21E657271D78DAE600B75EE5 /* AIRGoogleMapManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 21E657261D78DAE600B75EE5 /* AIRGoogleMapManager.m */; }; - 21E6572A1D78E03E00B75EE5 /* AIRGoogleMap.m in Sources */ = {isa = PBXBuildFile; fileRef = 21E657291D78E03E00B75EE5 /* AIRGoogleMap.m */; }; - BA9CB783B2222EB8372E95C3 /* libPods-AirMaps.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 6F3FD30B4FC9B3779A288DC7 /* libPods-AirMaps.a */; }; + DA6C26381C9E2AFE0035349F /* AIRMapUrlTile.m in Sources */ = {isa = PBXBuildFile; fileRef = DA6C26371C9E2AFE0035349F /* AIRMapUrlTile.m */; }; + DA6C263E1C9E324A0035349F /* AIRMapUrlTileManager.m in Sources */ = {isa = PBXBuildFile; fileRef = DA6C263D1C9E324A0035349F /* AIRMapUrlTileManager.m */; }; /* End PBXBuildFile section */ /* Begin PBXCopyFilesBuildPhase section */ @@ -80,19 +74,6 @@ DA6C26371C9E2AFE0035349F /* AIRMapUrlTile.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRMapUrlTile.m; sourceTree = ""; }; DA6C263C1C9E324A0035349F /* AIRMapUrlTileManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRMapUrlTileManager.h; sourceTree = ""; }; DA6C263D1C9E324A0035349F /* AIRMapUrlTileManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRMapUrlTileManager.m; sourceTree = ""; }; - 215D956F1D7A27BF000DF827 /* AIRGoogleMapMarker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AIRGoogleMapMarker.h; path = Google/AIRGoogleMapMarker.h; sourceTree = ""; }; - 215D95701D7A27BF000DF827 /* AIRGoogleMapMarker.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AIRGoogleMapMarker.m; path = Google/AIRGoogleMapMarker.m; sourceTree = ""; }; - 216133011D7A2F880024C623 /* AIRGoogleMapMarkerManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AIRGoogleMapMarkerManager.h; path = Google/AIRGoogleMapMarkerManager.h; sourceTree = ""; }; - 216133021D7A2F880024C623 /* AIRGoogleMapMarkerManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AIRGoogleMapMarkerManager.m; path = Google/AIRGoogleMapMarkerManager.m; sourceTree = ""; }; - 216133041D7E64D90024C623 /* AIRGMSMarker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AIRGMSMarker.h; path = Google/AIRGMSMarker.h; sourceTree = ""; }; - 216133051D7E64D90024C623 /* AIRGMSMarker.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AIRGMSMarker.m; path = Google/AIRGMSMarker.m; sourceTree = ""; }; - 21E657251D78DAE600B75EE5 /* AIRGoogleMapManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AIRGoogleMapManager.h; path = Google/AIRGoogleMapManager.h; sourceTree = ""; }; - 21E657261D78DAE600B75EE5 /* AIRGoogleMapManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AIRGoogleMapManager.m; path = Google/AIRGoogleMapManager.m; sourceTree = ""; }; - 21E657281D78E03E00B75EE5 /* AIRGoogleMap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AIRGoogleMap.h; path = Google/AIRGoogleMap.h; sourceTree = ""; }; - 21E657291D78E03E00B75EE5 /* AIRGoogleMap.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AIRGoogleMap.m; path = Google/AIRGoogleMap.m; sourceTree = ""; }; - 6F3FD30B4FC9B3779A288DC7 /* libPods-AirMaps.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-AirMaps.a"; sourceTree = BUILT_PRODUCTS_DIR; }; - 8CCE0467700E33644F88F948 /* Pods-AirMaps.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AirMaps.debug.xcconfig"; path = "Pods/Target Support Files/Pods-AirMaps/Pods-AirMaps.debug.xcconfig"; sourceTree = ""; }; - D22E28ACFEBD663EF2744EFE /* Pods-AirMaps.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AirMaps.release.xcconfig"; path = "Pods/Target Support Files/Pods-AirMaps/Pods-AirMaps.release.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -100,7 +81,6 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - BA9CB783B2222EB8372E95C3 /* libPods-AirMaps.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -112,8 +92,6 @@ children = ( 11FA5C531C4A1296003AC2EE /* AirMaps */, 11FA5C521C4A1296003AC2EE /* Products */, - 6F0AEBE80A623FE41FDC8708 /* Pods */, - 4712B0CE6DC6BF94D04BA69A /* Frameworks */, ); sourceTree = ""; }; @@ -128,7 +106,6 @@ 11FA5C531C4A1296003AC2EE /* AirMaps */ = { isa = PBXGroup; children = ( - 21E657241D78DA9600B75EE5 /* Google */, 1125B2BD1C4AD3DA007D0023 /* AIRMap.h */, 1125B2BE1C4AD3DA007D0023 /* AIRMap.m */, 1125B2BF1C4AD3DA007D0023 /* AIRMapCallout.h */, @@ -168,40 +145,6 @@ path = AirMaps; sourceTree = ""; }; - 21E657241D78DA9600B75EE5 /* Google */ = { - isa = PBXGroup; - children = ( - 21E657251D78DAE600B75EE5 /* AIRGoogleMapManager.h */, - 21E657261D78DAE600B75EE5 /* AIRGoogleMapManager.m */, - 21E657281D78E03E00B75EE5 /* AIRGoogleMap.h */, - 21E657291D78E03E00B75EE5 /* AIRGoogleMap.m */, - 215D956F1D7A27BF000DF827 /* AIRGoogleMapMarker.h */, - 215D95701D7A27BF000DF827 /* AIRGoogleMapMarker.m */, - 216133011D7A2F880024C623 /* AIRGoogleMapMarkerManager.h */, - 216133021D7A2F880024C623 /* AIRGoogleMapMarkerManager.m */, - 216133041D7E64D90024C623 /* AIRGMSMarker.h */, - 216133051D7E64D90024C623 /* AIRGMSMarker.m */, - ); - name = Google; - sourceTree = ""; - }; - 4712B0CE6DC6BF94D04BA69A /* Frameworks */ = { - isa = PBXGroup; - children = ( - 6F3FD30B4FC9B3779A288DC7 /* libPods-AirMaps.a */, - ); - name = Frameworks; - sourceTree = ""; - }; - 6F0AEBE80A623FE41FDC8708 /* Pods */ = { - isa = PBXGroup; - children = ( - 8CCE0467700E33644F88F948 /* Pods-AirMaps.debug.xcconfig */, - D22E28ACFEBD663EF2744EFE /* Pods-AirMaps.release.xcconfig */, - ); - name = Pods; - sourceTree = ""; - }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -209,11 +152,9 @@ isa = PBXNativeTarget; buildConfigurationList = 11FA5C5A1C4A1296003AC2EE /* Build configuration list for PBXNativeTarget "AirMaps" */; buildPhases = ( - 213F4612EFB9C7C068108D23 /* Check Pods Manifest.lock */, 11FA5C4D1C4A1296003AC2EE /* Sources */, 11FA5C4E1C4A1296003AC2EE /* Frameworks */, 11FA5C4F1C4A1296003AC2EE /* CopyFiles */, - 93CACE9D409FFE530662D7C9 /* Copy Pods Resources */, ); buildRules = ( ); @@ -255,39 +196,6 @@ }; /* End PBXProject section */ -/* Begin PBXShellScriptBuildPhase section */ - 213F4612EFB9C7C068108D23 /* Check Pods Manifest.lock */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - name = "Check Pods Manifest.lock"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n"; - showEnvVarsInLog = 0; - }; - 93CACE9D409FFE530662D7C9 /* Copy Pods Resources */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - name = "Copy Pods Resources"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-AirMaps/Pods-AirMaps-resources.sh\"\n"; - showEnvVarsInLog = 0; - }; -/* End PBXShellScriptBuildPhase section */ - /* Begin PBXSourcesBuildPhase section */ 11FA5C4D1C4A1296003AC2EE /* Sources */ = { isa = PBXSourcesBuildPhase; @@ -295,14 +203,10 @@ files = ( 1125B2E31C4AD3DA007D0023 /* AIRMapPolygon.m in Sources */, 1125B2E41C4AD3DA007D0023 /* AIRMapPolygonManager.m in Sources */, - 21E6572A1D78E03E00B75EE5 /* AIRGoogleMap.m in Sources */, - 21E657271D78DAE600B75EE5 /* AIRGoogleMapManager.m in Sources */, 1125B2DB1C4AD3DA007D0023 /* AIRMapCallout.m in Sources */, 1125B2E01C4AD3DA007D0023 /* AIRMapManager.m in Sources */, - 216133061D7E64D90024C623 /* AIRGMSMarker.m in Sources */, 1125B2E61C4AD3DA007D0023 /* AIRMapPolylineManager.m in Sources */, 1125B2DD1C4AD3DA007D0023 /* AIRMapCircle.m in Sources */, - 215D95711D7A27BF000DF827 /* AIRGoogleMapMarker.m in Sources */, 1125B2E51C4AD3DA007D0023 /* AIRMapPolyline.m in Sources */, DA6C263E1C9E324A0035349F /* AIRMapUrlTileManager.m in Sources */, 1125B2DA1C4AD3DA007D0023 /* AIRMap.m in Sources */, @@ -310,7 +214,6 @@ 1125B2DF1C4AD3DA007D0023 /* AIRMapCoordinate.m in Sources */, 1125B2F21C4AD445007D0023 /* SMCalloutView.m in Sources */, 1125B2E11C4AD3DA007D0023 /* AIRMapMarker.m in Sources */, - 216133031D7A2F880024C623 /* AIRGoogleMapMarkerManager.m in Sources */, 1125B2E21C4AD3DA007D0023 /* AIRMapMarkerManager.m in Sources */, DA6C26381C9E2AFE0035349F /* AIRMapUrlTile.m in Sources */, 1125B2DE1C4AD3DA007D0023 /* AIRMapCircleManager.m in Sources */, @@ -405,7 +308,6 @@ }; 11FA5C5B1C4A1296003AC2EE /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 8CCE0467700E33644F88F948 /* Pods-AirMaps.debug.xcconfig */; buildSettings = { HEADER_SEARCH_PATHS = ( "$(SRCROOT)/../../react-native/React/**", @@ -420,7 +322,6 @@ }; 11FA5C5C1C4A1296003AC2EE /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = D22E28ACFEBD663EF2744EFE /* Pods-AirMaps.release.xcconfig */; buildSettings = { HEADER_SEARCH_PATHS = ( "$(SRCROOT)/../../react-native/React/**", diff --git a/ios/AirMaps.xcworkspace/contents.xcworkspacedata b/ios/AirMaps.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index e49e5f4d1..000000000 --- a/ios/AirMaps.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - diff --git a/ios/Podfile b/ios/Podfile deleted file mode 100644 index 72cc083d7..000000000 --- a/ios/Podfile +++ /dev/null @@ -1,21 +0,0 @@ -# Uncomment this line to define a global platform for your project -platform :ios, '8.0' -# Uncomment this line if you're using Swift -# use_frameworks! - -target 'AirMaps' do - pod 'React', path: '../example/node_modules/react-native', :subspecs => [ - 'Core', - 'RCTActionSheet', - 'RCTGeolocation', - 'RCTImage', - 'RCTLinkingIOS', - 'RCTNetwork', - 'RCTSettings', - 'RCTText', - 'RCTVibration', - 'RCTWebSocket' - ] - - pod 'GoogleMaps' -end diff --git a/ios/Podfile.lock b/ios/Podfile.lock deleted file mode 100644 index cafccccf9..000000000 --- a/ios/Podfile.lock +++ /dev/null @@ -1,51 +0,0 @@ -PODS: - - GoogleMaps (2.0.1): - - GoogleMaps/Maps (= 2.0.1) - - GoogleMaps/Base (2.0.1) - - GoogleMaps/Maps (2.0.1): - - GoogleMaps/Base (= 2.0.1) - - React/Core (0.32.0): - - React/CSSLayout - - React/CSSLayout (0.32.0) - - React/RCTActionSheet (0.32.0): - - React/Core - - React/RCTGeolocation (0.32.0): - - React/Core - - React/RCTImage (0.32.0): - - React/Core - - React/RCTNetwork - - React/RCTLinkingIOS (0.32.0): - - React/Core - - React/RCTNetwork (0.32.0): - - React/Core - - React/RCTSettings (0.32.0): - - React/Core - - React/RCTText (0.32.0): - - React/Core - - React/RCTVibration (0.32.0): - - React/Core - - React/RCTWebSocket (0.32.0): - - React/Core - -DEPENDENCIES: - - GoogleMaps - - React/Core (from `../example/node_modules/react-native`) - - React/RCTActionSheet (from `../example/node_modules/react-native`) - - React/RCTGeolocation (from `../example/node_modules/react-native`) - - React/RCTImage (from `../example/node_modules/react-native`) - - React/RCTLinkingIOS (from `../example/node_modules/react-native`) - - React/RCTNetwork (from `../example/node_modules/react-native`) - - React/RCTSettings (from `../example/node_modules/react-native`) - - React/RCTText (from `../example/node_modules/react-native`) - - React/RCTVibration (from `../example/node_modules/react-native`) - - React/RCTWebSocket (from `../example/node_modules/react-native`) - -EXTERNAL SOURCES: - React: - :path: "../example/node_modules/react-native" - -SPEC CHECKSUMS: - GoogleMaps: f09da64fc987c1aa29394567c3cab5a3df83c402 - React: 0245b401173a94a5fba0f440aab3fb2f79b738f3 - -COCOAPODS: 0.39.0 From 5e417ea492161d9eb2ed4e3c087d0284eac22309 Mon Sep 17 00:00:00 2001 From: Ben Bodenmiller Date: Wed, 28 Sep 2016 02:13:16 -0700 Subject: [PATCH 0090/1148] improve installation instructions --- docs/installation.md | 250 +++++++++++++++++-------------------------- 1 file changed, 101 insertions(+), 149 deletions(-) diff --git a/docs/installation.md b/docs/installation.md index 90a349dd8..5ece3c071 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -6,16 +6,12 @@ First, download the library from npm: npm install react-native-maps --save ``` -Then you must install the native dependencies. You can use `rnpm` (now part of `react-native` core) to -add native dependencies automatically: +Then you must install the native dependencies: You can use `rnpm` (now part of `react-native` core) to +add native dependencies automatically then continue the directions below depending on your target OS. -`$ react-native link` + `$ react-native link` -Go to step 4 to configure Google Maps API KEY in Android. - ->This installation should work in physical devices. For Genymotion, please check installation step 5 - -or do it manually as described below: + >This installation should work in physical devices. For Genymotion, be sure to check Android installation about Google Play Services ## iOS @@ -23,10 +19,10 @@ or do it manually as described below: 1. Setup your `Podfile` like the included [example/ios/Podfile](../example/ios/Podfile) then run `pod install`. (If you do not need `GoogleMaps` support for iOS, then you can probably completely skip this step.) -2. Open your project in xCode workspace -3. Drag the following folder into your project: +1. Open your project in xCode workspace +1. Drag the following folder into your project: - `node_modules/react-native-maps/ios/AirMaps/` -4. If you need `GoogleMaps` support also drag this folder into your project: +1. If you need `GoogleMaps` support also drag this folder into your project: - `node_modules/react-native-maps/ios/AirGoogleMaps/` ### Option 2: Cocoapods -- Untested Way @@ -47,183 +43,139 @@ Now if you need `GoogleMaps` support you will also have to add a bunch of other After your `Podfile` is setup properly, run `pod install`. -### Option3: Manually +### Option 3: Manually 1. Open your project in XCode, right click on `Libraries` and click `Add Files to "Your Project Name"` Look under `node_modules/react-native-maps/ios` and add `AIRMaps.xcodeproj`. -2. Add `libAIRMaps.a` to `Build Phases -> Link Binary With Libraries. -3. Click on `AIRMaps.xcodeproj` in `Libraries` and go the `Build +1. Add `libAIRMaps.a` to `Build Phases -> Link Binary With Libraries. +1. Click on `AIRMaps.xcodeproj` in `Libraries` and go the `Build Settings` tab. Double click the text to the right of `Header Search Paths` and verify that it has `$(SRCROOT)/../../react-native/React` as well as `$(SRCROOT)/../../react-native/Libraries/Image` - if they aren't, then add them. This is so XCode is able to find the headers that the `AIRMaps` source files are referring to by pointing to the header files installed within the `react-native` `node_modules` directory. -4. Whenever you want to use it within React code now you can: `var MapView = +1. Whenever you want to use it within React code now you can: `var MapView = require('react-native-maps');` ## Android -1. in your `android/app/build.gradle` add: -```groovy -... -dependencies { - ... - compile project(':react-native-maps') -} -``` - -2. in your `android/settings.gradle` add: -```groovy -... -include ':react-native-maps' -project(':react-native-maps').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-maps/android') -``` - -3. in your application object, add: - -For React Native v0.29.0 or above: - -```java -import com.airbnb.android.react.maps.MapsPackage; - -public class MyApplication extends Application implements ReactApplication { - private final ReactNativeHost reactNativeHost = new ReactNativeHost(this) { - @Override protected List getPackages() { - return Arrays.asList( - new MainReactPackage(), - new MapsPackage()); - } - }; - - @Override public ReactNativeHost getReactNativeHost() { - return reactNativeHost; - } -} -``` - -For older versions of React Native: - -```java -@Override protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - mReactRootView = new ReactRootView(this); - - mReactInstanceManager = ReactInstanceManager.builder() - .setApplication(getApplication()) - .setBundleAssetName("index.android.bundle") - .setJSMainModuleName("index.android") - .addPackage(new MainReactPackage()) - .addPackage(new MapsPackage()) // <---- and This! - .setUseDeveloperSupport(BuildConfig.DEBUG) - .setInitialLifecycleState(LifecycleState.RESUMED) - .build(); - - mReactRootView.startReactApplication(mReactInstanceManager, "MyApp", null); - - setContentView(mReactRootView); -} -``` - -4. Specify your Google Maps API Key: +1. In your `android/app/build.gradle` add: + ```groovy + ... + dependencies { + ... + compile project(':react-native-maps') + } + ``` + +1. In your `android/settings.gradle` add: + ```groovy + ... + include ':react-native-maps' + project(':react-native-maps').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-maps/android') + ``` + +1. Specify your Google Maps API Key: > To develop is recommended a ***Browser Key*** without refeer restriction. Go to https://console.developers.google.com/apis/credentials to check your credentials. -Add your **Browser** API key to your manifest file: + Add your **Browser** API key to your manifest file (`android\app\src\main\AndroidManifest.xml`): -```xml - - - - -``` + ```xml + + + + + ``` > If that doesn't work try using an ***Android Key*** without refeer restriction. Go to https://console.developers.google.com/apis/credentials to check your credentials. -Add your **Android** API key to your manifest file: + Add your **Android** API key to your manifest file: -```xml - - - - -``` + ```xml + + + + + ``` -5. ensure that you have Google Play Services installed: +1. Ensure that you have Google Play Services installed: * For Genymotion you can follow [these instructions](http://stackoverflow.com/a/20137324/1424349). - * For a physical device you need to search on Google 'Google Play Services'. There will be a link that takes you to the play store and from there you will see a button to update it (do not search within the Play Store). + * For a physical device you need to search on Google for 'Google Play Services'. There will be a link that takes you to the Play Store and from there you will see a button to update it (do not search within the Play Store). -**Troubleshooting** +## Troubleshooting If you have a blank map issue, ([#118](https://github.com/airbnb/react-native-maps/issues/118), [#176](https://github.com/airbnb/react-native-maps/issues/176)) try the following lines : -**On iOS :** +### On iOS: + +You have to link dependencies with rnpm and re-run the build: - You have to link dependencies with rnpm and re-run the build : -1. `rnpm link` -2. `react-native run-ios` +1. `rnpm link` +1. `react-native run-ios` -**On Android :** +### On Android: 1. Set this Stylesheet in your map component -``` -... -const styles = StyleSheet.create({ - container: { - ...StyleSheet.absoluteFillObject, - height: 400, - width: 400, - justifyContent: 'flex-end', - alignItems: 'center', - }, - map: { - ...StyleSheet.absoluteFillObject, - }, -}); - -module.exports = class MyApp extends React.Component { - render() { - const { region } = this.props; - console.log(region); - - return ( - - - - - ); - } -} -``` -2. Run "android" and make sure every packages is updated. -3. If not installed yet, you have to install the following packages : + ``` + ... + const styles = StyleSheet.create({ + container: { + ...StyleSheet.absoluteFillObject, + height: 400, + width: 400, + justifyContent: 'flex-end', + alignItems: 'center', + }, + map: { + ...StyleSheet.absoluteFillObject, + }, + }); + + module.exports = class MyApp extends React.Component { + render() { + const { region } = this.props; + console.log(region); + + return ( + + + + + ); + } + } + ``` +1. Run "android" and make sure every packages is updated. +1. If not installed yet, you have to install the following packages : - Extras / Google Play services - Extras / Google Repository - Android 6.0 (API 23) / Google APIs Intel x86 Atom System Image Rev. 13 -4. Check manual installation steps -5. Generate your SHA1 key : +1. Check manual installation steps +1. Generate your SHA1 key : `keytool -list -v -keystore ~/.android/debug.keystore -alias androiddebugkey -storepass android -keypass android` -6. Go to [Google API Console](https://console.developers.google.com/flows/enableapi?apiid=maps_android_backend) and select your project, or create one. +1. Go to [Google API Console](https://console.developers.google.com/flows/enableapi?apiid=maps_android_backend) and select your project, or create one. In `Overview -> Google Maps API -> Google Maps Android API ` -> Check if it's enabled Create a new key by clicking on `Create credentials -> API Key -> Android Key`, enter the name of the API key and your SHA1 key, generated before, and create it. Check installation step 4. -7. Clean the cache : +1. Clean the cache : `watchman watch-del-all` `npm cache clean` -8. When starting emulator, make sure you have enabled `Wipe user data`. +1. When starting emulator, make sure you have enabled `Wipe user data`. -9. Run `react-native run-android` +1. Run `react-native run-android` -10. At this step it should work, but if not, go to your [Google API Console](https://console.developers.google.com/flows/enableapi?apiid=maps_android_backend&keyType=CLIENT_SIDE_ANDROID&pli=1) and create a `Browser key` instead of a `Android key` and go to step 6. +1. At this step it should work, but if not, go to your [Google API Console](https://console.developers.google.com/flows/enableapi?apiid=maps_android_backend&keyType=CLIENT_SIDE_ANDROID&pli=1) and create a `Browser key` instead of a `Android key` and go to step 6. From 1d9d5296a6c68a977fafd20b605512a63d488a39 Mon Sep 17 00:00:00 2001 From: IjzerenHein Date: Wed, 28 Sep 2016 23:03:28 +0200 Subject: [PATCH 0091/1148] Added support for taking snapshots on Android # Conflicts: # android/src/main/java/com/airbnb/android/react/maps/AirMapModule.java --- .../android/react/maps/AirMapModule.java | 126 ++++++++++++++++++ .../android/react/maps/MapsPackage.java | 2 +- components/MapView.js | 35 ++++- 3 files changed, 160 insertions(+), 3 deletions(-) create mode 100644 android/src/main/java/com/airbnb/android/react/maps/AirMapModule.java diff --git a/android/src/main/java/com/airbnb/android/react/maps/AirMapModule.java b/android/src/main/java/com/airbnb/android/react/maps/AirMapModule.java new file mode 100644 index 000000000..b68ef3efd --- /dev/null +++ b/android/src/main/java/com/airbnb/android/react/maps/AirMapModule.java @@ -0,0 +1,126 @@ +package com.airbnb.android.react.maps; + +import android.app.Activity; +import android.util.DisplayMetrics; +import android.util.Base64; +import android.graphics.Bitmap; +import android.net.Uri; +import android.view.View; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.OutputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; + +import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.bridge.ReactContextBaseJavaModule; +import com.facebook.react.bridge.ReadableMap; +import com.facebook.react.bridge.Promise; +import com.facebook.react.bridge.ReactMethod; +import com.facebook.react.uimanager.UIManagerModule; +import com.facebook.react.uimanager.UIBlock; +import com.facebook.react.uimanager.NativeViewHierarchyManager; + +import com.google.android.gms.maps.GoogleMap; + + +public class AirMapModule extends ReactContextBaseJavaModule { + + public AirMapModule(ReactApplicationContext reactContext) { + super(reactContext); + } + + @Override + public String getName() { + return "AirMapModule"; + } + + public Activity getActivity() { + return getCurrentActivity(); + } + + @ReactMethod + public void takeSnapshot(final int tag, final ReadableMap options, final Promise promise) { + + // Parse and verity options + final ReactApplicationContext context = getReactApplicationContext(); + final String format = options.hasKey("format") ? options.getString("format") : "png"; + final Bitmap.CompressFormat compressFormat = + format.equals("png") ? Bitmap.CompressFormat.PNG : + format.equals("jpg") ? Bitmap.CompressFormat.JPEG : null; + if (compressFormat == null) { + promise.reject("AIRMap.takeSnapshot", "Unsupported image format: " + format + ". Try one of: png | jpg | jpeg"); + return; + } + final double quality = options.hasKey("quality") ? options.getDouble("quality") : 1.0; + final DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics(); + final Integer width = options.hasKey("width") ? (int)(displayMetrics.density * options.getDouble("width")) : 0; + final Integer height = options.hasKey("height") ? (int)(displayMetrics.density * options.getDouble("height")) : 0; + final String result = options.hasKey("result") ? options.getString("result") : "file"; + + // Add UI-block so we can get a valid reference to the map-view + UIManagerModule uiManager = context.getNativeModule(UIManagerModule.class); + uiManager.addUIBlock(new UIBlock() { + public void execute (NativeViewHierarchyManager nvhm) { + AirMapView view = (AirMapView) nvhm.resolveView(tag); + if (view == null) { + promise.reject("AirMapView not found"); + return; + } + if (view.map == null) { + promise.reject("AirMapView.map is not valid"); + return; + } + view.map.snapshot(new GoogleMap.SnapshotReadyCallback() { + public void onSnapshotReady(Bitmap snapshot) { + + // Convert image to requested width/height if neccesary + if (snapshot != null && width != 0 && height != 0 && (width != snapshot.getWidth() || height != snapshot.getHeight())) { + snapshot = Bitmap.createScaledBitmap(snapshot, width, height, true); + } + if (snapshot == null) { + promise.reject("Failed to generate bitmap"); + return; + } + + // Save the snapshot to disk + OutputStream outputStream = null; + try { + if ("file".equals(result)) { + File tempFile = File.createTempFile("AirMapSnapshot", "." + format, context.getCacheDir()); + outputStream = new FileOutputStream(tempFile); + snapshot.compress(compressFormat, (int)(100.0 * quality), outputStream); + outputStream.close(); + outputStream = null; + String uri = Uri.fromFile(tempFile).toString(); + promise.resolve(uri); + } + else if ("base64".equals(result)) { + outputStream = new ByteArrayOutputStream(); + snapshot.compress(compressFormat, (int)(100.0 * quality), outputStream); + outputStream.close(); + outputStream = null; + byte[] bytes = ((ByteArrayOutputStream) outputStream).toByteArray(); + String data = Base64.encodeToString(bytes, Base64.NO_WRAP); + promise.resolve(data); + } + } + catch (Exception e) { + promise.reject(e); + } + finally { + if (outputStream != null) { + try { + outputStream.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + } + }); + } + }); + } +} diff --git a/android/src/main/java/com/airbnb/android/react/maps/MapsPackage.java b/android/src/main/java/com/airbnb/android/react/maps/MapsPackage.java index 5480c16ab..bc80cbcba 100644 --- a/android/src/main/java/com/airbnb/android/react/maps/MapsPackage.java +++ b/android/src/main/java/com/airbnb/android/react/maps/MapsPackage.java @@ -21,7 +21,7 @@ public MapsPackage() { @Override public List createNativeModules(ReactApplicationContext reactContext) { - return Collections.emptyList(); + return Arrays.asList(new AirMapModule(reactContext)); } @Override diff --git a/components/MapView.js b/components/MapView.js index 50683cd5a..7fe57fd40 100644 --- a/components/MapView.js +++ b/components/MapView.js @@ -446,8 +446,39 @@ class MapView extends React.Component { } takeSnapshot(width, height, region, callback) { - const finalRegion = region || this.props.region || this.props.initialRegion; - this._runCommand('takeSnapshot', [width, height, finalRegion, callback]); + return new Promise((resolve, reject) => { + let options; + if (typeof width === 'object') { + options = width; + } + else { + options = { + width: width, + height: height, + region: region || this.props.region || this.props.initialRegion + }; + } + if (Platform.OS === 'android') { + NativeModules.AirMapModule.takeSnapshot(this._getHandle(), options).then((snapshot) => { + if (callback) callback(undefined, {uri: snapshot}); + resolve(snapshot); + }, (err) => { + if (callback) callback(err); + reject(err); + }); + } + else { + this._runCommand('takeSnapshot', [options.width, options.height, options.region, (err, snapshot) => { + if (callback) callback(err, snapshot); + if (err) { + reject(err); + } + else { + resolve(snapshot.uri); + } + }]); + } + }); } _uiManagerCommand(name) { From 38ce6d5c37fdae7b3e4cd971624af3d61a7f3ff8 Mon Sep 17 00:00:00 2001 From: IjzerenHein Date: Wed, 28 Sep 2016 23:28:12 +0200 Subject: [PATCH 0092/1148] Fixed eslint errors in MapView.js --- components/MapView.js | 40 +++++++++++++++++++++++----------------- 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/components/MapView.js b/components/MapView.js index 7fe57fd40..b71c99a8c 100644 --- a/components/MapView.js +++ b/components/MapView.js @@ -450,33 +450,39 @@ class MapView extends React.Component { let options; if (typeof width === 'object') { options = width; - } - else { + } else { options = { - width: width, - height: height, - region: region || this.props.region || this.props.initialRegion + width, + height, + region: region || this.props.region || this.props.initialRegion, }; } if (Platform.OS === 'android') { NativeModules.AirMapModule.takeSnapshot(this._getHandle(), options).then((snapshot) => { - if (callback) callback(undefined, {uri: snapshot}); + if (callback) { + callback(undefined, { + uri: snapshot, + }); + } resolve(snapshot); }, (err) => { if (callback) callback(err); reject(err); }); - } - else { - this._runCommand('takeSnapshot', [options.width, options.height, options.region, (err, snapshot) => { - if (callback) callback(err, snapshot); - if (err) { - reject(err); - } - else { - resolve(snapshot.uri); - } - }]); + } else { + this._runCommand('takeSnapshot', [ + options.width, + options.height, + options.region, + (err, snapshot) => { + if (callback) callback(err, snapshot); + if (err) { + reject(err); + } else { + resolve(snapshot.uri); + } + }, + ]); } }); } From 65e331c2b129e6a25c948f9dfa5414233fbc1d20 Mon Sep 17 00:00:00 2001 From: gilbox Date: Wed, 28 Sep 2016 17:10:52 -0700 Subject: [PATCH 0093/1148] Fix podspec github url --- react-native-google-maps.podspec | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/react-native-google-maps.podspec b/react-native-google-maps.podspec index 9cf323e6e..9b9116648 100644 --- a/react-native-google-maps.podspec +++ b/react-native-google-maps.podspec @@ -4,11 +4,11 @@ Pod::Spec.new do |s| s.summary = "React Native Mapview component for iOS + Android" s.authors = { "intelligibabble" => "leland.m.richardson@gmail.com" } - s.homepage = "https://github.com/lelandrichardson/react-native-maps#readme" + s.homepage = "https://github.com/airbnb/react-native-maps#readme" s.license = "MIT" s.platform = :ios, "8.0" - s.source = { :git => "https://github.com/lelandrichardson/react-native-maps.git" } + s.source = { :git => "https://github.com/airbnb/react-native-maps.git" } s.source_files = "ios/AirMaps/**/*.{h,m}" s.dependency 'React' From 6126c6d0794983734b6af52f8936a54f16adfe5d Mon Sep 17 00:00:00 2001 From: Spike Brehm Date: Wed, 28 Sep 2016 17:44:37 -0700 Subject: [PATCH 0094/1148] Remove unused tileMap variable from AirMapView --- .../java/com/airbnb/android/react/maps/AirMapView.java | 8 -------- 1 file changed, 8 deletions(-) diff --git a/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java b/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java index 6f44294f4..4a04af88a 100644 --- a/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java +++ b/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java @@ -70,8 +70,6 @@ public class AirMapView extends MapView implements GoogleMap.InfoWindowAdapter, private static final String[] PERMISSIONS = new String[] { "android.permission.ACCESS_FINE_LOCATION", "android.permission.ACCESS_COARSE_LOCATION"}; - // TODO: don't need tileMap at all??? - private HashMap tileMap = new HashMap<>(); private final List features = new ArrayList<>(); private final Map markerMap = new HashMap<>(); private final ScaleGestureDetector scaleDetector; @@ -402,9 +400,6 @@ public void addFeature(View child, int index) { AirMapUrlTile urlTileView = (AirMapUrlTile) child; urlTileView.addToMap(map); features.add(index, urlTileView); - TileOverlay tile = (TileOverlay)urlTileView.getFeature(); - // TODO: don't need tileMap at all??? - tileMap.put(tile, urlTileView); } else { // TODO(lmr): throw? User shouldn't be adding non-feature children. } @@ -422,9 +417,6 @@ public void removeFeatureAt(int index) { AirMapFeature feature = features.remove(index); if (feature instanceof AirMapMarker) { markerMap.remove(feature.getFeature()); - } else if (feature instanceof AirMapUrlTile) { - // TODO: don't need tileMap at all??? - tileMap.remove(feature.getFeature()); } feature.removeFromMap(map); } From a08336e867e2a5157a7b1c66b253e46178bc791e Mon Sep 17 00:00:00 2001 From: Spike Brehm Date: Wed, 28 Sep 2016 16:40:45 -0700 Subject: [PATCH 0095/1148] Version 0.9.0-rc.0 --- android/gradle.properties | 2 +- package.json | 2 +- react-native-google-maps.podspec | 2 +- react-native-maps.podspec | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/android/gradle.properties b/android/gradle.properties index 33a00d044..3e0156412 100644 --- a/android/gradle.properties +++ b/android/gradle.properties @@ -1,5 +1,5 @@ VERSION_CODE=2 -VERSION_NAME=0.8.2 +VERSION_NAME=0.9.0-rc.0 GROUP=com.airbnb.android POM_DESCRIPTION=React Native Map view component for Android diff --git a/package.json b/package.json index df61e0a0b..df55868e3 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "description": "React Native Mapview component for iOS + Android", "main": "index.js", "author": "Leland Richardson ", - "version": "0.8.2", + "version": "0.9.0-rc.0", "scripts": { "start": "react-native start", "lint": "eslint ." diff --git a/react-native-google-maps.podspec b/react-native-google-maps.podspec index 9b9116648..7062cd7e6 100644 --- a/react-native-google-maps.podspec +++ b/react-native-google-maps.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "react-native-google-maps" - s.version = "0.8.2" + s.version = "0.9.0-rc.0" s.summary = "React Native Mapview component for iOS + Android" s.authors = { "intelligibabble" => "leland.m.richardson@gmail.com" } diff --git a/react-native-maps.podspec b/react-native-maps.podspec index ddbf4f4f4..2b543a6e9 100644 --- a/react-native-maps.podspec +++ b/react-native-maps.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "react-native-maps" - s.version = "0.8.2" + s.version = "0.9.0-rc.0" s.summary = "React Native Mapview component for iOS + Android" s.authors = { "intelligibabble" => "leland.m.richardson@gmail.com" } From be2e6b32b3e4cb87b124a9d78de402fe6b725f34 Mon Sep 17 00:00:00 2001 From: Spike Brehm Date: Wed, 28 Sep 2016 17:33:32 -0700 Subject: [PATCH 0096/1148] Update CHANGELOG.md for 0.9.0 --- CHANGELOG.md | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 64 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 24555b136..86a78e750 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,68 @@ # Change Log +## 0.9.0 (September 28, 2016) + +As of this release, this repository has moved from +`lelandrichardson/react-native-maps` to `airbnb/react-native-maps`. + +### Breaking Changes + +* [iOS] Support Google Maps on iOS + [#548](https://github.com/airbnb/react-native-maps/pull/548) + (@gilbox) + +### Patches + +* Added support for AnimatedRegion without modifying the AnimatedImplementation.js of react-native + [#608](https://github.com/airbnb/react-native-maps/pull/608) + (@IjzerenHein) +* [iOS] Remove pod stuff. Fix AirMaps.xcodeproj related to missing pod stuff + [#620](https://github.com/airbnb/react-native-maps/pull/620) + (@gilbox) +* [iOS] Fix import of AIRMapSnapshot + [#622](https://github.com/airbnb/react-native-maps/pull/622) + (@spikebrehm) +* [iOS] Fix nullability issue + [#614](https://github.com/airbnb/react-native-maps/pull/614) + (@simonmitchell) +* [iOS] Added support for drawing polylines on snapshots on iOS + [#615](https://github.com/airbnb/react-native-maps/pull/615) + (@IjzerenHein) +* Add `fitToCoordinates` method + [#545](https://github.com/airbnb/react-native-maps/pull/545) + (@naoufal) +* [Android] Fix list of examples on Android + [#597](https://github.com/airbnb/react-native-maps/pull/597) + (@spikebrehm) +* [Android] Fix overlapping map issue + [#589](https://github.com/airbnb/react-native-maps/pull/589) + (@fdnhkj) +* Add tile overlay support + [#595](https://github.com/airbnb/react-native-maps/pull/595) + (@cascadian, @spikebrehm) +* [Android] Support Android LiteMode + [#546](https://github.com/airbnb/react-native-maps/pull/546) + (@rops) +* s/lelandrichardson/airbnb/ + [#573](https://github.com/airbnb/react-native-maps/pull/573) + (@spikebrehm) +* [Android] Don't fit to elements if no positions added + [#567](https://github.com/airbnb/react-native-maps/pull/567) + (@ryankask) +* [iOS] Add class prefix to EmptyCalloutBackgroundView + [#563](https://github.com/airbnb/react-native-maps/pull/563) + (@terribleben) +* [Android] Minor code cleanup + [#564](https://github.com/airbnb/react-native-maps/pull/564) + (@felipecsl) +* Documentation updates + [#566](https://github.com/airbnb/react-native-maps/pull/566), + [#591](https://github.com/airbnb/react-native-maps/pull/591), + [#601](https://github.com/airbnb/react-native-maps/pull/601), + [#602](https://github.com/airbnb/react-native-maps/pull/602), + [#624](https://github.com/airbnb/react-native-maps/pull/624) + (@felipecsl, @Alastairm, @Keksike, @bbodenmiller) + ## 0.8.2 (September 8, 2016) We realized immediately after publishing 0.8.1 that the NPM package contained @@ -19,7 +82,7 @@ This error is caused by a @providesModule declaration with the same name accross ## 0.8.1 (September 8, 2016) *[DEPRECATED]* -#### *NOTE: 0.8.1 has been unpublished from NPM beacuse it was faulty. Please use 0.8.2.* +#### *NOTE: 0.8.1 has been unpublished from NPM because it was faulty. Please use 0.8.2.* ### Patches From bd32db971f60a68fbd041b91cdaa2ea2b0008857 Mon Sep 17 00:00:00 2001 From: Gil Birman Date: Fri, 30 Sep 2016 16:34:10 -0700 Subject: [PATCH 0097/1148] [google] Use same region format as iOS (#631) --- ios/AirGoogleMaps/AIRGoogleMap.m | 38 ++++++++++++++++++++++++++------ 1 file changed, 31 insertions(+), 7 deletions(-) diff --git a/ios/AirGoogleMaps/AIRGoogleMap.m b/ios/AirGoogleMaps/AIRGoogleMap.m index d38188d56..daa2189bc 100644 --- a/ios/AirGoogleMaps/AIRGoogleMap.m +++ b/ios/AirGoogleMaps/AIRGoogleMap.m @@ -12,15 +12,38 @@ #import "RCTConvert+MapKit.h" #import "UIView+React.h" -id cameraPositionAsJSON(GMSCameraPosition *position) { - // todo: convert zoom to delta lat/lng +id regionAsJSON(MKCoordinateRegion region) { return @{ - @"latitude": [NSNumber numberWithDouble:position.target.latitude], - @"longitude": [NSNumber numberWithDouble:position.target.longitude], - @"zoom": [NSNumber numberWithDouble:position.zoom], + @"latitude": [NSNumber numberWithDouble:region.center.latitude], + @"longitude": [NSNumber numberWithDouble:region.center.longitude], + @"latitudeDelta": [NSNumber numberWithDouble:region.span.latitudeDelta], + @"longitudeDelta": [NSNumber numberWithDouble:region.span.longitudeDelta], }; } +MKCoordinateRegion makeMKCoordinateRegionFromGMSCameraPositionOfMap(GMSMapView *map, GMSCameraPosition *position) { + // solution from here: http://stackoverflow.com/a/16587735/1102215 + GMSVisibleRegion visibleRegion = map.projection.visibleRegion; + GMSCoordinateBounds *bounds = [[GMSCoordinateBounds alloc] initWithRegion: visibleRegion]; + CLLocationCoordinate2D center; + CLLocationDegrees longitudeDelta; + CLLocationDegrees latitudeDelta = bounds.northEast.latitude - bounds.southWest.latitude; + + if(bounds.northEast.longitude >= bounds.southWest.longitude) { + //Standard case + center = CLLocationCoordinate2DMake((bounds.southWest.latitude + bounds.northEast.latitude) / 2, + (bounds.southWest.longitude + bounds.northEast.longitude) / 2); + longitudeDelta = bounds.northEast.longitude - bounds.southWest.longitude; + } else { + //Region spans the international dateline + center = CLLocationCoordinate2DMake((bounds.southWest.latitude + bounds.northEast.latitude) / 2, + (bounds.southWest.longitude + bounds.northEast.longitude + 360) / 2); + longitudeDelta = bounds.northEast.longitude + 360 - bounds.southWest.longitude; + } + MKCoordinateSpan span = MKCoordinateSpanMake(latitudeDelta, longitudeDelta); + return MKCoordinateRegionMake(center, span); +} + GMSCameraPosition* makeGMSCameraPositionFromMKCoordinateRegionOfMap(GMSMapView *map, MKCoordinateRegion region) { float latitudeDelta = region.span.latitudeDelta * 0.5; float longitudeDelta = region.span.longitudeDelta * 0.5; @@ -137,14 +160,15 @@ - (void)didLongPressAtCoordinate:(CLLocationCoordinate2D)coordinate { - (void)didChangeCameraPosition:(GMSCameraPosition *)position { id event = @{@"continuous": @YES, - @"region": cameraPositionAsJSON(position), + @"region": regionAsJSON(makeMKCoordinateRegionFromGMSCameraPositionOfMap(self, position)), }; + if (self.onChange) self.onChange(event); } - (void)idleAtCameraPosition:(GMSCameraPosition *)position { id event = @{@"continuous": @NO, - @"region": cameraPositionAsJSON(position), + @"region": regionAsJSON(makeMKCoordinateRegionFromGMSCameraPositionOfMap(self, position)), }; if (self.onChange) self.onChange(event); // complete } From 7f5e05f503b34b2828d532539c700159f5c64c4e Mon Sep 17 00:00:00 2001 From: Gil Birman Date: Fri, 30 Sep 2016 16:59:41 -0700 Subject: [PATCH 0098/1148] [google][ios] fix markers never going away for provider="google" (#632) --- example/examples/DefaultMarkers.js | 8 ++++++-- ios/AirGoogleMaps/AIRGoogleMap.m | 7 +++++++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/example/examples/DefaultMarkers.js b/example/examples/DefaultMarkers.js index 628384561..67768d07b 100644 --- a/example/examples/DefaultMarkers.js +++ b/example/examples/DefaultMarkers.js @@ -4,6 +4,7 @@ import { View, Text, Dimensions, + TouchableOpacity, } from 'react-native'; import MapView from 'react-native-maps'; @@ -67,9 +68,12 @@ class DefaultMarkers extends React.Component { ))} - + this.setState({ markers: [] })} + style={styles.bubble} + > Tap to create a marker of random color - +
); diff --git a/ios/AirGoogleMaps/AIRGoogleMap.m b/ios/AirGoogleMaps/AIRGoogleMap.m index daa2189bc..3b4a00c50 100644 --- a/ios/AirGoogleMaps/AIRGoogleMap.m +++ b/ios/AirGoogleMaps/AIRGoogleMap.m @@ -122,6 +122,13 @@ - (void)removeReactSubview:(id)subview { } #pragma clang diagnostic pop +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wobjc-missing-super-calls" +- (NSArray> *)reactSubviews { + return _reactSubviews; +} +#pragma clang diagnostic pop + - (void)setInitialRegion:(MKCoordinateRegion)initialRegion { if (_initialRegionSet) return; _initialRegionSet = true; From 3334e167e7990ac987dc717b904c8e227beb1c52 Mon Sep 17 00:00:00 2001 From: IjzerenHein Date: Sat, 1 Oct 2016 17:32:28 +0200 Subject: [PATCH 0099/1148] Added Const definition for snapshot result & format on Android --- .../android/react/maps/AirMapModule.java | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/android/src/main/java/com/airbnb/android/react/maps/AirMapModule.java b/android/src/main/java/com/airbnb/android/react/maps/AirMapModule.java index b68ef3efd..08566d997 100644 --- a/android/src/main/java/com/airbnb/android/react/maps/AirMapModule.java +++ b/android/src/main/java/com/airbnb/android/react/maps/AirMapModule.java @@ -24,9 +24,13 @@ import com.google.android.gms.maps.GoogleMap; - public class AirMapModule extends ReactContextBaseJavaModule { + private static final String SNAPSHOT_RESULT_FILE = "file"; + private static final String SNAPSHOT_RESULT_BASE64 = "base64"; + private static final String SNAPSHOT_FORMAT_PNG = "png"; + private static final String SNAPSHOT_FORMAT_JPG = "jpg"; + public AirMapModule(ReactApplicationContext reactContext) { super(reactContext); } @@ -47,12 +51,8 @@ public void takeSnapshot(final int tag, final ReadableMap options, final Promise final ReactApplicationContext context = getReactApplicationContext(); final String format = options.hasKey("format") ? options.getString("format") : "png"; final Bitmap.CompressFormat compressFormat = - format.equals("png") ? Bitmap.CompressFormat.PNG : - format.equals("jpg") ? Bitmap.CompressFormat.JPEG : null; - if (compressFormat == null) { - promise.reject("AIRMap.takeSnapshot", "Unsupported image format: " + format + ". Try one of: png | jpg | jpeg"); - return; - } + format.equals(SNAPSHOT_FORMAT_PNG) ? Bitmap.CompressFormat.PNG : + format.equals(SNAPSHOT_FORMAT_JPG) ? Bitmap.CompressFormat.JPEG : null; final double quality = options.hasKey("quality") ? options.getDouble("quality") : 1.0; final DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics(); final Integer width = options.hasKey("width") ? (int)(displayMetrics.density * options.getDouble("width")) : 0; @@ -87,7 +87,7 @@ public void onSnapshotReady(Bitmap snapshot) { // Save the snapshot to disk OutputStream outputStream = null; try { - if ("file".equals(result)) { + if (result.equals(SNAPSHOT_RESULT_FILE)) { File tempFile = File.createTempFile("AirMapSnapshot", "." + format, context.getCacheDir()); outputStream = new FileOutputStream(tempFile); snapshot.compress(compressFormat, (int)(100.0 * quality), outputStream); @@ -96,7 +96,7 @@ public void onSnapshotReady(Bitmap snapshot) { String uri = Uri.fromFile(tempFile).toString(); promise.resolve(uri); } - else if ("base64".equals(result)) { + else if (result.equals(SNAPSHOT_RESULT_BASE64)) { outputStream = new ByteArrayOutputStream(); snapshot.compress(compressFormat, (int)(100.0 * quality), outputStream); outputStream.close(); From 8da7db7ce6abc399fa7efd38b4c0867a2ef609e7 Mon Sep 17 00:00:00 2001 From: IjzerenHein Date: Sat, 1 Oct 2016 17:33:37 +0200 Subject: [PATCH 0100/1148] Implemented new takeSnapshot API for iOS # Conflicts: # components/MapView.js # ios/AirMaps/AIRMapManager.m --- components/MapView.js | 97 +++++++++++++++++++++++++------------ ios/AirMaps/AIRMapManager.m | 76 +++++++++++++++++++++-------- 2 files changed, 122 insertions(+), 51 deletions(-) diff --git a/components/MapView.js b/components/MapView.js index b71c99a8c..ce82b7390 100644 --- a/components/MapView.js +++ b/components/MapView.js @@ -445,46 +445,79 @@ class MapView extends React.Component { this._runCommand('fitToCoordinates', [coordinates, edgePadding, animated]); } - takeSnapshot(width, height, region, callback) { - return new Promise((resolve, reject) => { - let options; - if (typeof width === 'object') { - options = width; - } else { - options = { - width, - height, - region: region || this.props.region || this.props.initialRegion, - }; - } - if (Platform.OS === 'android') { - NativeModules.AirMapModule.takeSnapshot(this._getHandle(), options).then((snapshot) => { - if (callback) { - callback(undefined, { - uri: snapshot, - }); - } - resolve(snapshot); - }, (err) => { - if (callback) callback(err); - reject(err); - }); - } else { + /** + * Takes a snapshot of the map and saves it to a picture + * file or returns the image as a base64 encoded string. + * + * @param config Configuration options + * @param [config.width] Width of the rendered map-view (when omitted actual view width is used). + * @param [config.height] Height of the rendered map-view (when omitted actual height is used). + * @param [config.region] Region to render (Only supported on iOS). + * @param [config.format] Encoding format ('png', 'jpg') (default: 'png'). + * @param [config.quality] Compression quality (only used for jpg) (default: 1.0). + * @param [config.result] Result format ('file', 'base64') (default: 'file'). + * + * @return Promise Promise with either the file-uri or base64 encoded string + */ + takeSnapshot(args) { + // For the time being we support the legacy API on iOS. + // This will be removed in a future release and only the + // new Promise style API shall be supported. + if (Platform.OS === 'ios' && (arguments.length === 4)) { + console.warn('Old takeSnapshot API has been deprecated; will be removed in the near future'); //eslint-disable-line + const width = arguments[0]; // eslint-disable-line + const height = arguments[1]; // eslint-disable-line + const region = arguments[2]; // eslint-disable-line + const callback = arguments[3]; // eslint-disable-line + this._runCommand('takeSnapshot', [ + width || 0, + height || 0, + region || {}, + 'png', + 1, + 'legacy', + callback, + ]); + return undefined; + } + + // Sanitize inputs + const config = { + width: args.width || 0, + height: args.height || 0, + region: args.region || {}, + format: args.format || 'png', + quality: args.quality || 1.0, + result: args.result || 'file', + }; + if ((config.format !== 'png') && + (config.format !== 'jpg')) throw new Error('Invalid format specified'); + if ((config.result !== 'file') && + (config.result !== 'base64')) throw new Error('Invalid result specified'); + + // Call native function + if (Platform.OS === 'android') { + return NativeModules.AirMapModule.takeSnapshot(this._getHandle(), config); + } else if (Platform.OS === 'ios') { + return new Promise((resolve, reject) => { this._runCommand('takeSnapshot', [ - options.width, - options.height, - options.region, + config.width, + config.height, + config.region, + config.format, + config.quality, + config.result, (err, snapshot) => { - if (callback) callback(err, snapshot); if (err) { reject(err); } else { - resolve(snapshot.uri); + resolve(snapshot); } }, ]); - } - }); + }); + } + return Promise.reject('takeSnapshot not supported on this platform'); } _uiManagerCommand(name) { diff --git a/ios/AirMaps/AIRMapManager.m b/ios/AirMaps/AIRMapManager.m index c45711c3f..58cd31574 100644 --- a/ios/AirMaps/AIRMapManager.m +++ b/ios/AirMaps/AIRMapManager.m @@ -221,10 +221,13 @@ - (UIView *)view } RCT_EXPORT_METHOD(takeSnapshot:(nonnull NSNumber *)reactTag - withWidth:(nonnull NSNumber *)width - withHeight:(nonnull NSNumber *)height - withRegion:(MKCoordinateRegion)region - withCallback:(RCTResponseSenderBlock)callback) + width:(nonnull NSNumber *)width + height:(nonnull NSNumber *)height + region:(MKCoordinateRegion)region + format:(nonnull NSString *)format + quality:(nonnull NSNumber *)quality + result:(nonnull NSString *)result + callback:(RCTResponseSenderBlock)callback) { [self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary *viewRegistry) { id view = viewRegistry[reactTag]; @@ -234,25 +237,34 @@ - (UIView *)view AIRMap *mapView = (AIRMap *)view; MKMapSnapshotOptions *options = [[MKMapSnapshotOptions alloc] init]; - options.region = region; - options.size = CGSizeMake([width floatValue], [height floatValue]); + options.region = (region.center.latitude && region.center.longitude) ? region : mapView.region; + options.size = CGSizeMake( + ([width floatValue] == 0) ? mapView.bounds.size.width : [width floatValue], + ([height floatValue] == 0) ? mapView.bounds.size.height : [height floatValue] + ); options.scale = [[UIScreen mainScreen] scale]; MKMapSnapshotter *snapshotter = [[MKMapSnapshotter alloc] initWithOptions:options]; - - [self takeMapSnapshot:mapView withSnapshotter:snapshotter withCallback:callback]; - + [self takeMapSnapshot:mapView + snapshotter:snapshotter + format:format + quality:quality.floatValue + result:result + callback:callback]; } }]; } #pragma mark Take Snapshot - (void)takeMapSnapshot:(AIRMap *)mapView - withSnapshotter:(MKMapSnapshotter *) snapshotter - withCallback:(RCTResponseSenderBlock) callback { + snapshotter:(MKMapSnapshotter *) snapshotter + format:(NSString *)format + quality:(CGFloat) quality + result:(NSString *)result + callback:(RCTResponseSenderBlock) callback { NSTimeInterval timeStamp = [[NSDate date] timeIntervalSince1970]; - NSString *pathComponent = [NSString stringWithFormat:@"Documents/snapshot-%.20lf.png", timeStamp]; + NSString *pathComponent = [NSString stringWithFormat:@"Documents/snapshot-%.20lf.%@", timeStamp, format]; NSString *filePath = [NSHomeDirectory() stringByAppendingPathComponent: pathComponent]; [snapshotter startWithQueue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0) @@ -294,13 +306,39 @@ - (void)takeMapSnapshot:(AIRMap *)mapView UIImage *compositeImage = UIGraphicsGetImageFromCurrentImageContext(); - NSData *data = UIImagePNGRepresentation(compositeImage); - [data writeToFile:filePath atomically:YES]; - NSDictionary *snapshotData = @{ - @"uri": filePath, - @"data": [data base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithCarriageReturn] - }; - callback(@[[NSNull null], snapshotData]); + NSData *data; + if ([format isEqualToString:@"png"]) { + data = UIImagePNGRepresentation(compositeImage); + } + else if([format isEqualToString:@"jpg"]) { + data = UIImageJPEGRepresentation(compositeImage, quality); + } + + if ([result isEqualToString:@"file"]) { + [data writeToFile:filePath atomically:YES]; + callback(@[[NSNull null], filePath]); + } + else if ([result isEqualToString:@"base64"]) { + callback(@[[NSNull null], [data base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithCarriageReturn]]); + } + else if ([result isEqualToString:@"legacy"]) { + + // In the initial (iOS only) implementation of takeSnapshot, + // both the uri and the base64 encoded string were returned. + // Returning both is rarely useful and in fact causes a + // performance penalty when only the file URI is desired. + // In that case the base64 encoded string was always marshalled + // over the JS-bridge (which is quite slow). + // A new more flexible API was created to cover this. + // This code should be removed in a future release when the + // old API is fully deprecated. + [data writeToFile:filePath atomically:YES]; + NSDictionary *snapshotData = @{ + @"uri": filePath, + @"data": [data base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithCarriageReturn] + }; + callback(@[[NSNull null], snapshotData]); + } } UIGraphicsEndImageContext(); }]; From fe61cd179cee2958f64ba48bbebf418142c0ad9e Mon Sep 17 00:00:00 2001 From: IjzerenHein Date: Sat, 1 Oct 2016 17:34:03 +0200 Subject: [PATCH 0101/1148] Updated README with new Snapshot API --- README.md | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index db9a4dffa..57994b7e8 100644 --- a/README.md +++ b/README.md @@ -328,7 +328,6 @@ render() { ``` ### Take Snapshot of map -currently only for ios, android implementation WIP ```jsx getInitialState() { @@ -341,11 +340,19 @@ getInitialState() { } takeSnapshot () { - // arguments to 'takeSnapshot' are width, height, coordinates and callback - this.refs.map.takeSnapshot(300, 300, this.state.coordinate, (err, snapshot) => { - // snapshot contains image 'uri' - full path to image and 'data' - base64 encoded image - this.setState({ mapSnapshot: snapshot }) - }) + // 'takeSnapshot' takes a config object with the + // following options + const snapshot = this.refs.map.takeSnapshot({ + width: 300, // optional, when omitted the view-width is used + height: 300, // optional, when omitted the view-height is used + region: {..}, // iOS only, optional region to render + format: 'png', // image formats: 'png', 'jpg' (default: 'png') + quality: 0.8, // image quality: 0..1 (only relevant for jpg, default: 1) + result: 'file' // result types: 'file', 'base64' (default: 'file') + }); + snapshot.then((uri) => { + this.setState({ mapSnapshot: uri }); + }); } render() { From 1543968842f036876463c60a3ba1fed8cf4271bd Mon Sep 17 00:00:00 2001 From: Daniele Rossetti Date: Mon, 3 Oct 2016 19:27:06 +0100 Subject: [PATCH 0102/1148] Adding support for iOS < 10 --- ios/AirMaps/Callout/SMCalloutView.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ios/AirMaps/Callout/SMCalloutView.h b/ios/AirMaps/Callout/SMCalloutView.h index a1e911469..f0a41a49c 100644 --- a/ios/AirMaps/Callout/SMCalloutView.h +++ b/ios/AirMaps/Callout/SMCalloutView.h @@ -40,7 +40,11 @@ extern NSTimeInterval const kSMCalloutViewRepositionDelayForUIScrollView; // Callout view. // +#if __IPHONE_OS_VERSION_MAX_ALLOWED < 100000 +@interface SMCalloutView : UIView +#else @interface SMCalloutView : UIView +#endif @property (nonatomic, weak, nullable) id delegate; /// title/titleView relationship mimics UINavigationBar. From 31b3c5754181600c58d2f96130f97c670eb89a1f Mon Sep 17 00:00:00 2001 From: Sam Mueller Date: Tue, 4 Oct 2016 21:07:05 -0700 Subject: [PATCH 0103/1148] change loadImageWithURLRequest for RN (#613) --- ios/AirMaps/AIRMapMarker.m | 1 + 1 file changed, 1 insertion(+) diff --git a/ios/AirMaps/AIRMapMarker.m b/ios/AirMaps/AIRMapMarker.m index 79343cff0..4c3c0f6cc 100644 --- a/ios/AirMaps/AIRMapMarker.m +++ b/ios/AirMaps/AIRMapMarker.m @@ -215,6 +215,7 @@ - (void)setImageSrc:(NSString *)imageSrc clipped:YES resizeMode:RCTResizeModeCenter progressBlock:nil + partialLoadBlock:nil completionBlock:^(NSError *error, UIImage *image) { if (error) { // TODO(lmr): do something with the error? From f226d901b9d4ff3c6b69c3bb72701a68501b0ec5 Mon Sep 17 00:00:00 2001 From: alaoui abdellah Date: Wed, 5 Oct 2016 05:09:38 +0100 Subject: [PATCH 0104/1148] Add clarification on initialRegion behaviour (#628) * Add clarification on initialRegion behaviour Use case: specifying an `initialRegion` when `fitToSuppliedMarkers` is used in `ComponentDidMount` * Add recommendation on using `fitToSuppliedMarkers` Using `fitToSuppliedMarkers` in `ComponentDidMount` blocks the UI in Android before the map renders, nothing perceived in IOS simulator. This is to be expected since > Sometimes components will do additional work on componentDidMount, which might result in a second stutter in the transition. As stated in [rn docs](https://facebook.github.io/react-native/docs/performance.html#javascript-frame-rate) --- docs/mapview.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/mapview.md b/docs/mapview.md index 657b7edc8..c3e5e0bea 100644 --- a/docs/mapview.md +++ b/docs/mapview.md @@ -56,7 +56,7 @@ | `animateToRegion` | `region: Region`, `duration: Number` | | `animateToCoordinate` | `region: Coordinate`, `duration: Number` | | `fitToElements` | `animated: Boolean` | -| `fitToSuppliedMarkers` | `markerIDs: String[]` | +| `fitToSuppliedMarkers` | `markerIDs: String[]` | If you need to use this in `ComponentDidMount`, make sure you put it in a timeout or it will cause performance problems. | `fitToCoordinates` | `coordinates: Array, edgePadding: EdgePadding, animated: Boolean` | From d556597de5f38696002a6a42204283140765bfe6 Mon Sep 17 00:00:00 2001 From: Gil Birman Date: Wed, 5 Oct 2016 12:55:44 -0700 Subject: [PATCH 0105/1148] [google] refactor AIRGoogleMapMarker to use DummyView (#649) - DummyView is used to create virtual tree - Add CustomMarkers example - Prevent annoying errors from showing up with OS_ACTIVITY_MODE disable, see here https://github.com/facebook/react-native/issues/9921#issuecomment-250078139 --- example/App.js | 2 + example/examples/CustomMarkers.js | 118 ++++++++++++++++++ .../AirMapsExplorer.xcodeproj/project.pbxproj | 6 + .../xcschemes/AirMapsExplorer.xcscheme | 7 ++ example/ios/Podfile.lock | 12 +- ios/AirGoogleMaps/AIRGoogleMapMarker.m | 66 ++++++---- ios/AirGoogleMaps/DummyView.h | 14 +++ ios/AirGoogleMaps/DummyView.m | 19 +++ 8 files changed, 217 insertions(+), 27 deletions(-) create mode 100644 example/examples/CustomMarkers.js create mode 100644 ios/AirGoogleMaps/DummyView.h create mode 100644 ios/AirGoogleMaps/DummyView.m diff --git a/example/App.js b/example/App.js index 7fa21bce1..625f67edb 100644 --- a/example/App.js +++ b/example/App.js @@ -21,6 +21,7 @@ import AnimatedMarkers from './examples/AnimatedMarkers'; import Callouts from './examples/Callouts'; import Overlays from './examples/Overlays'; import DefaultMarkers from './examples/DefaultMarkers'; +import CustomMarkers from './examples/CustomMarkers'; import CachedMap from './examples/CachedMap'; import LoadingMap from './examples/LoadingMap'; import TakeSnapshot from './examples/TakeSnapshot'; @@ -129,6 +130,7 @@ class App extends React.Component { [Callouts, 'Custom Callouts', true], [Overlays, 'Circles, Polygons, and Polylines', true, '(ios error)'], [DefaultMarkers, 'Default Markers', true], + [CustomMarkers, 'Custom Markers', true], [TakeSnapshot, 'Take Snapshot', true, '(incomplete)'], [CachedMap, 'Cached Map'], [LoadingMap, 'Map with loading'], diff --git a/example/examples/CustomMarkers.js b/example/examples/CustomMarkers.js new file mode 100644 index 000000000..5c5330263 --- /dev/null +++ b/example/examples/CustomMarkers.js @@ -0,0 +1,118 @@ +import React from 'react'; +import { + StyleSheet, + View, + Text, + Dimensions, + TouchableOpacity, +} from 'react-native'; + +import MapView from 'react-native-maps'; +import flagPinkImg from './assets/flag-pink.png'; + +const { width, height } = Dimensions.get('window'); + +const ASPECT_RATIO = width / height; +const LATITUDE = 37.78825; +const LONGITUDE = -122.4324; +const LATITUDE_DELTA = 0.0922; +const LONGITUDE_DELTA = LATITUDE_DELTA * ASPECT_RATIO; +let id = 0; + +class CustomMarkers extends React.Component { + constructor(props) { + super(props); + + this.state = { + region: { + latitude: LATITUDE, + longitude: LONGITUDE, + latitudeDelta: LATITUDE_DELTA, + longitudeDelta: LONGITUDE_DELTA, + }, + markers: [], + }; + + this.onMapPress = this.onMapPress.bind(this); + } + + onMapPress(e) { + this.setState({ + markers: [ + ...this.state.markers, + { + coordinate: e.nativeEvent.coordinate, + key: `foo${id++}`, + }, + ], + }); + } + + render() { + return ( + + + {this.state.markers.map(marker => ( + + ))} + + + this.setState({ markers: [] })} + style={styles.bubble} + > + Tap to create a marker of random color + + + + ); + } +} + +CustomMarkers.propTypes = { + provider: MapView.ProviderPropType, +}; + +const styles = StyleSheet.create({ + container: { + ...StyleSheet.absoluteFillObject, + justifyContent: 'flex-end', + alignItems: 'center', + }, + map: { + ...StyleSheet.absoluteFillObject, + }, + bubble: { + backgroundColor: 'rgba(255,255,255,0.7)', + paddingHorizontal: 18, + paddingVertical: 12, + borderRadius: 20, + }, + latlng: { + width: 200, + alignItems: 'stretch', + }, + button: { + width: 80, + paddingHorizontal: 12, + alignItems: 'center', + marginHorizontal: 10, + }, + buttonContainer: { + flexDirection: 'row', + marginVertical: 20, + backgroundColor: 'transparent', + }, +}); + +module.exports = CustomMarkers; diff --git a/example/ios/AirMapsExplorer.xcodeproj/project.pbxproj b/example/ios/AirMapsExplorer.xcodeproj/project.pbxproj index 2ed33f2e3..365d67b6e 100644 --- a/example/ios/AirMapsExplorer.xcodeproj/project.pbxproj +++ b/example/ios/AirMapsExplorer.xcodeproj/project.pbxproj @@ -33,6 +33,7 @@ 2166AB351D82EC56007538D7 /* AIRMapPolylineManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 2166AB141D82EC56007538D7 /* AIRMapPolylineManager.m */; }; 2166AB361D82EC56007538D7 /* SMCalloutView.m in Sources */ = {isa = PBXBuildFile; fileRef = 2166AB171D82EC56007538D7 /* SMCalloutView.m */; }; 2166AB3E1D82EC56007538D7 /* RCTConvert+MoreMapKit.m in Sources */ = {isa = PBXBuildFile; fileRef = 2166AB281D82EC56007538D7 /* RCTConvert+MoreMapKit.m */; }; + 21B248671DA4483D008FCB52 /* DummyView.m in Sources */ = {isa = PBXBuildFile; fileRef = 21B248661DA4483D008FCB52 /* DummyView.m */; }; 21D346651D933B8C002BAD8A /* AIRMapUrlTile.m in Sources */ = {isa = PBXBuildFile; fileRef = 21D346621D933B8C002BAD8A /* AIRMapUrlTile.m */; }; 21D346661D933B8C002BAD8A /* AIRMapUrlTileManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 21D346641D933B8C002BAD8A /* AIRMapUrlTileManager.m */; }; 21E6570A1D77591400B75EE5 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 21E657091D77591400B75EE5 /* SystemConfiguration.framework */; }; @@ -111,6 +112,8 @@ 2166AB171D82EC56007538D7 /* SMCalloutView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SMCalloutView.m; sourceTree = ""; }; 2166AB271D82EC56007538D7 /* RCTConvert+MoreMapKit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "RCTConvert+MoreMapKit.h"; sourceTree = ""; }; 2166AB281D82EC56007538D7 /* RCTConvert+MoreMapKit.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "RCTConvert+MoreMapKit.m"; sourceTree = ""; }; + 21B248661DA4483D008FCB52 /* DummyView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DummyView.m; sourceTree = ""; }; + 21B248681DA44851008FCB52 /* DummyView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DummyView.h; sourceTree = ""; }; 21D346611D933B8C002BAD8A /* AIRMapUrlTile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRMapUrlTile.h; sourceTree = ""; }; 21D346621D933B8C002BAD8A /* AIRMapUrlTile.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRMapUrlTile.m; sourceTree = ""; }; 21D346631D933B8C002BAD8A /* AIRMapUrlTileManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRMapUrlTileManager.h; sourceTree = ""; }; @@ -195,6 +198,8 @@ 213CA8E71D89F66A008623EC /* AIRGoogleMapMarker.m */, 213CA8E81D89F66A008623EC /* AIRGoogleMapMarkerManager.h */, 213CA8E91D89F66A008623EC /* AIRGoogleMapMarkerManager.m */, + 21B248661DA4483D008FCB52 /* DummyView.m */, + 21B248681DA44851008FCB52 /* DummyView.h */, ); name = AirGoogleMaps; path = ../../ios/AirGoogleMaps; @@ -512,6 +517,7 @@ 2166AB301D82EC56007538D7 /* AIRMapMarker.m in Sources */, 2166AB321D82EC56007538D7 /* AIRMapPolygon.m in Sources */, 13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */, + 21B248671DA4483D008FCB52 /* DummyView.m in Sources */, 2166AB3E1D82EC56007538D7 /* RCTConvert+MoreMapKit.m in Sources */, 13B07FC11A68108700A75B9A /* main.m in Sources */, 2166AB331D82EC56007538D7 /* AIRMapPolygonManager.m in Sources */, diff --git a/example/ios/AirMapsExplorer.xcodeproj/xcshareddata/xcschemes/AirMapsExplorer.xcscheme b/example/ios/AirMapsExplorer.xcodeproj/xcshareddata/xcschemes/AirMapsExplorer.xcscheme index b4bbba00f..9b7c436e0 100644 --- a/example/ios/AirMapsExplorer.xcodeproj/xcshareddata/xcschemes/AirMapsExplorer.xcscheme +++ b/example/ios/AirMapsExplorer.xcodeproj/xcshareddata/xcschemes/AirMapsExplorer.xcscheme @@ -85,6 +85,13 @@ ReferencedContainer = "container:AirMapsExplorer.xcodeproj"> + + + + diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index 9314559fd..6dd5ea99d 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -1,9 +1,9 @@ PODS: - - GoogleMaps (2.0.1): - - GoogleMaps/Maps (= 2.0.1) - - GoogleMaps/Base (2.0.1) - - GoogleMaps/Maps (2.0.1): - - GoogleMaps/Base (= 2.0.1) + - GoogleMaps (2.1.0): + - GoogleMaps/Maps (= 2.1.0) + - GoogleMaps/Base (2.1.0) + - GoogleMaps/Maps (2.1.0): + - GoogleMaps/Base (= 2.1.0) - React/Core (0.32.0): - React/CSSLayout - React/CSSLayout (0.32.0) @@ -45,7 +45,7 @@ EXTERNAL SOURCES: :path: "../node_modules/react-native" SPEC CHECKSUMS: - GoogleMaps: f09da64fc987c1aa29394567c3cab5a3df83c402 + GoogleMaps: 06589b9a38097bce0cd6e90f0fd9b5e4b4a9344c React: 0245b401173a94a5fba0f440aab3fb2f79b738f3 COCOAPODS: 0.39.0 diff --git a/ios/AirGoogleMaps/AIRGoogleMapMarker.m b/ios/AirGoogleMaps/AIRGoogleMapMarker.m index 676fff59e..5c179e6aa 100644 --- a/ios/AirGoogleMaps/AIRGoogleMapMarker.m +++ b/ios/AirGoogleMaps/AIRGoogleMapMarker.m @@ -11,6 +11,7 @@ #import "AIRGoogleMapCallout.h" #import "RCTImageLoader.h" #import "RCTUtils.h" +#import "DummyView.h" CGRect unionRect(CGRect a, CGRect b) { return CGRectMake( @@ -27,6 +28,7 @@ - (id)eventFromMarker:(AIRGMSMarker*)marker; @implementation AIRGoogleMapMarker { RCTImageLoaderCancellationBlock _reloadImageCancellationBlock; __weak UIImageView *_iconImageView; + UIView *_iconView; } - (instancetype)init @@ -38,12 +40,28 @@ - (instancetype)init return self; } +- (void)layoutSubviews { + float width = 0; + float height = 0; + + for (UIView *v in [_iconView subviews]) { + + float fw = v.frame.origin.x + v.frame.size.width; + float fh = v.frame.origin.y + v.frame.size.height; + + width = MAX(fw, width); + height = MAX(fh, height); + } + + [_iconView setFrame:CGRectMake(0, 0, width, height)]; +} + - (id)eventFromMarker:(AIRGMSMarker*)marker { CLLocationCoordinate2D coordinate = marker.position; CGPoint position = [self.realMarker.map.projection pointForCoordinate:coordinate]; -return @{ + return @{ @"id": marker.identifier ?: @"unknown", @"position": @{ @"x": @(position.x), @@ -56,27 +74,33 @@ - (id)eventFromMarker:(AIRGMSMarker*)marker { }; } +- (void)iconViewInsertSubview:(UIView*)subview atIndex:(NSInteger)atIndex { + if (!_realMarker.iconView) { + _iconView = [[UIView alloc] init]; + _realMarker.iconView = _iconView; + } + [_iconView insertSubview:subview atIndex:atIndex]; +} + - (void)insertReactSubview:(id)subview atIndex:(NSInteger)atIndex { if ([subview isKindOfClass:[AIRGoogleMapCallout class]]) { self.calloutView = (AIRGoogleMapCallout *)subview; - } else { - // Custom UIView Marker - // NOTE: Originally I tried creating a new UIView here to encapsulate subview, - // but it would not sizeToFit properly. Not sure why. - [super insertReactSubview:(UIView*)subview atIndex:atIndex]; - [self sizeToFit]; - - // TODO: how to handle this circular reference properly? - _realMarker.iconView = self; + } else { // a child view of the marker + [self iconViewInsertSubview:(UIView*)subview atIndex:atIndex+1]; } + DummyView *dummySubview = [[DummyView alloc] initWithView:(UIView *)subview]; + [super insertReactSubview:(UIView*)dummySubview atIndex:atIndex]; } -- (void)removeReactSubview:(id)subview { +- (void)removeReactSubview:(id)dummySubview { + UIView* subview = ((DummyView*)dummySubview).view; + if ([subview isKindOfClass:[AIRGoogleMapCallout class]]) { self.calloutView = nil; } else { - [super removeReactSubview:(UIView*)subview]; + [(UIView*)subview removeFromSuperview]; } + [super removeReactSubview:(UIView*)dummySubview]; } - (void)showCalloutView { @@ -151,7 +175,6 @@ - (RCTBubblingEventBlock)onPress { - (void)setImageSrc:(NSString *)imageSrc { - _imageSrc = imageSrc; if (_reloadImageCancellationBlock) { @@ -172,11 +195,14 @@ - (void)setImageSrc:(NSString *)imageSrc } dispatch_async(dispatch_get_main_queue(), ^{ - if (_iconImageView) { - // TODO: doesn't work because image is blank (WHY??) - [_iconImageView setImage:image]; - return; - } + // TODO(gil): This way allows different image sizes + if (_iconImageView) [_iconImageView removeFromSuperview]; + + // ... but this way is more efficient? +// if (_iconImageView) { +// [_iconImageView setImage:image]; +// return; +// } UIImageView *imageView = [[UIImageView alloc] initWithImage:image]; @@ -197,9 +223,7 @@ - (void)setImageSrc:(NSString *)imageSrc [self setFrame:selfBounds]; _iconImageView = imageView; - - [super insertSubview:imageView atIndex:0]; - _realMarker.iconView = self; + [self iconViewInsertSubview:imageView atIndex:0]; // TODO: This could be a prop //_realMarker.groundAnchor = CGPointMake(0.75, 1); diff --git a/ios/AirGoogleMaps/DummyView.h b/ios/AirGoogleMaps/DummyView.h new file mode 100644 index 000000000..ba4be2834 --- /dev/null +++ b/ios/AirGoogleMaps/DummyView.h @@ -0,0 +1,14 @@ +// +// DummyView.h +// AirMapsExplorer +// +// Created by Gil Birman on 10/4/16. +// + +#import + + +@interface DummyView : UIView +@property (nonatomic, weak) UIView *view; +- (instancetype)initWithView:(UIView*)view; +@end diff --git a/ios/AirGoogleMaps/DummyView.m b/ios/AirGoogleMaps/DummyView.m new file mode 100644 index 000000000..9e8439707 --- /dev/null +++ b/ios/AirGoogleMaps/DummyView.m @@ -0,0 +1,19 @@ +// +// DummyView.m +// AirMapsExplorer +// +// Created by Gil Birman on 10/4/16. +// + +#import +#import "DummyView.h" + +@implementation DummyView +- (instancetype)initWithView:(UIView*)view +{ + if ((self = [super init])) { + self.view = view; + } + return self; +} +@end From ab5c2c151a4f04d6ecb63f524b67abd40a572802 Mon Sep 17 00:00:00 2001 From: Spike Brehm Date: Wed, 5 Oct 2016 13:17:45 -0700 Subject: [PATCH 0106/1148] v0.9.0 --- android/gradle.properties | 2 +- package.json | 2 +- react-native-google-maps.podspec | 2 +- react-native-maps.podspec | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/android/gradle.properties b/android/gradle.properties index 3e0156412..34832a259 100644 --- a/android/gradle.properties +++ b/android/gradle.properties @@ -1,5 +1,5 @@ VERSION_CODE=2 -VERSION_NAME=0.9.0-rc.0 +VERSION_NAME=0.9.0 GROUP=com.airbnb.android POM_DESCRIPTION=React Native Map view component for Android diff --git a/package.json b/package.json index df55868e3..6cecb4664 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "description": "React Native Mapview component for iOS + Android", "main": "index.js", "author": "Leland Richardson ", - "version": "0.9.0-rc.0", + "version": "0.9.0", "scripts": { "start": "react-native start", "lint": "eslint ." diff --git a/react-native-google-maps.podspec b/react-native-google-maps.podspec index 7062cd7e6..0aae3ec22 100644 --- a/react-native-google-maps.podspec +++ b/react-native-google-maps.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "react-native-google-maps" - s.version = "0.9.0-rc.0" + s.version = "0.9.0" s.summary = "React Native Mapview component for iOS + Android" s.authors = { "intelligibabble" => "leland.m.richardson@gmail.com" } diff --git a/react-native-maps.podspec b/react-native-maps.podspec index 2b543a6e9..7c9e9134a 100644 --- a/react-native-maps.podspec +++ b/react-native-maps.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "react-native-maps" - s.version = "0.9.0-rc.0" + s.version = "0.9.0" s.summary = "React Native Mapview component for iOS + Android" s.authors = { "intelligibabble" => "leland.m.richardson@gmail.com" } From 96524b41dc524c7dcaa0dff7bd42383c981d2fc3 Mon Sep 17 00:00:00 2001 From: gilbox Date: Wed, 5 Oct 2016 14:44:21 -0700 Subject: [PATCH 0107/1148] Bump RN version to 0.33.0 --- example/ios/Podfile.lock | 24 ++++++++++++------------ example/package.json | 2 +- ios/AirMaps/AIRMapMarker.m | 1 - package.json | 2 +- 4 files changed, 14 insertions(+), 15 deletions(-) diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index 6dd5ea99d..a25a5caa3 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -4,27 +4,27 @@ PODS: - GoogleMaps/Base (2.1.0) - GoogleMaps/Maps (2.1.0): - GoogleMaps/Base (= 2.1.0) - - React/Core (0.32.0): + - React/Core (0.33.0): - React/CSSLayout - - React/CSSLayout (0.32.0) - - React/RCTActionSheet (0.32.0): + - React/CSSLayout (0.33.0) + - React/RCTActionSheet (0.33.0): - React/Core - - React/RCTGeolocation (0.32.0): + - React/RCTGeolocation (0.33.0): - React/Core - - React/RCTImage (0.32.0): + - React/RCTImage (0.33.0): - React/Core - React/RCTNetwork - - React/RCTLinkingIOS (0.32.0): + - React/RCTLinkingIOS (0.33.0): - React/Core - - React/RCTNetwork (0.32.0): + - React/RCTNetwork (0.33.0): - React/Core - - React/RCTSettings (0.32.0): + - React/RCTSettings (0.33.0): - React/Core - - React/RCTText (0.32.0): + - React/RCTText (0.33.0): - React/Core - - React/RCTVibration (0.32.0): + - React/RCTVibration (0.33.0): - React/Core - - React/RCTWebSocket (0.32.0): + - React/RCTWebSocket (0.33.0): - React/Core DEPENDENCIES: @@ -46,6 +46,6 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: GoogleMaps: 06589b9a38097bce0cd6e90f0fd9b5e4b4a9344c - React: 0245b401173a94a5fba0f440aab3fb2f79b738f3 + React: 46edc166689ba71b0b6cf11e64dbdb258d177089 COCOAPODS: 0.39.0 diff --git a/example/package.json b/example/package.json index 788629857..83ff86b95 100644 --- a/example/package.json +++ b/example/package.json @@ -10,7 +10,7 @@ }, "dependencies": { "react": "15.3.0", - "react-native": "0.32.0", + "react-native": "0.33.0", "react-native-maps": "../" }, "devDependencies": { diff --git a/ios/AirMaps/AIRMapMarker.m b/ios/AirMaps/AIRMapMarker.m index 4c3c0f6cc..79343cff0 100644 --- a/ios/AirMaps/AIRMapMarker.m +++ b/ios/AirMaps/AIRMapMarker.m @@ -215,7 +215,6 @@ - (void)setImageSrc:(NSString *)imageSrc clipped:YES resizeMode:RCTResizeModeCenter progressBlock:nil - partialLoadBlock:nil completionBlock:^(NSError *error, UIImage *image) { if (error) { // TODO(lmr): do something with the error? diff --git a/package.json b/package.json index 6cecb4664..7686ea95b 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ ], "peerDependencies": { "react": ">=15.3.0", - "react-native": ">=0.32.0" + "react-native": ">=0.33.0" }, "devDependencies": { "babel-eslint": "^6.1.2", From 69a32aa3bf6b3d6b2e8a2fa29163e0de6e086ed9 Mon Sep 17 00:00:00 2001 From: Gil Birman Date: Wed, 5 Oct 2016 23:06:50 -0700 Subject: [PATCH 0108/1148] v0.10.0 (#652) --- CHANGELOG.md | 6 ++++++ android/gradle.properties | 2 +- package.json | 2 +- react-native-google-maps.podspec | 2 +- react-native-maps.podspec | 2 +- 5 files changed, 10 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 86a78e750..4c8a1ec07 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Change Log +## 0.10.0 (October 5, 2016) + +### Breaking Changes + +* Upgrade to `react-native@0.33.0` + ## 0.9.0 (September 28, 2016) As of this release, this repository has moved from diff --git a/android/gradle.properties b/android/gradle.properties index 34832a259..ac2813f55 100644 --- a/android/gradle.properties +++ b/android/gradle.properties @@ -1,5 +1,5 @@ VERSION_CODE=2 -VERSION_NAME=0.9.0 +VERSION_NAME=0.10.0 GROUP=com.airbnb.android POM_DESCRIPTION=React Native Map view component for Android diff --git a/package.json b/package.json index 7686ea95b..8b2cd3eaa 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "description": "React Native Mapview component for iOS + Android", "main": "index.js", "author": "Leland Richardson ", - "version": "0.9.0", + "version": "0.10.0", "scripts": { "start": "react-native start", "lint": "eslint ." diff --git a/react-native-google-maps.podspec b/react-native-google-maps.podspec index 0aae3ec22..387f55ce5 100644 --- a/react-native-google-maps.podspec +++ b/react-native-google-maps.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "react-native-google-maps" - s.version = "0.9.0" + s.version = "0.10.0" s.summary = "React Native Mapview component for iOS + Android" s.authors = { "intelligibabble" => "leland.m.richardson@gmail.com" } diff --git a/react-native-maps.podspec b/react-native-maps.podspec index 7c9e9134a..23abe624e 100644 --- a/react-native-maps.podspec +++ b/react-native-maps.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "react-native-maps" - s.version = "0.9.0" + s.version = "0.10.0" s.summary = "React Native Mapview component for iOS + Android" s.authors = { "intelligibabble" => "leland.m.richardson@gmail.com" } From 0a143d8f86b9877e710e96e909364223484b2e6c Mon Sep 17 00:00:00 2001 From: gilbox Date: Fri, 7 Oct 2016 16:39:04 -0700 Subject: [PATCH 0109/1148] [android] fix gradle build setup for explorer, bump to gradle 2.2.0 --- android/build.gradle | 35 +++++++++++++++++------------------ example/android/build.gradle | 2 +- 2 files changed, 18 insertions(+), 19 deletions(-) diff --git a/android/build.gradle b/android/build.gradle index 684c92e24..4b13030d9 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -2,23 +2,22 @@ apply plugin: 'com.android.library' apply from: 'gradle-maven-push.gradle' - buildscript { repositories { - mavenLocal() - jcenter() - maven { - // For developing the library outside the context of the example app, expect `react-native` - // to be installed at `./android/node_modules`. - url "$projectDir/../node_modules/react-native/android" - } maven { // For developing the example app, expect this library to be installed as a node module // inside of the example app. So traverse from `./android/example/node_modules/react-native-maps/android` // to `./android/example/node_modules/react-native/android`. // react-native should be installed since it's a peer dependency - url "$projectDir/../../react-native/android" + url "$projectDir/../example/node_modules/react-native/android" } + maven { + // For developing the library outside the context of the example app, expect `react-native` + // to be installed at `./android/node_modules`. + url "$projectDir/../node_modules/react-native/android" + } + mavenLocal() + jcenter() } dependencies { classpath 'com.android.tools.build:gradle:2.1.0' @@ -27,20 +26,20 @@ buildscript { allprojects { repositories { - mavenLocal() - jcenter() + maven { + // For developing the example app, expect this library to be installed as a node module + // inside of the example app. So traverse from `./android/example/node_modules/react-native-maps/android` + // to `./android/example/node_modules/react-native/android`. + // react-native should be installed since it's a peer dependency + url "$projectDir/../example/node_modules/react-native/android" + } maven { // For developing the library outside the context of the example app, expect `react-native` // to be installed at `./android/node_modules`. url "$projectDir/../node_modules/react-native/android" } - maven { - // For developing the example app, expect this library to be installed as a node module - // inside of the example app. So traverse from `./android/example/node_modules/react-native-maps/android` - // to `./android/example/node_modules/react-native/android`. - // react-native should be installed since it's a peer dependency - url "$projectDir/../../react-native/android" - } + mavenLocal() + jcenter() } } diff --git a/example/android/build.gradle b/example/android/build.gradle index 421e13f2f..cc73e1e1e 100644 --- a/example/android/build.gradle +++ b/example/android/build.gradle @@ -5,7 +5,7 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:2.1.3' + classpath 'com.android.tools.build:gradle:2.2.0' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files From 375da114d9af4c426baadbf4c0fd4eaa36bb0a42 Mon Sep 17 00:00:00 2001 From: gilbox Date: Mon, 10 Oct 2016 10:45:38 -0700 Subject: [PATCH 0110/1148] [android] fix getAirMapName to fix ref-based commands --- components/decorateMapComponent.js | 1 + 1 file changed, 1 insertion(+) diff --git a/components/decorateMapComponent.js b/components/decorateMapComponent.js index 5af86a427..2f5e98de5 100644 --- a/components/decorateMapComponent.js +++ b/components/decorateMapComponent.js @@ -14,6 +14,7 @@ export const USES_DEFAULT_IMPLEMENTATION = 'USES_DEFAULT_IMPLEMENTATION'; export const NOT_SUPPORTED = 'NOT_SUPPORTED'; export function getAirMapName(provider) { + if (Platform.OS === 'android') return 'AIRMap'; if (provider === PROVIDER_GOOGLE) return 'AIRGoogleMap'; return 'AIRMap'; } From 87c584730a565fab9c5def99c1b6bffdc61d3d08 Mon Sep 17 00:00:00 2001 From: gilbox Date: Mon, 10 Oct 2016 10:46:24 -0700 Subject: [PATCH 0111/1148] [android] fix gradle build setup for explorer, bump to gradle --- android/build.gradle | 43 +++++++++++++++++++------------------------ 1 file changed, 19 insertions(+), 24 deletions(-) diff --git a/android/build.gradle b/android/build.gradle index 4b13030d9..9cef8f1d0 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -2,22 +2,20 @@ apply plugin: 'com.android.library' apply from: 'gradle-maven-push.gradle' + buildscript { repositories { - maven { - // For developing the example app, expect this library to be installed as a node module - // inside of the example app. So traverse from `./android/example/node_modules/react-native-maps/android` - // to `./android/example/node_modules/react-native/android`. - // react-native should be installed since it's a peer dependency - url "$projectDir/../example/node_modules/react-native/android" - } + mavenLocal() + jcenter() maven { // For developing the library outside the context of the example app, expect `react-native` - // to be installed at `./android/node_modules`. + // to be installed at `./node_modules`. url "$projectDir/../node_modules/react-native/android" } - mavenLocal() - jcenter() + maven { + // For developing the example app. + url "$projectDir/../../react-native/android" + } } dependencies { classpath 'com.android.tools.build:gradle:2.1.0' @@ -26,20 +24,17 @@ buildscript { allprojects { repositories { - maven { - // For developing the example app, expect this library to be installed as a node module - // inside of the example app. So traverse from `./android/example/node_modules/react-native-maps/android` - // to `./android/example/node_modules/react-native/android`. - // react-native should be installed since it's a peer dependency - url "$projectDir/../example/node_modules/react-native/android" - } - maven { - // For developing the library outside the context of the example app, expect `react-native` - // to be installed at `./android/node_modules`. - url "$projectDir/../node_modules/react-native/android" - } - mavenLocal() - jcenter() + mavenLocal() + jcenter() + maven { + // For developing the library outside the context of the example app, expect `react-native` + // to be installed at `./node_modules`. + url "$projectDir/../node_modules/react-native/android" + } + maven { + // For developing the example app. + url "$projectDir/../../react-native/android" + } } } From 2f4cc03f2f713bb1c802544a3a1a01c69eeb22fb Mon Sep 17 00:00:00 2001 From: Gil Birman Date: Mon, 10 Oct 2016 15:58:27 -0700 Subject: [PATCH 0112/1148] v0.10.1 (#673) --- CHANGELOG.md | 12 ++++++++++++ android/gradle.properties | 2 +- package.json | 2 +- react-native-google-maps.podspec | 2 +- react-native-maps.podspec | 2 +- 5 files changed, 16 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4c8a1ec07..ee1eeda15 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,17 @@ # Change Log +## 0.10.0 (October 10, 2016) + +### Patches + +* [android] fix gradle build setup for explorer, bump to gradle 2.2.0 + [#666](https://github.com/airbnb/react-native-maps/pull/666) + (@gilbox) +* [android] fix getAirMapName to fix ref-based commands + [#665](https://github.com/airbnb/react-native-maps/pull/665) + (@gilbox) +* Hopefully this release will fix issue [#656](https://github.com/airbnb/react-native-maps/issues/656) + ## 0.10.0 (October 5, 2016) ### Breaking Changes diff --git a/android/gradle.properties b/android/gradle.properties index ac2813f55..78fc2b11d 100644 --- a/android/gradle.properties +++ b/android/gradle.properties @@ -1,5 +1,5 @@ VERSION_CODE=2 -VERSION_NAME=0.10.0 +VERSION_NAME=0.10.1 GROUP=com.airbnb.android POM_DESCRIPTION=React Native Map view component for Android diff --git a/package.json b/package.json index 8b2cd3eaa..54af102c0 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "description": "React Native Mapview component for iOS + Android", "main": "index.js", "author": "Leland Richardson ", - "version": "0.10.0", + "version": "0.10.1", "scripts": { "start": "react-native start", "lint": "eslint ." diff --git a/react-native-google-maps.podspec b/react-native-google-maps.podspec index 387f55ce5..3148c9238 100644 --- a/react-native-google-maps.podspec +++ b/react-native-google-maps.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "react-native-google-maps" - s.version = "0.10.0" + s.version = "0.10.1" s.summary = "React Native Mapview component for iOS + Android" s.authors = { "intelligibabble" => "leland.m.richardson@gmail.com" } diff --git a/react-native-maps.podspec b/react-native-maps.podspec index 23abe624e..c6843b48f 100644 --- a/react-native-maps.podspec +++ b/react-native-maps.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "react-native-maps" - s.version = "0.10.0" + s.version = "0.10.1" s.summary = "React Native Mapview component for iOS + Android" s.authors = { "intelligibabble" => "leland.m.richardson@gmail.com" } From 3433a7aac50224091b2dd4542ef579703b02c322 Mon Sep 17 00:00:00 2001 From: Matt Lanter Date: Mon, 10 Oct 2016 18:58:53 -0700 Subject: [PATCH 0113/1148] [android] Add parameter to disable the moving on marker press --- .../airbnb/android/react/maps/AirMapManager.java | 5 +++++ .../com/airbnb/android/react/maps/AirMapView.java | 14 +++++++++++++- components/MapView.js | 8 ++++++++ 3 files changed, 26 insertions(+), 1 deletion(-) diff --git a/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java b/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java index b35737021..2f6e30d46 100644 --- a/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java +++ b/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java @@ -165,6 +165,11 @@ public void setLoadingEnabled(AirMapView view, boolean loadingEnabled) { view.enableMapLoading(loadingEnabled); } + @ReactProp(name="moveOnMarkerPress", defaultBoolean = true) + public void setMoveOnMarkerPress(AirMapView view, boolean moveOnPress) { + view.setMoveOnMarkerPress(moveOnPress); + } + @ReactProp(name="loadingBackgroundColor", customType="Color") public void setLoadingBackgroundColor(AirMapView view, @Nullable Integer loadingBackgroundColor) { view.setLoadingBackgroundColor(loadingBackgroundColor); diff --git a/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java b/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java index 4a04af88a..faae1a002 100644 --- a/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java +++ b/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java @@ -65,6 +65,7 @@ public class AirMapView extends MapView implements GoogleMap.InfoWindowAdapter, private boolean isMonitoringRegion = false; private boolean isTouchDown = false; private boolean handlePanDrag = false; + private boolean moveOnMarkerPress = true; private boolean cacheEnabled = false; private static final String[] PERMISSIONS = new String[] { @@ -154,7 +155,14 @@ public boolean onMarkerClick(Marker marker) { event.putString("action", "marker-press"); manager.pushEvent(markerMap.get(marker), "onPress", event); - return false; // returning false opens the callout window, if possible + // Return false to open the callout info window and center on the marker + // https://developers.google.com/android/reference/com/google/android/gms/maps/GoogleMap.OnMarkerClickListener + if (view.moveOnMarkerPress) { + return false; + } else { + marker.showInfoWindow(); + return true; + } } }); @@ -330,6 +338,10 @@ public void enableMapLoading(boolean loadingEnabled) { } } + public void setMoveOnMarkerPress(boolean moveOnPress) { + this.moveOnMarkerPress = moveOnPress; + } + public void setLoadingBackgroundColor(Integer loadingBackgroundColor) { this.loadingBackgroundColor = loadingBackgroundColor; diff --git a/components/MapView.js b/components/MapView.js index 429a71133..a7762665d 100644 --- a/components/MapView.js +++ b/components/MapView.js @@ -167,6 +167,14 @@ const propTypes = { */ toolbarEnabled: PropTypes.bool, + /** + * A Boolean indicating whether on marker press the map will move to the pressed marker + * Default value is `true` + * + * @platform android + */ + moveOnMarkerPress: PropTypes.bool, + /** * A Boolean indicating whether the map shows scale information. * Default value is `false` From 99c3bdadbcec3cfccb58f87ecfaffc95deb03aa0 Mon Sep 17 00:00:00 2001 From: Eugene HP Date: Wed, 12 Oct 2016 01:40:12 +0300 Subject: [PATCH 0114/1148] upgraded to RN 0.35 and added fix to RCTImageLoader, missing `partialLoadBlock` (#680) --- ios/AirMaps/AIRMapMarker.m | 1 + package.json | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/ios/AirMaps/AIRMapMarker.m b/ios/AirMaps/AIRMapMarker.m index 79343cff0..4c3c0f6cc 100644 --- a/ios/AirMaps/AIRMapMarker.m +++ b/ios/AirMaps/AIRMapMarker.m @@ -215,6 +215,7 @@ - (void)setImageSrc:(NSString *)imageSrc clipped:YES resizeMode:RCTResizeModeCenter progressBlock:nil + partialLoadBlock:nil completionBlock:^(NSError *error, UIImage *image) { if (error) { // TODO(lmr): do something with the error? diff --git a/package.json b/package.json index 54af102c0..fbd52827d 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ ], "peerDependencies": { "react": ">=15.3.0", - "react-native": ">=0.33.0" + "react-native": ">=0.35" }, "devDependencies": { "babel-eslint": "^6.1.2", From e313be38f1f1820fda6c6dc7f8d9442224ac4595 Mon Sep 17 00:00:00 2001 From: Matt Lanter Date: Tue, 11 Oct 2016 16:13:24 -0700 Subject: [PATCH 0115/1148] Add spaces around `=` --- .../com/airbnb/android/react/maps/AirMapManager.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java b/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java index 2f6e30d46..b31106dca 100644 --- a/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java +++ b/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java @@ -155,27 +155,27 @@ public void setRotateEnabled(AirMapView view, boolean rotateEnabled) { view.map.getUiSettings().setRotateGesturesEnabled(rotateEnabled); } - @ReactProp(name="cacheEnabled", defaultBoolean = false) + @ReactProp(name = "cacheEnabled", defaultBoolean = false) public void setCacheEnabled(AirMapView view, boolean cacheEnabled) { view.setCacheEnabled(cacheEnabled); } - @ReactProp(name="loadingEnabled", defaultBoolean = false) + @ReactProp(name = "loadingEnabled", defaultBoolean = false) public void setLoadingEnabled(AirMapView view, boolean loadingEnabled) { view.enableMapLoading(loadingEnabled); } - @ReactProp(name="moveOnMarkerPress", defaultBoolean = true) + @ReactProp(name = "moveOnMarkerPress", defaultBoolean = true) public void setMoveOnMarkerPress(AirMapView view, boolean moveOnPress) { view.setMoveOnMarkerPress(moveOnPress); } - @ReactProp(name="loadingBackgroundColor", customType="Color") + @ReactProp(name = "loadingBackgroundColor", customType = "Color") public void setLoadingBackgroundColor(AirMapView view, @Nullable Integer loadingBackgroundColor) { view.setLoadingBackgroundColor(loadingBackgroundColor); } - @ReactProp(name="loadingIndicatorColor", customType="Color") + @ReactProp(name = "loadingIndicatorColor", customType = "Color") public void setLoadingIndicatorColor(AirMapView view, @Nullable Integer loadingIndicatorColor) { view.setLoadingIndicatorColor(loadingIndicatorColor); } From 914ec6d13ccedefe55c0bb90dd3ceab4d020a88c Mon Sep 17 00:00:00 2001 From: Youngchan Je Date: Thu, 13 Oct 2016 09:44:21 +0900 Subject: [PATCH 0116/1148] included MapUrlTile usage in README.md --- README.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/README.md b/README.md index c7bad724e..f4f1c5f6f 100644 --- a/README.md +++ b/README.md @@ -135,6 +135,22 @@ render() {
``` +### Using a custom Tile Overlay + +```jsx + + + +``` ## Examples From 8dac2ef8ff413578156a15c62867ef6834604e03 Mon Sep 17 00:00:00 2001 From: Youngchan Je Date: Thu, 13 Oct 2016 10:12:40 +0900 Subject: [PATCH 0117/1148] travis build fix --- example/examples/CachedMap.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/example/examples/CachedMap.js b/example/examples/CachedMap.js index f76ad3308..349e996b8 100644 --- a/example/examples/CachedMap.js +++ b/example/examples/CachedMap.js @@ -66,8 +66,8 @@ class CachedMap extends React.Component { cacheEnabled={this.state.cache} zoomEnabled scrollingEnabled - loadingIndicatorColor={"#666666"} - loadingBackgroundColor={"#eeeeee"} + loadingIndicatorColor={'#666666'} + loadingBackgroundColor={'#eeeeee'} > Date: Thu, 13 Oct 2016 10:13:19 +0900 Subject: [PATCH 0118/1148] travis build fix --- example/examples/LoadingMap.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/example/examples/LoadingMap.js b/example/examples/LoadingMap.js index a7cca9fe8..5d6279f71 100644 --- a/example/examples/LoadingMap.js +++ b/example/examples/LoadingMap.js @@ -41,8 +41,8 @@ class LoadingMap extends React.Component { initialRegion={this.state.region} onPress={this.onMapPress} loadingEnabled - loadingIndicatorColor={"#666666"} - loadingBackgroundColor={"#eeeeee"} + loadingIndicatorColor={'#666666'} + loadingBackgroundColor={'#eeeeee'} > Date: Thu, 13 Oct 2016 12:02:09 +0900 Subject: [PATCH 0119/1148] included Android and IOS setup --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.md b/README.md index f4f1c5f6f..2b59aae3a 100644 --- a/README.md +++ b/README.md @@ -152,6 +152,14 @@ render() { ``` +For Android: add the following line in your AndroidManifest.xml +```xml + +``` +For IOS: configure [App Transport Security](https://developer.apple.com/library/content/documentation/General/Reference/InfoPlistKeyReference/Articles/CocoaKeys.html#//apple_ref/doc/uid/TP40009251-SW33) in your app + + + ## Examples ### MapView Events From 734c5d73db0411f5ba3072658a8729992782ba0a Mon Sep 17 00:00:00 2001 From: Youngchan Je Date: Thu, 13 Oct 2016 16:00:12 +0900 Subject: [PATCH 0120/1148] kept double quote and removed curly braces --- example/examples/CachedMap.js | 4 ++-- example/examples/LoadingMap.js | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/example/examples/CachedMap.js b/example/examples/CachedMap.js index 349e996b8..296e042d6 100644 --- a/example/examples/CachedMap.js +++ b/example/examples/CachedMap.js @@ -66,8 +66,8 @@ class CachedMap extends React.Component { cacheEnabled={this.state.cache} zoomEnabled scrollingEnabled - loadingIndicatorColor={'#666666'} - loadingBackgroundColor={'#eeeeee'} + loadingIndicatorColor="#666666" + loadingBackgroundColor="#eeeeee" > Date: Mon, 10 Oct 2016 17:56:11 -0700 Subject: [PATCH 0121/1148] [zIndex] Add support for setting zIndex on markers --- .../com/airbnb/android/react/maps/AirMapMarker.java | 10 ++++++++++ .../airbnb/android/react/maps/AirMapMarkerManager.java | 6 ++++++ ios/AirMaps/AIRMapMarker.h | 1 + ios/AirMaps/AIRMapMarker.m | 8 ++++++++ ios/AirMaps/AIRMapMarkerManager.m | 1 + 5 files changed, 26 insertions(+) diff --git a/android/src/main/java/com/airbnb/android/react/maps/AirMapMarker.java b/android/src/main/java/com/airbnb/android/react/maps/AirMapMarker.java index 8623812c2..de01d106e 100644 --- a/android/src/main/java/com/airbnb/android/react/maps/AirMapMarker.java +++ b/android/src/main/java/com/airbnb/android/react/maps/AirMapMarker.java @@ -61,6 +61,7 @@ public class AirMapMarker extends AirMapFeature { private float rotation = 0.0f; private boolean flat = false; private boolean draggable = false; + private int zIndex = 0; private float calloutAnchorX; private float calloutAnchorY; @@ -173,6 +174,14 @@ public void setDraggable(boolean draggable) { update(); } + public void setZIndex(int zIndex) { + this.zIndex = zIndex; + if (marker != null) { + marker.setZIndex(zIndex); + } + update(); + } + public void setMarkerHue(float markerHue) { this.markerHue = markerHue; update(); @@ -288,6 +297,7 @@ private MarkerOptions createMarkerOptions() { options.rotation(rotation); options.flat(flat); options.draggable(draggable); + options.zIndex(zIndex); options.icon(getIcon()); return options; } diff --git a/android/src/main/java/com/airbnb/android/react/maps/AirMapMarkerManager.java b/android/src/main/java/com/airbnb/android/react/maps/AirMapMarkerManager.java index f87a8233a..a3d079b10 100644 --- a/android/src/main/java/com/airbnb/android/react/maps/AirMapMarkerManager.java +++ b/android/src/main/java/com/airbnb/android/react/maps/AirMapMarkerManager.java @@ -116,6 +116,12 @@ public void setDraggable(AirMapMarker view, boolean draggable) { view.setDraggable(draggable); } + @ReactProp(name = "zIndex", defaultFloat = 0.0f) + public void setZIndex(AirMapMarker view, float zIndex) { + int integerZIndex = Math.round(zIndex); + view.setZIndex(integerZIndex); + } + @Override public void addView(AirMapMarker parent, View child, int index) { // if an component is a child, then it is a callout view, NOT part of the diff --git a/ios/AirMaps/AIRMapMarker.h b/ios/AirMaps/AIRMapMarker.h index d1779074f..187cbad0a 100644 --- a/ios/AirMaps/AIRMapMarker.h +++ b/ios/AirMaps/AIRMapMarker.h @@ -32,6 +32,7 @@ @property (nonatomic, copy) NSString *subtitle; @property (nonatomic, assign) CLLocationCoordinate2D coordinate; @property (nonatomic, strong) UIColor *pinColor; +@property (nonatomic, assign) NSInteger zIndex; @property (nonatomic, copy) RCTBubblingEventBlock onPress; @property (nonatomic, copy) RCTDirectEventBlock onSelect; diff --git a/ios/AirMaps/AIRMapMarker.m b/ios/AirMaps/AIRMapMarker.m index 4c3c0f6cc..983f5fabe 100644 --- a/ios/AirMaps/AIRMapMarker.m +++ b/ios/AirMaps/AIRMapMarker.m @@ -75,6 +75,7 @@ - (MKAnnotationView *)getAnnotationView } _pinView.draggable = self.draggable; + _pinView.layer.zPosition = self.zIndex; // TODO(lmr): Looks like this API was introduces in iOS 8. We may want to handle differently for earlier // versions. Right now it's just leaving it with the default color. People needing the colors are free to @@ -89,6 +90,7 @@ - (MKAnnotationView *)getAnnotationView // if it has a non-null image, it means we want to render a custom marker with the image. // In either case, we want to return the AIRMapMarker since it is both an MKAnnotation and an // MKAnnotationView all at the same time. + self.layer.zPosition = self.zIndex; return self; } } @@ -236,4 +238,10 @@ - (void)setPinColor:(UIColor *)pinColor } } +- (void)setZIndex:(NSInteger)zIndex +{ + _zIndex = zIndex; + self.layer.zPosition = _zIndex; +} + @end diff --git a/ios/AirMaps/AIRMapMarkerManager.m b/ios/AirMaps/AIRMapMarkerManager.m index 83a18c4a2..ceecf0148 100644 --- a/ios/AirMaps/AIRMapMarkerManager.m +++ b/ios/AirMaps/AIRMapMarkerManager.m @@ -43,6 +43,7 @@ - (UIView *)view RCT_REMAP_VIEW_PROPERTY(image, imageSrc, NSString) RCT_EXPORT_VIEW_PROPERTY(pinColor, UIColor) RCT_EXPORT_VIEW_PROPERTY(draggable, BOOL) +RCT_EXPORT_VIEW_PROPERTY(zIndex, NSInteger) RCT_EXPORT_VIEW_PROPERTY(onPress, RCTBubblingEventBlock) RCT_EXPORT_VIEW_PROPERTY(onSelect, RCTDirectEventBlock) From 2828d2e099d375c75d36057f001d63ae2ebe0293 Mon Sep 17 00:00:00 2001 From: Matt Lanter Date: Wed, 12 Oct 2016 13:25:47 -0700 Subject: [PATCH 0122/1148] Add an example --- .../react/maps/AirMapMarkerManager.java | 2 + example/App.js | 2 + example/examples/ZIndexMarkers.js | 102 ++++++++++++++++++ 3 files changed, 106 insertions(+) create mode 100644 example/examples/ZIndexMarkers.js diff --git a/android/src/main/java/com/airbnb/android/react/maps/AirMapMarkerManager.java b/android/src/main/java/com/airbnb/android/react/maps/AirMapMarkerManager.java index a3d079b10..f6da4c1cd 100644 --- a/android/src/main/java/com/airbnb/android/react/maps/AirMapMarkerManager.java +++ b/android/src/main/java/com/airbnb/android/react/maps/AirMapMarkerManager.java @@ -116,8 +116,10 @@ public void setDraggable(AirMapMarker view, boolean draggable) { view.setDraggable(draggable); } + @Override @ReactProp(name = "zIndex", defaultFloat = 0.0f) public void setZIndex(AirMapMarker view, float zIndex) { + super.setZIndex(view, zIndex); int integerZIndex = Math.round(zIndex); view.setZIndex(integerZIndex); } diff --git a/example/App.js b/example/App.js index 625f67edb..e927c4566 100644 --- a/example/App.js +++ b/example/App.js @@ -29,6 +29,7 @@ import FitToSuppliedMarkers from './examples/FitToSuppliedMarkers'; import FitToCoordinates from './examples/FitToCoordinates'; import LiteMapView from './examples/LiteMapView'; import CustomTiles from './examples/CustomTiles'; +import ZIndexMarkers from './examples/ZIndexMarkers'; import StaticMap from './examples/StaticMap'; const IOS = Platform.OS === 'ios'; @@ -138,6 +139,7 @@ class App extends React.Component { [FitToCoordinates, 'Fit Map To Coordinates'], [LiteMapView, 'Android Lite MapView'], [CustomTiles, 'Custom Tiles'], + [ZIndexMarkers, 'Position Markers with Z-index', true], ] // Filter out examples that are not yet supported for Google Maps on iOS. .filter(example => ANDROID || (IOS && (example[2] || !this.state.useGoogleMaps))) diff --git a/example/examples/ZIndexMarkers.js b/example/examples/ZIndexMarkers.js new file mode 100644 index 000000000..c9e67cd5b --- /dev/null +++ b/example/examples/ZIndexMarkers.js @@ -0,0 +1,102 @@ +import React from 'react'; +import { + Dimensions, + StyleSheet, + Text, + View, +} from 'react-native'; + +import MapView from 'react-native-maps'; + +const { width, height } = Dimensions.get('window'); + +const ASPECT_RATIO = width / height; +const LATITUDE = 37.733858; +const LONGITUDE = -122.446549; +const MARKERS_LATITUDE_DELTA = 0.03; +const MARKERS_LONGITUDE_DELTA = MARKERS_LATITUDE_DELTA * ASPECT_RATIO; +const MAP_LATITUDE_DELTA = 0.3; +const MAP_LONGITUDE_DELTA = MAP_LATITUDE_DELTA * ASPECT_RATIO; +const NUM_MARKERS = 100; +const PERCENT_SPECIAL_MARKERS = 0.1; + +class ZIndexMarkers extends React.Component { + constructor(props) { + super(props); + + let markerInfo = []; + for (let i = 1; i < NUM_MARKERS; i++) { + markerInfo.push({ + latitude: (Math.random() * 2 - 1) * MARKERS_LATITUDE_DELTA + LATITUDE, + longitude: (Math.random() * 2 - 1) * MARKERS_LONGITUDE_DELTA + LONGITUDE, + isSpecial: Math.random() < PERCENT_SPECIAL_MARKERS, + id: i, + }); + } + + this.state = { + markerInfo + }; + } + + render() { + let markers = this.state.markerInfo.map((markerInfo) => { + return ( + + ); + }); + + return ( + + { this.map = ref; }} + style={styles.map} + initialRegion={{ + latitude: LATITUDE, + longitude: LONGITUDE, + latitudeDelta: MAP_LATITUDE_DELTA, + longitudeDelta: MAP_LONGITUDE_DELTA, + }} + > + {markers} + + + The yellow markers have a higher zIndex and appear above other markers. + + + ); + } +} + +ZIndexMarkers.propTypes = { + provider: MapView.ProviderPropType, +}; + +const styles = StyleSheet.create({ + container: { + ...StyleSheet.absoluteFillObject, + justifyContent: 'flex-end', + alignItems: 'center', + }, + map: { + ...StyleSheet.absoluteFillObject, + }, + textContainer: { + backgroundColor: 'white', + borderRadius: 4, + marginHorizontal: 40, + marginVertical: 20, + padding: 10, + }, + specialMarker: { + zIndex: 1, + }, +}); + +module.exports = ZIndexMarkers; From 45f85a050e87541216495fe87fb80e2ef9bfa62e Mon Sep 17 00:00:00 2001 From: Matt Lanter Date: Thu, 13 Oct 2016 01:34:56 -0700 Subject: [PATCH 0123/1148] Add support for Google Maps on iOS, fix lints --- example/examples/ZIndexMarkers.js | 12 ++++++------ ios/AirGoogleMaps/AIRGoogleMapMarker.h | 1 + ios/AirGoogleMaps/AIRGoogleMapMarker.m | 6 ++++++ ios/AirGoogleMaps/AIRGoogleMapMarkerManager.m | 1 + 4 files changed, 14 insertions(+), 6 deletions(-) diff --git a/example/examples/ZIndexMarkers.js b/example/examples/ZIndexMarkers.js index c9e67cd5b..de96725cb 100644 --- a/example/examples/ZIndexMarkers.js +++ b/example/examples/ZIndexMarkers.js @@ -24,28 +24,28 @@ class ZIndexMarkers extends React.Component { constructor(props) { super(props); - let markerInfo = []; + const markerInfo = []; for (let i = 1; i < NUM_MARKERS; i++) { markerInfo.push({ - latitude: (Math.random() * 2 - 1) * MARKERS_LATITUDE_DELTA + LATITUDE, - longitude: (Math.random() * 2 - 1) * MARKERS_LONGITUDE_DELTA + LONGITUDE, + latitude: (((Math.random() * 2) - 1) * MARKERS_LATITUDE_DELTA) + LATITUDE, + longitude: (((Math.random() * 2) - 1) * MARKERS_LONGITUDE_DELTA) + LONGITUDE, isSpecial: Math.random() < PERCENT_SPECIAL_MARKERS, id: i, }); } this.state = { - markerInfo + markerInfo, }; } render() { - let markers = this.state.markerInfo.map((markerInfo) => { + const markers = this.state.markerInfo.map((markerInfo) => { return ( ); diff --git a/ios/AirGoogleMaps/AIRGoogleMapMarker.h b/ios/AirGoogleMaps/AIRGoogleMapMarker.h index db1c929b6..ff1a54508 100644 --- a/ios/AirGoogleMaps/AIRGoogleMapMarker.h +++ b/ios/AirGoogleMaps/AIRGoogleMapMarker.h @@ -26,6 +26,7 @@ @property (nonatomic, copy) NSString *title; @property (nonatomic, copy) NSString *subtitle; @property (nonatomic, strong) UIColor *pinColor; +@property (nonatomic, assign) NSInteger zIndex; @property (nonatomic, assign) BOOL draggable; - (void)showCalloutView; diff --git a/ios/AirGoogleMaps/AIRGoogleMapMarker.m b/ios/AirGoogleMaps/AIRGoogleMapMarker.m index 5c179e6aa..482197bf4 100644 --- a/ios/AirGoogleMaps/AIRGoogleMapMarker.m +++ b/ios/AirGoogleMaps/AIRGoogleMapMarker.m @@ -252,6 +252,12 @@ - (void)setPinColor:(UIColor *)pinColor { _realMarker.icon = [GMSMarker markerImageWithColor:pinColor]; } +- (void)setZIndex:(NSInteger)zIndex +{ + _zIndex = zIndex; + _realMarker.zIndex = (int)zIndex; +} + - (void)setDraggable:(BOOL)draggable { _realMarker.draggable = draggable; } diff --git a/ios/AirGoogleMaps/AIRGoogleMapMarkerManager.m b/ios/AirGoogleMaps/AIRGoogleMapMarkerManager.m index 43dfd900f..8e7c43622 100644 --- a/ios/AirGoogleMaps/AIRGoogleMapMarkerManager.m +++ b/ios/AirGoogleMaps/AIRGoogleMapMarkerManager.m @@ -33,6 +33,7 @@ - (UIView *)view RCT_EXPORT_VIEW_PROPERTY(title, NSString) RCT_REMAP_VIEW_PROPERTY(description, subtitle, NSString) RCT_EXPORT_VIEW_PROPERTY(pinColor, UIColor) +RCT_EXPORT_VIEW_PROPERTY(zIndex, NSInteger) RCT_EXPORT_VIEW_PROPERTY(draggable, BOOL) RCT_EXPORT_VIEW_PROPERTY(onDragStart, RCTDirectEventBlock) RCT_EXPORT_VIEW_PROPERTY(onDrag, RCTDirectEventBlock) From 40c5dd3fcd9c42dddd257600c7191f3192e1e9ba Mon Sep 17 00:00:00 2001 From: Matt Lanter Date: Thu, 13 Oct 2016 01:45:47 -0700 Subject: [PATCH 0124/1148] Fix lint --- example/examples/ZIndexMarkers.js | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/example/examples/ZIndexMarkers.js b/example/examples/ZIndexMarkers.js index de96725cb..78e3063d2 100644 --- a/example/examples/ZIndexMarkers.js +++ b/example/examples/ZIndexMarkers.js @@ -40,16 +40,14 @@ class ZIndexMarkers extends React.Component { } render() { - const markers = this.state.markerInfo.map((markerInfo) => { - return ( - - ); - }); + const markers = this.state.markerInfo.map((markerInfo) => + + ); return ( From cd2f6d99aced7c199298c1c8e4519124e3ea645e Mon Sep 17 00:00:00 2001 From: Matt Lanter Date: Thu, 13 Oct 2016 01:51:58 -0700 Subject: [PATCH 0125/1148] Fix other lints --- example/examples/CachedMap.js | 4 ++-- example/examples/LoadingMap.js | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/example/examples/CachedMap.js b/example/examples/CachedMap.js index f76ad3308..296e042d6 100644 --- a/example/examples/CachedMap.js +++ b/example/examples/CachedMap.js @@ -66,8 +66,8 @@ class CachedMap extends React.Component { cacheEnabled={this.state.cache} zoomEnabled scrollingEnabled - loadingIndicatorColor={"#666666"} - loadingBackgroundColor={"#eeeeee"} + loadingIndicatorColor="#666666" + loadingBackgroundColor="#eeeeee" > Date: Fri, 14 Oct 2016 16:27:02 -0700 Subject: [PATCH 0126/1148] Fixes crash during Activity onPause() --- .../android/react/maps/AirMapManager.java | 6 -- .../airbnb/android/react/maps/AirMapView.java | 81 +++++++------------ example/android/build.gradle | 2 +- 3 files changed, 32 insertions(+), 57 deletions(-) diff --git a/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java b/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java index b35737021..72d21a030 100644 --- a/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java +++ b/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java @@ -72,12 +72,6 @@ protected AirMapView createViewInstance(ThemedReactContext context) { return new AirMapView(context, this.appContext.getCurrentActivity(), this, this.googleMapOptions); } - @Override - public void onDropViewInstance(AirMapView view) { - view.doDestroy(); - super.onDropViewInstance(view); - } - private void emitMapError(String message, String type) { WritableMap error = Arguments.createMap(); error.putString("message", message); diff --git a/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java b/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java index 4a04af88a..97943956a 100644 --- a/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java +++ b/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java @@ -39,7 +39,6 @@ import com.google.android.gms.maps.model.LatLng; import com.google.android.gms.maps.model.LatLngBounds; import com.google.android.gms.maps.model.Marker; -import com.google.android.gms.maps.model.TileOverlay; import java.util.ArrayList; import java.util.Arrays; @@ -75,16 +74,16 @@ public class AirMapView extends MapView implements GoogleMap.InfoWindowAdapter, private final ScaleGestureDetector scaleDetector; private final GestureDetectorCompat gestureDetector; private final AirMapManager manager; - private LifecycleEventListener lifecycleListener; private boolean paused = false; private final ThemedReactContext context; private final EventDispatcher eventDispatcher; - public AirMapView(ThemedReactContext context, Context appContext, AirMapManager manager, GoogleMapOptions googleMapOptions) { + public AirMapView(ThemedReactContext reactContext, Context appContext, AirMapManager manager, + GoogleMapOptions googleMapOptions) { super(appContext, googleMapOptions); this.manager = manager; - this.context = context; + this.context = reactContext; super.onCreate(null); super.onResume(); @@ -92,7 +91,7 @@ public AirMapView(ThemedReactContext context, Context appContext, AirMapManager final AirMapView view = this; scaleDetector = - new ScaleGestureDetector(context, new ScaleGestureDetector.SimpleOnScaleGestureListener() { + new ScaleGestureDetector(reactContext, new ScaleGestureDetector.SimpleOnScaleGestureListener() { @Override public boolean onScaleBegin(ScaleGestureDetector detector) { view.startMonitoringRegion(); @@ -101,7 +100,7 @@ public boolean onScaleBegin(ScaleGestureDetector detector) { }); gestureDetector = - new GestureDetectorCompat(context, new GestureDetector.SimpleOnGestureListener() { + new GestureDetectorCompat(reactContext, new GestureDetector.SimpleOnGestureListener() { @Override public boolean onDoubleTap(MotionEvent e) { view.startMonitoringRegion(); @@ -122,13 +121,13 @@ public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, this.addOnLayoutChangeListener(new OnLayoutChangeListener() { @Override public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) { - if (!AirMapView.this.paused) { + if (!paused) { AirMapView.this.cacheView(); } } }); - eventDispatcher = context.getNativeModule(UIManagerModule.class).getEventDispatcher(); + eventDispatcher = reactContext.getNativeModule(UIManagerModule.class).getEventDispatcher(); } @Override @@ -222,36 +221,32 @@ public void onCameraChange(CameraPosition position) { // updating location constantly, killing the battery, even though some other location-mgmt // module may // desire to shut-down location-services. - lifecycleListener = new LifecycleEventListener() { - @Override - public void onHostResume() { - if (hasPermissions()) { - //noinspection MissingPermission - map.setMyLocationEnabled(showUserLocation); - } - synchronized (AirMapView.this) { - AirMapView.this.onResume(); - paused = false; - } - } + LifecycleEventListener lifecycleListener = new LifecycleEventListener() { + @Override + public void onHostResume() { + if (hasPermissions()) { + //noinspection MissingPermission + map.setMyLocationEnabled(showUserLocation); + } + synchronized (AirMapView.this) { + AirMapView.this.onResume(); + paused = false; + } + } - @Override - public void onHostPause() { - if (hasPermissions()) { - //noinspection MissingPermission - map.setMyLocationEnabled(false); - } - synchronized (AirMapView.this) { - AirMapView.this.onPause(); - paused = true; - } - } + @Override + public void onHostPause() { + if (hasPermissions()) { + //noinspection MissingPermission + map.setMyLocationEnabled(false); + } + paused = true; + } - @Override - public void onHostDestroy() { - AirMapView.this.doDestroy(); - } - }; + @Override + public void onHostDestroy() { + } + }; context.addLifecycleEventListener(lifecycleListener); } @@ -261,20 +256,6 @@ private boolean hasPermissions() { checkSelfPermission(getContext(), PERMISSIONS[1]) == PackageManager.PERMISSION_GRANTED; } - /* - onDestroy is final method so I can't override it. - */ - public synchronized void doDestroy() { - if (lifecycleListener != null) { - context.removeLifecycleEventListener(lifecycleListener); - lifecycleListener = null; - } - if (!paused) { - onPause(); - } - onDestroy(); - } - public void setRegion(ReadableMap region) { if (region == null) return; diff --git a/example/android/build.gradle b/example/android/build.gradle index cc73e1e1e..b249b0409 100644 --- a/example/android/build.gradle +++ b/example/android/build.gradle @@ -5,7 +5,7 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:2.2.0' + classpath 'com.android.tools.build:gradle:2.2.1' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files From 4cb998fb2c4f991a4e4bd89a8253089c5645af18 Mon Sep 17 00:00:00 2001 From: Spike Brehm Date: Fri, 14 Oct 2016 16:46:28 -0700 Subject: [PATCH 0127/1148] Update example app for 0.35.0 --- example/ios/Podfile.lock | 24 +++++++++++------------- example/package.json | 4 ++-- package.json | 2 +- 3 files changed, 14 insertions(+), 16 deletions(-) diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index a25a5caa3..5029967df 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -4,27 +4,25 @@ PODS: - GoogleMaps/Base (2.1.0) - GoogleMaps/Maps (2.1.0): - GoogleMaps/Base (= 2.1.0) - - React/Core (0.33.0): - - React/CSSLayout - - React/CSSLayout (0.33.0) - - React/RCTActionSheet (0.33.0): + - React/Core (0.35.0) + - React/RCTActionSheet (0.35.0): - React/Core - - React/RCTGeolocation (0.33.0): + - React/RCTGeolocation (0.35.0): - React/Core - - React/RCTImage (0.33.0): + - React/RCTImage (0.35.0): - React/Core - React/RCTNetwork - - React/RCTLinkingIOS (0.33.0): + - React/RCTLinkingIOS (0.35.0): - React/Core - - React/RCTNetwork (0.33.0): + - React/RCTNetwork (0.35.0): - React/Core - - React/RCTSettings (0.33.0): + - React/RCTSettings (0.35.0): - React/Core - - React/RCTText (0.33.0): + - React/RCTText (0.35.0): - React/Core - - React/RCTVibration (0.33.0): + - React/RCTVibration (0.35.0): - React/Core - - React/RCTWebSocket (0.33.0): + - React/RCTWebSocket (0.35.0): - React/Core DEPENDENCIES: @@ -46,6 +44,6 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: GoogleMaps: 06589b9a38097bce0cd6e90f0fd9b5e4b4a9344c - React: 46edc166689ba71b0b6cf11e64dbdb258d177089 + React: d80af5410aa500d0cb1bce2cc4493a584cf2ec92 COCOAPODS: 0.39.0 diff --git a/example/package.json b/example/package.json index 83ff86b95..a303d3cff 100644 --- a/example/package.json +++ b/example/package.json @@ -9,8 +9,8 @@ "dev": "concurrently 'npm run watch' 'npm run packager'" }, "dependencies": { - "react": "15.3.0", - "react-native": "0.33.0", + "react": "^15.3.1", + "react-native": "^0.35.0", "react-native-maps": "../" }, "devDependencies": { diff --git a/package.json b/package.json index fbd52827d..138054698 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,7 @@ "mapkit" ], "peerDependencies": { - "react": ">=15.3.0", + "react": ">=15.3.1", "react-native": ">=0.35" }, "devDependencies": { From 7dfdb77e99261a7a8d9ba8001e52b0c6a0f5b2c0 Mon Sep 17 00:00:00 2001 From: Spike Brehm Date: Fri, 14 Oct 2016 16:52:34 -0700 Subject: [PATCH 0128/1148] Fix bug in AIRGoogleMapMarker from RN 0.33->0.35 --- ios/AirGoogleMaps/AIRGoogleMapMarker.m | 1 + 1 file changed, 1 insertion(+) diff --git a/ios/AirGoogleMaps/AIRGoogleMapMarker.m b/ios/AirGoogleMaps/AIRGoogleMapMarker.m index 482197bf4..a31a13efc 100644 --- a/ios/AirGoogleMaps/AIRGoogleMapMarker.m +++ b/ios/AirGoogleMaps/AIRGoogleMapMarker.m @@ -188,6 +188,7 @@ - (void)setImageSrc:(NSString *)imageSrc clipped:YES resizeMode:RCTResizeModeCenter progressBlock:nil + partialLoadBlock:nil completionBlock:^(NSError *error, UIImage *image) { if (error) { // TODO(lmr): do something with the error? From 60afece8351690bfa81c16f3dd8eed0b88b316b8 Mon Sep 17 00:00:00 2001 From: James Hrisho Date: Sun, 16 Oct 2016 11:50:37 -0400 Subject: [PATCH 0129/1148] Update installation.md (#696) * Update installation.md * Adds note about usage of google api key. --- docs/installation.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/installation.md b/docs/installation.md index 5ece3c071..40cd3b9d9 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -76,7 +76,7 @@ After your `Podfile` is setup properly, run `pod install`. ``` 1. Specify your Google Maps API Key: - > To develop is recommended a ***Browser Key*** without refeer restriction. Go to https://console.developers.google.com/apis/credentials to check your credentials. + > For development, it is recommended to use a ***Browser Key*** without referrer restrictions. Go to https://console.developers.google.com/apis/credentials to check your credentials. Add your **Browser** API key to your manifest file (`android\app\src\main\AndroidManifest.xml`): @@ -88,7 +88,7 @@ After your `Podfile` is setup properly, run `pod install`. android:value="{{Your Google maps API Key Here}}"/> ``` - > If that doesn't work try using an ***Android Key*** without refeer restriction. Go to https://console.developers.google.com/apis/credentials to check your credentials. + > If that doesn't work, try using an ***Android Key*** without referrer restrictions. Go to https://console.developers.google.com/apis/credentials to check your credentials. Add your **Android** API key to your manifest file: @@ -100,6 +100,8 @@ After your `Podfile` is setup properly, run `pod install`. android:value="{{@string/ANDROID_GOOGLE_MAPS_API_KEY}}"/> ``` + > Note: As shown above, com.google.android.geo.API_KEY is the recommended metadata name for the API key. A key with this name can be used to authenticate to multiple Google Maps-based APIs on the Android platform, including the Google Maps Android API. For backwards compatibility, the API also supports the name com.google.android.maps.v2.API_KEY. This legacy name allows authentication to the Android Maps API v2 only. An application can specify only one of the API key metadata names. If both are specified, the API throws an exception. +Source: https://developers.google.com/maps/documentation/android-api/signup 1. Ensure that you have Google Play Services installed: * For Genymotion you can follow [these instructions](http://stackoverflow.com/a/20137324/1424349). From 12853f03686f7f8af11d853e629afcb8146e50c8 Mon Sep 17 00:00:00 2001 From: Spike Brehm Date: Sun, 16 Oct 2016 15:11:29 -0700 Subject: [PATCH 0130/1148] 0.11.0 --- CHANGELOG.md | 32 +++++++++++++++++++++++++++++++- android/gradle.properties | 2 +- package.json | 2 +- react-native-google-maps.podspec | 2 +- react-native-maps.podspec | 2 +- 5 files changed, 35 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ee1eeda15..a6ec8c208 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,36 @@ # Change Log -## 0.10.0 (October 10, 2016) +## 0.11.0 (October 16, 2016) + +### Breaking Changes + +* Update example app for RN 0.35, fix Gmaps bug for 0.35 + [#695](https://github.com/airbnb/react-native-maps/pull/695) + (@spikebrehm) +* Upgraded to RN 0.35 + [#680](https://github.com/airbnb/react-native-maps/pull/680) + (@eugenehp) + +### Patches + +* Update installation.md + [#696](https://github.com/airbnb/react-native-maps/pull/696) + (@securingsincity) +* [android] Fixes crash during Activity onPause() + [#694](https://github.com/airbnb/react-native-maps/pull/694) + (@felipecsl) +* Included MapUrlTile usage in README.md + [#687](https://github.com/airbnb/react-native-maps/pull/687) + (@ochanje210) +* [android] Add parameter to disable the moving on marker press + [#676](https://github.com/airbnb/react-native-maps/pull/676) + (@mlanter) +* Add support for setting zIndex on markers + [#675](https://github.com/airbnb/react-native-maps/pull/675) + (@mlanter) + + +## 0.10.1 (October 10, 2016) ### Patches diff --git a/android/gradle.properties b/android/gradle.properties index 78fc2b11d..ff024eb51 100644 --- a/android/gradle.properties +++ b/android/gradle.properties @@ -1,5 +1,5 @@ VERSION_CODE=2 -VERSION_NAME=0.10.1 +VERSION_NAME=0.11.0 GROUP=com.airbnb.android POM_DESCRIPTION=React Native Map view component for Android diff --git a/package.json b/package.json index 138054698..e611648f0 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "description": "React Native Mapview component for iOS + Android", "main": "index.js", "author": "Leland Richardson ", - "version": "0.10.1", + "version": "0.11.0", "scripts": { "start": "react-native start", "lint": "eslint ." diff --git a/react-native-google-maps.podspec b/react-native-google-maps.podspec index 3148c9238..f0b23a057 100644 --- a/react-native-google-maps.podspec +++ b/react-native-google-maps.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "react-native-google-maps" - s.version = "0.10.1" + s.version = "0.11.0" s.summary = "React Native Mapview component for iOS + Android" s.authors = { "intelligibabble" => "leland.m.richardson@gmail.com" } diff --git a/react-native-maps.podspec b/react-native-maps.podspec index c6843b48f..73607d2b0 100644 --- a/react-native-maps.podspec +++ b/react-native-maps.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "react-native-maps" - s.version = "0.10.1" + s.version = "0.11.0" s.summary = "React Native Mapview component for iOS + Android" s.authors = { "intelligibabble" => "leland.m.richardson@gmail.com" } From f67a6db19936800f4e8c329803597f589d5a902d Mon Sep 17 00:00:00 2001 From: Denis Date: Wed, 19 Oct 2016 20:07:43 +0300 Subject: [PATCH 0131/1148] Move Component API links to the top (#707) --- README.md | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 2b59aae3a..7b6d358ea 100644 --- a/README.md +++ b/README.md @@ -22,6 +22,20 @@ Since react-native 0.25.0, `React` should be required from `node_modules`. React Native versions from 0.18 should be working out of the box, for lower versions you should add `react` as a dependency in your `package.json`. +## Component API + +[`` Component API](docs/mapview.md) + +[`` Component API](docs/marker.md) + +[`` Component API](docs/callout.md) + +[`` Component API](docs/polygon.md) + +[`` Component API](docs/polyline.md) + +[`` Component API](docs/circle.md) + ## General Usage ```js @@ -272,21 +286,6 @@ Enable lite mode on Android with `liteMode` prop. Ideal when having multiple map ![](http://i.giphy.com/qZ2lAf18s89na.gif) -## Component API - -[`` Component API](docs/mapview.md) - -[`` Component API](docs/marker.md) - -[`` Component API](docs/callout.md) - -[`` Component API](docs/polygon.md) - -[`` Component API](docs/polyline.md) - -[`` Component API](docs/circle.md) - - ### Animated Region The MapView can accept an `MapView.AnimatedRegion` value as its `region` prop. This allows you to utilize the Animated API to control the map's center and zoom. From b9daf222ac824e734ec3033eec5861ebde3af13a Mon Sep 17 00:00:00 2001 From: Spike Brehm Date: Wed, 19 Oct 2016 17:39:30 -0700 Subject: [PATCH 0132/1148] [rn] Update changelog --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a6ec8c208..ecabd37a4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,6 +32,8 @@ ## 0.10.1 (October 10, 2016) +This release fixes issue [#656](https://github.com/airbnb/react-native-maps/issues/656) + ### Patches * [android] fix gradle build setup for explorer, bump to gradle 2.2.0 @@ -40,7 +42,6 @@ * [android] fix getAirMapName to fix ref-based commands [#665](https://github.com/airbnb/react-native-maps/pull/665) (@gilbox) -* Hopefully this release will fix issue [#656](https://github.com/airbnb/react-native-maps/issues/656) ## 0.10.0 (October 5, 2016) From d183c0ff5306b3cb00ed7aca65fb072540b3bae9 Mon Sep 17 00:00:00 2001 From: Julien Rodrigues Date: Mon, 24 Oct 2016 17:09:12 -0400 Subject: [PATCH 0133/1148] [iOS] Added showsUserLocation property support for Google Maps (#721) * Added suppport for the property showsUserLocation on iOS for GoogleMaps * CS fix --- ios/AirGoogleMaps/AIRGoogleMap.h | 1 + ios/AirGoogleMaps/AIRGoogleMap.m | 8 ++++++++ ios/AirGoogleMaps/AIRGoogleMapManager.m | 1 + 3 files changed, 10 insertions(+) diff --git a/ios/AirGoogleMaps/AIRGoogleMap.h b/ios/AirGoogleMaps/AIRGoogleMap.h index ae3b36d34..10a4f1f65 100644 --- a/ios/AirGoogleMaps/AIRGoogleMap.h +++ b/ios/AirGoogleMaps/AIRGoogleMap.h @@ -32,6 +32,7 @@ @property (nonatomic, assign) BOOL zoomEnabled; @property (nonatomic, assign) BOOL rotateEnabled; @property (nonatomic, assign) BOOL pitchEnabled; +@property (nonatomic, assign) BOOL showsUserLocation; - (BOOL)didTapMarker:(GMSMarker *)marker; - (void)didTapAtCoordinate:(CLLocationCoordinate2D)coordinate; diff --git a/ios/AirGoogleMaps/AIRGoogleMap.m b/ios/AirGoogleMaps/AIRGoogleMap.m index 3b4a00c50..c00b82b17 100644 --- a/ios/AirGoogleMaps/AIRGoogleMap.m +++ b/ios/AirGoogleMaps/AIRGoogleMap.m @@ -236,4 +236,12 @@ - (void)setShowsCompass:(BOOL)showsCompass { - (BOOL)showsCompass { return self.settings.compassButton; } + +- (void)setShowsUserLocation:(BOOL)showsUserLocation { + self.myLocationEnabled = showsUserLocation; +} + +- (BOOL)showsUserLocation { + return self.myLocationEnabled; +} @end diff --git a/ios/AirGoogleMaps/AIRGoogleMapManager.m b/ios/AirGoogleMaps/AIRGoogleMapManager.m index d42a29724..ffc9a47c7 100644 --- a/ios/AirGoogleMaps/AIRGoogleMapManager.m +++ b/ios/AirGoogleMaps/AIRGoogleMapManager.m @@ -54,6 +54,7 @@ - (UIView *)view RCT_EXPORT_VIEW_PROPERTY(rotateEnabled, BOOL) RCT_EXPORT_VIEW_PROPERTY(scrollEnabled, BOOL) RCT_EXPORT_VIEW_PROPERTY(pitchEnabled, BOOL) +RCT_EXPORT_VIEW_PROPERTY(showsUserLocation, BOOL) RCT_EXPORT_VIEW_PROPERTY(onPress, RCTBubblingEventBlock) RCT_EXPORT_VIEW_PROPERTY(onLongPress, RCTBubblingEventBlock) RCT_EXPORT_VIEW_PROPERTY(onChange, RCTBubblingEventBlock) From 16f362b64ed7691399396044f6d8b50c75db95bf Mon Sep 17 00:00:00 2001 From: Nick Italiano Date: Sun, 23 Oct 2016 17:22:56 -0700 Subject: [PATCH 0134/1148] Added ios google maps polygon, polyline, maptype support --- components/MapPolygon.js | 5 +- components/MapPolyline.js | 4 +- components/MapView.js | 11 +- example/App.js | 4 +- example/examples/PolygonCreator.js | 1 + .../AirMapsExplorer.xcodeproj/project.pbxproj | 250 +++++++++--------- example/ios/Podfile.lock | 4 +- ios/AirGoogleMaps/AIRGoogleMap.h | 2 + ios/AirGoogleMaps/AIRGoogleMap.m | 21 ++ ios/AirGoogleMaps/AIRGoogleMapManager.m | 2 + ios/AirGoogleMaps/AIRGoogleMapPolygon.h | 21 ++ ios/AirGoogleMaps/AIRGoogleMapPolygon.m | 64 +++++ .../AIRGoogleMapPolygonManager.h | 11 + .../AIRGoogleMapPolygonManager.m | 38 +++ ios/AirGoogleMaps/AIRGoogleMapPolyline.h | 22 ++ ios/AirGoogleMaps/AIRGoogleMapPolyline.m | 73 +++++ .../AIRGoogleMapPolylineManager.h | 11 + .../AIRGoogleMapPolylineManager.m | 39 +++ ios/AirGoogleMaps/RCTConvert+GMSMapViewType.h | 13 + ios/AirGoogleMaps/RCTConvert+GMSMapViewType.m | 21 ++ 20 files changed, 471 insertions(+), 146 deletions(-) create mode 100644 ios/AirGoogleMaps/AIRGoogleMapPolygon.h create mode 100644 ios/AirGoogleMaps/AIRGoogleMapPolygon.m create mode 100644 ios/AirGoogleMaps/AIRGoogleMapPolygonManager.h create mode 100644 ios/AirGoogleMaps/AIRGoogleMapPolygonManager.m create mode 100644 ios/AirGoogleMaps/AIRGoogleMapPolyline.h create mode 100644 ios/AirGoogleMaps/AIRGoogleMapPolyline.m create mode 100644 ios/AirGoogleMaps/AIRGoogleMapPolylineManager.h create mode 100644 ios/AirGoogleMaps/AIRGoogleMapPolylineManager.m create mode 100644 ios/AirGoogleMaps/RCTConvert+GMSMapViewType.h create mode 100644 ios/AirGoogleMaps/RCTConvert+GMSMapViewType.m diff --git a/components/MapPolygon.js b/components/MapPolygon.js index 979cd54f7..d04b7e0e3 100644 --- a/components/MapPolygon.js +++ b/components/MapPolygon.js @@ -4,7 +4,7 @@ import { } from 'react-native'; import decorateMapComponent, { USES_DEFAULT_IMPLEMENTATION, - NOT_SUPPORTED, + SUPPORTED, } from './decorateMapComponent'; const propTypes = { @@ -92,7 +92,6 @@ const propTypes = { * points on the Earth's surface. The geodesic curve is constructed assuming the Earth is * a sphere. * - * @platform android */ geodesic: PropTypes.bool, @@ -145,7 +144,7 @@ module.exports = decorateMapComponent(MapPolygon, { componentType: 'Polygon', providers: { google: { - ios: NOT_SUPPORTED, + ios: SUPPORTED, android: USES_DEFAULT_IMPLEMENTATION, }, }, diff --git a/components/MapPolyline.js b/components/MapPolyline.js index 067e706de..1dc253dff 100644 --- a/components/MapPolyline.js +++ b/components/MapPolyline.js @@ -4,7 +4,7 @@ import { } from 'react-native'; import decorateMapComponent, { USES_DEFAULT_IMPLEMENTATION, - NOT_SUPPORTED, + SUPPORTED, } from './decorateMapComponent'; const propTypes = { @@ -140,7 +140,7 @@ module.exports = decorateMapComponent(MapPolyline, { componentType: 'Polyline', providers: { google: { - ios: NOT_SUPPORTED, + ios: SUPPORTED, android: USES_DEFAULT_IMPLEMENTATION, }, }, diff --git a/components/MapView.js b/components/MapView.js index a7762665d..4267a475d 100644 --- a/components/MapView.js +++ b/components/MapView.js @@ -32,11 +32,6 @@ const MAP_TYPES = { NONE: 'none', }; -const ANDROID_ONLY_MAP_TYPES = [ - MAP_TYPES.TERRAIN, - MAP_TYPES.NONE, -]; - const viewConfig = { uiViewClassName: 'AIRMap', validAttributes: { @@ -208,7 +203,8 @@ const propTypes = { * - standard: standard road map (default) * - satellite: satellite view * - hybrid: satellite view with roads and points of interest overlayed - * - terrain: (Android only) topographic view + * - terrain: topographic view + * - none: no base map */ mapType: PropTypes.oneOf(Object.values(MAP_TYPES)), @@ -502,9 +498,6 @@ class MapView extends React.Component { onMapReady: this._onMapReady, onLayout: this._onLayout, }; - if (Platform.OS === 'ios' && ANDROID_ONLY_MAP_TYPES.includes(props.mapType)) { - props.mapType = MAP_TYPES.STANDARD; - } props.handlePanDrag = !!props.onPanDrag; } else { props = { diff --git a/example/App.js b/example/App.js index e927c4566..a53b5be16 100644 --- a/example/App.js +++ b/example/App.js @@ -124,8 +124,8 @@ class App extends React.Component { [EventListener, 'Events', true, '(incomplete)'], [MarkerTypes, 'Image Based Markers', true], [DraggableMarkers, 'Draggable Markers', true], - [PolygonCreator, 'Polygon Creator'], - [PolylineCreator, 'Polyline Creator'], + [PolygonCreator, 'Polygon Creator', true], + [PolylineCreator, 'Polyline Creator', true], [AnimatedViews, 'Animating with MapViews'], [AnimatedMarkers, 'Animated Marker Position'], [Callouts, 'Custom Callouts', true], diff --git a/example/examples/PolygonCreator.js b/example/examples/PolygonCreator.js index 605651c58..99b02809e 100644 --- a/example/examples/PolygonCreator.js +++ b/example/examples/PolygonCreator.js @@ -79,6 +79,7 @@ class PolygonCreator extends React.Component { this.onPress(e)} {...mapOptions} diff --git a/example/ios/AirMapsExplorer.xcodeproj/project.pbxproj b/example/ios/AirMapsExplorer.xcodeproj/project.pbxproj index 365d67b6e..ef5503872 100644 --- a/example/ios/AirMapsExplorer.xcodeproj/project.pbxproj +++ b/example/ios/AirMapsExplorer.xcodeproj/project.pbxproj @@ -11,13 +11,6 @@ 13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB11A68108700A75B9A /* LaunchScreen.xib */; }; 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; }; 13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; }; - 213CA8EA1D89F66A008623EC /* AIRGMSMarker.m in Sources */ = {isa = PBXBuildFile; fileRef = 213CA8DD1D89F66A008623EC /* AIRGMSMarker.m */; }; - 213CA8EB1D89F66A008623EC /* AIRGoogleMap.m in Sources */ = {isa = PBXBuildFile; fileRef = 213CA8DF1D89F66A008623EC /* AIRGoogleMap.m */; }; - 213CA8EC1D89F66A008623EC /* AIRGoogleMapCallout.m in Sources */ = {isa = PBXBuildFile; fileRef = 213CA8E11D89F66A008623EC /* AIRGoogleMapCallout.m */; }; - 213CA8ED1D89F66A008623EC /* AIRGoogleMapCalloutManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 213CA8E31D89F66A008623EC /* AIRGoogleMapCalloutManager.m */; }; - 213CA8EE1D89F66A008623EC /* AIRGoogleMapManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 213CA8E51D89F66A008623EC /* AIRGoogleMapManager.m */; }; - 213CA8EF1D89F66A008623EC /* AIRGoogleMapMarker.m in Sources */ = {isa = PBXBuildFile; fileRef = 213CA8E71D89F66A008623EC /* AIRGoogleMapMarker.m */; }; - 213CA8F01D89F66A008623EC /* AIRGoogleMapMarkerManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 213CA8E91D89F66A008623EC /* AIRGoogleMapMarkerManager.m */; }; 2166AB291D82EC56007538D7 /* AIRMap.m in Sources */ = {isa = PBXBuildFile; fileRef = 2166AAFC1D82EC56007538D7 /* AIRMap.m */; }; 2166AB2A1D82EC56007538D7 /* AIRMapCallout.m in Sources */ = {isa = PBXBuildFile; fileRef = 2166AAFE1D82EC56007538D7 /* AIRMapCallout.m */; }; 2166AB2B1D82EC56007538D7 /* AIRMapCalloutManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 2166AB001D82EC56007538D7 /* AIRMapCalloutManager.m */; }; @@ -33,14 +26,26 @@ 2166AB351D82EC56007538D7 /* AIRMapPolylineManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 2166AB141D82EC56007538D7 /* AIRMapPolylineManager.m */; }; 2166AB361D82EC56007538D7 /* SMCalloutView.m in Sources */ = {isa = PBXBuildFile; fileRef = 2166AB171D82EC56007538D7 /* SMCalloutView.m */; }; 2166AB3E1D82EC56007538D7 /* RCTConvert+MoreMapKit.m in Sources */ = {isa = PBXBuildFile; fileRef = 2166AB281D82EC56007538D7 /* RCTConvert+MoreMapKit.m */; }; - 21B248671DA4483D008FCB52 /* DummyView.m in Sources */ = {isa = PBXBuildFile; fileRef = 21B248661DA4483D008FCB52 /* DummyView.m */; }; 21D346651D933B8C002BAD8A /* AIRMapUrlTile.m in Sources */ = {isa = PBXBuildFile; fileRef = 21D346621D933B8C002BAD8A /* AIRMapUrlTile.m */; }; 21D346661D933B8C002BAD8A /* AIRMapUrlTileManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 21D346641D933B8C002BAD8A /* AIRMapUrlTileManager.m */; }; 21E6570A1D77591400B75EE5 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 21E657091D77591400B75EE5 /* SystemConfiguration.framework */; }; 21E6570C1D77591A00B75EE5 /* MobileCoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 21E6570B1D77591A00B75EE5 /* MobileCoreServices.framework */; }; 21E6570E1D77591F00B75EE5 /* MapKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 21E6570D1D77591F00B75EE5 /* MapKit.framework */; }; 21E657101D77594C00B75EE5 /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 21E6570F1D77594C00B75EE5 /* AudioToolbox.framework */; }; - C27EBA2BED74D74958F60ABC /* Pods_AirMapsExplorer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7C91D72410F775D78CACEBA8 /* Pods_AirMapsExplorer.framework */; }; + 8620CC871DBD814A00B79BFE /* AIRGMSMarker.m in Sources */ = {isa = PBXBuildFile; fileRef = 8620CC6E1DBD814A00B79BFE /* AIRGMSMarker.m */; }; + 8620CC881DBD814A00B79BFE /* AIRGoogleMap.m in Sources */ = {isa = PBXBuildFile; fileRef = 8620CC701DBD814A00B79BFE /* AIRGoogleMap.m */; }; + 8620CC891DBD814A00B79BFE /* AIRGoogleMapCallout.m in Sources */ = {isa = PBXBuildFile; fileRef = 8620CC721DBD814A00B79BFE /* AIRGoogleMapCallout.m */; }; + 8620CC8A1DBD814A00B79BFE /* AIRGoogleMapCalloutManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 8620CC741DBD814A00B79BFE /* AIRGoogleMapCalloutManager.m */; }; + 8620CC8B1DBD814A00B79BFE /* AIRGoogleMapManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 8620CC761DBD814A00B79BFE /* AIRGoogleMapManager.m */; }; + 8620CC8C1DBD814A00B79BFE /* AIRGoogleMapMarker.m in Sources */ = {isa = PBXBuildFile; fileRef = 8620CC781DBD814A00B79BFE /* AIRGoogleMapMarker.m */; }; + 8620CC8D1DBD814A00B79BFE /* AIRGoogleMapMarkerManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 8620CC7A1DBD814A00B79BFE /* AIRGoogleMapMarkerManager.m */; }; + 8620CC8E1DBD814A00B79BFE /* AIRGoogleMapPolygon.m in Sources */ = {isa = PBXBuildFile; fileRef = 8620CC7C1DBD814A00B79BFE /* AIRGoogleMapPolygon.m */; }; + 8620CC8F1DBD814A00B79BFE /* AIRGoogleMapPolygonManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 8620CC7E1DBD814A00B79BFE /* AIRGoogleMapPolygonManager.m */; }; + 8620CC901DBD814A00B79BFE /* AIRGoogleMapPolyline.m in Sources */ = {isa = PBXBuildFile; fileRef = 8620CC801DBD814A00B79BFE /* AIRGoogleMapPolyline.m */; }; + 8620CC911DBD814A00B79BFE /* AIRGoogleMapPolylineManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 8620CC821DBD814A00B79BFE /* AIRGoogleMapPolylineManager.m */; }; + 8620CC921DBD814A00B79BFE /* DummyView.m in Sources */ = {isa = PBXBuildFile; fileRef = 8620CC841DBD814A00B79BFE /* DummyView.m */; }; + 8620CC931DBD814A00B79BFE /* RCTConvert+GMSMapViewType.m in Sources */ = {isa = PBXBuildFile; fileRef = 8620CC861DBD814A00B79BFE /* RCTConvert+GMSMapViewType.m */; }; + C9315A21AD5A149EB5B40F29 /* Pods_AirMapsExplorer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 24EB66BA0860A4DCD4CA3D77 /* Pods_AirMapsExplorer.framework */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -63,20 +68,6 @@ 13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = AirMapsExplorer/Images.xcassets; sourceTree = ""; }; 13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = AirMapsExplorer/Info.plist; sourceTree = ""; }; 13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = AirMapsExplorer/main.m; sourceTree = ""; }; - 213CA8DC1D89F66A008623EC /* AIRGMSMarker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRGMSMarker.h; sourceTree = ""; }; - 213CA8DD1D89F66A008623EC /* AIRGMSMarker.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRGMSMarker.m; sourceTree = ""; }; - 213CA8DE1D89F66A008623EC /* AIRGoogleMap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRGoogleMap.h; sourceTree = ""; }; - 213CA8DF1D89F66A008623EC /* AIRGoogleMap.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRGoogleMap.m; sourceTree = ""; }; - 213CA8E01D89F66A008623EC /* AIRGoogleMapCallout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRGoogleMapCallout.h; sourceTree = ""; }; - 213CA8E11D89F66A008623EC /* AIRGoogleMapCallout.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRGoogleMapCallout.m; sourceTree = ""; }; - 213CA8E21D89F66A008623EC /* AIRGoogleMapCalloutManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRGoogleMapCalloutManager.h; sourceTree = ""; }; - 213CA8E31D89F66A008623EC /* AIRGoogleMapCalloutManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRGoogleMapCalloutManager.m; sourceTree = ""; }; - 213CA8E41D89F66A008623EC /* AIRGoogleMapManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRGoogleMapManager.h; sourceTree = ""; }; - 213CA8E51D89F66A008623EC /* AIRGoogleMapManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRGoogleMapManager.m; sourceTree = ""; }; - 213CA8E61D89F66A008623EC /* AIRGoogleMapMarker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRGoogleMapMarker.h; sourceTree = ""; }; - 213CA8E71D89F66A008623EC /* AIRGoogleMapMarker.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRGoogleMapMarker.m; sourceTree = ""; }; - 213CA8E81D89F66A008623EC /* AIRGoogleMapMarkerManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRGoogleMapMarkerManager.h; sourceTree = ""; }; - 213CA8E91D89F66A008623EC /* AIRGoogleMapMarkerManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRGoogleMapMarkerManager.m; sourceTree = ""; }; 2166AAF01D8233EC007538D7 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; 2166AAF21D8233F9007538D7 /* CoreLocation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreLocation.framework; path = System/Library/Frameworks/CoreLocation.framework; sourceTree = SDKROOT; }; 2166AAF41D823402007538D7 /* CoreText.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreText.framework; path = System/Library/Frameworks/CoreText.framework; sourceTree = SDKROOT; }; @@ -112,8 +103,6 @@ 2166AB171D82EC56007538D7 /* SMCalloutView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SMCalloutView.m; sourceTree = ""; }; 2166AB271D82EC56007538D7 /* RCTConvert+MoreMapKit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "RCTConvert+MoreMapKit.h"; sourceTree = ""; }; 2166AB281D82EC56007538D7 /* RCTConvert+MoreMapKit.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "RCTConvert+MoreMapKit.m"; sourceTree = ""; }; - 21B248661DA4483D008FCB52 /* DummyView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DummyView.m; sourceTree = ""; }; - 21B248681DA44851008FCB52 /* DummyView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DummyView.h; sourceTree = ""; }; 21D346611D933B8C002BAD8A /* AIRMapUrlTile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRMapUrlTile.h; sourceTree = ""; }; 21D346621D933B8C002BAD8A /* AIRMapUrlTile.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRMapUrlTile.m; sourceTree = ""; }; 21D346631D933B8C002BAD8A /* AIRMapUrlTileManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRMapUrlTileManager.h; sourceTree = ""; }; @@ -122,9 +111,35 @@ 21E6570B1D77591A00B75EE5 /* MobileCoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MobileCoreServices.framework; path = System/Library/Frameworks/MobileCoreServices.framework; sourceTree = SDKROOT; }; 21E6570D1D77591F00B75EE5 /* MapKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MapKit.framework; path = System/Library/Frameworks/MapKit.framework; sourceTree = SDKROOT; }; 21E6570F1D77594C00B75EE5 /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = System/Library/Frameworks/AudioToolbox.framework; sourceTree = SDKROOT; }; - 2451EE03458E9BDA5F49B446 /* Pods-AirMapsExplorer.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AirMapsExplorer.debug.xcconfig"; path = "Pods/Target Support Files/Pods-AirMapsExplorer/Pods-AirMapsExplorer.debug.xcconfig"; sourceTree = ""; }; - 39293F18DE5A673E1BD8D397 /* Pods-AirMapsExplorer.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AirMapsExplorer.release.xcconfig"; path = "Pods/Target Support Files/Pods-AirMapsExplorer/Pods-AirMapsExplorer.release.xcconfig"; sourceTree = ""; }; - 7C91D72410F775D78CACEBA8 /* Pods_AirMapsExplorer.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_AirMapsExplorer.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 24EB66BA0860A4DCD4CA3D77 /* Pods_AirMapsExplorer.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_AirMapsExplorer.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 309B9CD42BBCF38F87696E10 /* Pods-AirMapsExplorer.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AirMapsExplorer.release.xcconfig"; path = "Pods/Target Support Files/Pods-AirMapsExplorer/Pods-AirMapsExplorer.release.xcconfig"; sourceTree = ""; }; + 8620CC6D1DBD814A00B79BFE /* AIRGMSMarker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRGMSMarker.h; sourceTree = ""; }; + 8620CC6E1DBD814A00B79BFE /* AIRGMSMarker.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRGMSMarker.m; sourceTree = ""; }; + 8620CC6F1DBD814A00B79BFE /* AIRGoogleMap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRGoogleMap.h; sourceTree = ""; }; + 8620CC701DBD814A00B79BFE /* AIRGoogleMap.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRGoogleMap.m; sourceTree = ""; }; + 8620CC711DBD814A00B79BFE /* AIRGoogleMapCallout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRGoogleMapCallout.h; sourceTree = ""; }; + 8620CC721DBD814A00B79BFE /* AIRGoogleMapCallout.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRGoogleMapCallout.m; sourceTree = ""; }; + 8620CC731DBD814A00B79BFE /* AIRGoogleMapCalloutManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRGoogleMapCalloutManager.h; sourceTree = ""; }; + 8620CC741DBD814A00B79BFE /* AIRGoogleMapCalloutManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRGoogleMapCalloutManager.m; sourceTree = ""; }; + 8620CC751DBD814A00B79BFE /* AIRGoogleMapManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRGoogleMapManager.h; sourceTree = ""; }; + 8620CC761DBD814A00B79BFE /* AIRGoogleMapManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRGoogleMapManager.m; sourceTree = ""; }; + 8620CC771DBD814A00B79BFE /* AIRGoogleMapMarker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRGoogleMapMarker.h; sourceTree = ""; }; + 8620CC781DBD814A00B79BFE /* AIRGoogleMapMarker.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRGoogleMapMarker.m; sourceTree = ""; }; + 8620CC791DBD814A00B79BFE /* AIRGoogleMapMarkerManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRGoogleMapMarkerManager.h; sourceTree = ""; }; + 8620CC7A1DBD814A00B79BFE /* AIRGoogleMapMarkerManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRGoogleMapMarkerManager.m; sourceTree = ""; }; + 8620CC7B1DBD814A00B79BFE /* AIRGoogleMapPolygon.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRGoogleMapPolygon.h; sourceTree = ""; }; + 8620CC7C1DBD814A00B79BFE /* AIRGoogleMapPolygon.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRGoogleMapPolygon.m; sourceTree = ""; }; + 8620CC7D1DBD814A00B79BFE /* AIRGoogleMapPolygonManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRGoogleMapPolygonManager.h; sourceTree = ""; }; + 8620CC7E1DBD814A00B79BFE /* AIRGoogleMapPolygonManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRGoogleMapPolygonManager.m; sourceTree = ""; }; + 8620CC7F1DBD814A00B79BFE /* AIRGoogleMapPolyline.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRGoogleMapPolyline.h; sourceTree = ""; }; + 8620CC801DBD814A00B79BFE /* AIRGoogleMapPolyline.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRGoogleMapPolyline.m; sourceTree = ""; }; + 8620CC811DBD814A00B79BFE /* AIRGoogleMapPolylineManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRGoogleMapPolylineManager.h; sourceTree = ""; }; + 8620CC821DBD814A00B79BFE /* AIRGoogleMapPolylineManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRGoogleMapPolylineManager.m; sourceTree = ""; }; + 8620CC831DBD814A00B79BFE /* DummyView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DummyView.h; sourceTree = ""; }; + 8620CC841DBD814A00B79BFE /* DummyView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DummyView.m; sourceTree = ""; }; + 8620CC851DBD814A00B79BFE /* RCTConvert+GMSMapViewType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "RCTConvert+GMSMapViewType.h"; sourceTree = ""; }; + 8620CC861DBD814A00B79BFE /* RCTConvert+GMSMapViewType.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "RCTConvert+GMSMapViewType.m"; sourceTree = ""; }; + 86C3F1E16CFF1D84E5317F85 /* Pods-AirMapsExplorer.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AirMapsExplorer.debug.xcconfig"; path = "Pods/Target Support Files/Pods-AirMapsExplorer/Pods-AirMapsExplorer.debug.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -143,7 +158,7 @@ 21E6570E1D77591F00B75EE5 /* MapKit.framework in Frameworks */, 21E6570C1D77591A00B75EE5 /* MobileCoreServices.framework in Frameworks */, 21E6570A1D77591400B75EE5 /* SystemConfiguration.framework in Frameworks */, - C27EBA2BED74D74958F60ABC /* Pods_AirMapsExplorer.framework in Frameworks */, + C9315A21AD5A149EB5B40F29 /* Pods_AirMapsExplorer.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -162,11 +177,20 @@ 21E6570D1D77591F00B75EE5 /* MapKit.framework */, 21E6570B1D77591A00B75EE5 /* MobileCoreServices.framework */, 21E657091D77591400B75EE5 /* SystemConfiguration.framework */, - 7C91D72410F775D78CACEBA8 /* Pods_AirMapsExplorer.framework */, + 24EB66BA0860A4DCD4CA3D77 /* Pods_AirMapsExplorer.framework */, ); name = Frameworks; sourceTree = ""; }; + 075E864247A56626509A7315 /* Pods */ = { + isa = PBXGroup; + children = ( + 86C3F1E16CFF1D84E5317F85 /* Pods-AirMapsExplorer.debug.xcconfig */, + 309B9CD42BBCF38F87696E10 /* Pods-AirMapsExplorer.release.xcconfig */, + ); + name = Pods; + sourceTree = ""; + }; 13B07FAE1A68108700A75B9A /* AirMapsExplorer */ = { isa = PBXGroup; children = ( @@ -181,30 +205,6 @@ name = AirMapsExplorer; sourceTree = ""; }; - 213CA8DB1D89F66A008623EC /* AirGoogleMaps */ = { - isa = PBXGroup; - children = ( - 213CA8DC1D89F66A008623EC /* AIRGMSMarker.h */, - 213CA8DD1D89F66A008623EC /* AIRGMSMarker.m */, - 213CA8DE1D89F66A008623EC /* AIRGoogleMap.h */, - 213CA8DF1D89F66A008623EC /* AIRGoogleMap.m */, - 213CA8E01D89F66A008623EC /* AIRGoogleMapCallout.h */, - 213CA8E11D89F66A008623EC /* AIRGoogleMapCallout.m */, - 213CA8E21D89F66A008623EC /* AIRGoogleMapCalloutManager.h */, - 213CA8E31D89F66A008623EC /* AIRGoogleMapCalloutManager.m */, - 213CA8E41D89F66A008623EC /* AIRGoogleMapManager.h */, - 213CA8E51D89F66A008623EC /* AIRGoogleMapManager.m */, - 213CA8E61D89F66A008623EC /* AIRGoogleMapMarker.h */, - 213CA8E71D89F66A008623EC /* AIRGoogleMapMarker.m */, - 213CA8E81D89F66A008623EC /* AIRGoogleMapMarkerManager.h */, - 213CA8E91D89F66A008623EC /* AIRGoogleMapMarkerManager.m */, - 21B248661DA4483D008FCB52 /* DummyView.m */, - 21B248681DA44851008FCB52 /* DummyView.h */, - ); - name = AirGoogleMaps; - path = ../../ios/AirGoogleMaps; - sourceTree = ""; - }; 2166AAFA1D82EC56007538D7 /* AirMaps */ = { isa = PBXGroup; children = ( @@ -255,24 +255,23 @@ path = Callout; sourceTree = ""; }; - 76083FA9A1B0F1AEF4D2FCE7 /* Pods */ = { + 2BAA8C4A80B44CFBB3F83458 /* Libraries */ = { isa = PBXGroup; children = ( - 2451EE03458E9BDA5F49B446 /* Pods-AirMapsExplorer.debug.xcconfig */, - 39293F18DE5A673E1BD8D397 /* Pods-AirMapsExplorer.release.xcconfig */, ); - name = Pods; + name = Libraries; sourceTree = ""; }; 83CBB9F61A601CBA00E9B192 = { isa = PBXGroup; children = ( - 213CA8DB1D89F66A008623EC /* AirGoogleMaps */, + 8620CC6C1DBD814A00B79BFE /* AirGoogleMaps */, 2166AAFA1D82EC56007538D7 /* AirMaps */, 13B07FAE1A68108700A75B9A /* AirMapsExplorer */, 83CBBA001A601CBA00E9B192 /* Products */, - 76083FA9A1B0F1AEF4D2FCE7 /* Pods */, 051AB288C799B62BE091B88A /* Frameworks */, + 075E864247A56626509A7315 /* Pods */, + 2BAA8C4A80B44CFBB3F83458 /* Libraries */, ); indentWidth = 2; sourceTree = ""; @@ -287,6 +286,40 @@ name = Products; sourceTree = ""; }; + 8620CC6C1DBD814A00B79BFE /* AirGoogleMaps */ = { + isa = PBXGroup; + children = ( + 8620CC6D1DBD814A00B79BFE /* AIRGMSMarker.h */, + 8620CC6E1DBD814A00B79BFE /* AIRGMSMarker.m */, + 8620CC6F1DBD814A00B79BFE /* AIRGoogleMap.h */, + 8620CC701DBD814A00B79BFE /* AIRGoogleMap.m */, + 8620CC711DBD814A00B79BFE /* AIRGoogleMapCallout.h */, + 8620CC721DBD814A00B79BFE /* AIRGoogleMapCallout.m */, + 8620CC731DBD814A00B79BFE /* AIRGoogleMapCalloutManager.h */, + 8620CC741DBD814A00B79BFE /* AIRGoogleMapCalloutManager.m */, + 8620CC751DBD814A00B79BFE /* AIRGoogleMapManager.h */, + 8620CC761DBD814A00B79BFE /* AIRGoogleMapManager.m */, + 8620CC771DBD814A00B79BFE /* AIRGoogleMapMarker.h */, + 8620CC781DBD814A00B79BFE /* AIRGoogleMapMarker.m */, + 8620CC791DBD814A00B79BFE /* AIRGoogleMapMarkerManager.h */, + 8620CC7A1DBD814A00B79BFE /* AIRGoogleMapMarkerManager.m */, + 8620CC7B1DBD814A00B79BFE /* AIRGoogleMapPolygon.h */, + 8620CC7C1DBD814A00B79BFE /* AIRGoogleMapPolygon.m */, + 8620CC7D1DBD814A00B79BFE /* AIRGoogleMapPolygonManager.h */, + 8620CC7E1DBD814A00B79BFE /* AIRGoogleMapPolygonManager.m */, + 8620CC7F1DBD814A00B79BFE /* AIRGoogleMapPolyline.h */, + 8620CC801DBD814A00B79BFE /* AIRGoogleMapPolyline.m */, + 8620CC811DBD814A00B79BFE /* AIRGoogleMapPolylineManager.h */, + 8620CC821DBD814A00B79BFE /* AIRGoogleMapPolylineManager.m */, + 8620CC831DBD814A00B79BFE /* DummyView.h */, + 8620CC841DBD814A00B79BFE /* DummyView.m */, + 8620CC851DBD814A00B79BFE /* RCTConvert+GMSMapViewType.h */, + 8620CC861DBD814A00B79BFE /* RCTConvert+GMSMapViewType.m */, + ); + name = AirGoogleMaps; + path = ../../ios/AirGoogleMaps; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -312,16 +345,13 @@ isa = PBXNativeTarget; buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "AirMapsExplorer" */; buildPhases = ( - DEE1DC9F05F890EC3C87C39A /* Check Pods Manifest.lock */, - 53BB7F61AC8C3BE47A838FC0 /* 📦 Check Pods Manifest.lock */, + B27D5F0DA3595C3A8B5D31D9 /* [CP] Check Pods Manifest.lock */, 13B07F871A680F5B00A75B9A /* Sources */, 13B07F8C1A680F5B00A75B9A /* Frameworks */, 13B07F8E1A680F5B00A75B9A /* Resources */, 00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */, - D71F7E633EDE287637BD0861 /* 📦 Embed Pods Frameworks */, - 1ED7E90E82F1447B3BDF7F89 /* 📦 Copy Pods Resources */, - 39894B48A7C87B9F345BABA2 /* Embed Pods Frameworks */, - 82539956530080D9C27BC6A0 /* Copy Pods Resources */, + A4662ADFE799D81334C129C7 /* [CP] Embed Pods Frameworks */, + DD0B426CF8A839A0248EA8C7 /* [CP] Copy Pods Resources */, ); buildRules = ( ); @@ -338,7 +368,7 @@ 83CBB9F71A601CBA00E9B192 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0710; + LastUpgradeCheck = 710; ORGANIZATIONNAME = Facebook; TargetAttributes = { 00E356ED1AD99517003FC87E = { @@ -400,29 +430,14 @@ shellPath = /bin/sh; shellScript = "../node_modules/react-native/packager/react-native-xcode.sh"; }; - 1ED7E90E82F1447B3BDF7F89 /* 📦 Copy Pods Resources */ = { + A4662ADFE799D81334C129C7 /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); - name = "📦 Copy Pods Resources"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-AirMapsExplorer/Pods-AirMapsExplorer-resources.sh\"\n"; - showEnvVarsInLog = 0; - }; - 39894B48A7C87B9F345BABA2 /* Embed Pods Frameworks */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - name = "Embed Pods Frameworks"; + name = "[CP] Embed Pods Frameworks"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; @@ -430,29 +445,29 @@ shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-AirMapsExplorer/Pods-AirMapsExplorer-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; - 53BB7F61AC8C3BE47A838FC0 /* 📦 Check Pods Manifest.lock */ = { + B27D5F0DA3595C3A8B5D31D9 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); - name = "📦 Check Pods Manifest.lock"; + name = "[CP] Check Pods Manifest.lock"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n"; + shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n"; showEnvVarsInLog = 0; }; - 82539956530080D9C27BC6A0 /* Copy Pods Resources */ = { + DD0B426CF8A839A0248EA8C7 /* [CP] Copy Pods Resources */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); - name = "Copy Pods Resources"; + name = "[CP] Copy Pods Resources"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; @@ -460,36 +475,6 @@ shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-AirMapsExplorer/Pods-AirMapsExplorer-resources.sh\"\n"; showEnvVarsInLog = 0; }; - D71F7E633EDE287637BD0861 /* 📦 Embed Pods Frameworks */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - name = "📦 Embed Pods Frameworks"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-AirMapsExplorer/Pods-AirMapsExplorer-frameworks.sh\"\n"; - showEnvVarsInLog = 0; - }; - DEE1DC9F05F890EC3C87C39A /* Check Pods Manifest.lock */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - name = "Check Pods Manifest.lock"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n"; - showEnvVarsInLog = 0; - }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ @@ -504,30 +489,35 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 8620CC891DBD814A00B79BFE /* AIRGoogleMapCallout.m in Sources */, + 8620CC8D1DBD814A00B79BFE /* AIRGoogleMapMarkerManager.m in Sources */, + 8620CC881DBD814A00B79BFE /* AIRGoogleMap.m in Sources */, 2166AB2D1D82EC56007538D7 /* AIRMapCircleManager.m in Sources */, 21D346651D933B8C002BAD8A /* AIRMapUrlTile.m in Sources */, 2166AB2A1D82EC56007538D7 /* AIRMapCallout.m in Sources */, - 213CA8F01D89F66A008623EC /* AIRGoogleMapMarkerManager.m in Sources */, - 213CA8EF1D89F66A008623EC /* AIRGoogleMapMarker.m in Sources */, + 8620CC8E1DBD814A00B79BFE /* AIRGoogleMapPolygon.m in Sources */, + 8620CC8C1DBD814A00B79BFE /* AIRGoogleMapMarker.m in Sources */, + 8620CC8F1DBD814A00B79BFE /* AIRGoogleMapPolygonManager.m in Sources */, + 8620CC8A1DBD814A00B79BFE /* AIRGoogleMapCalloutManager.m in Sources */, + 8620CC8B1DBD814A00B79BFE /* AIRGoogleMapManager.m in Sources */, 2166AB2C1D82EC56007538D7 /* AIRMapCircle.m in Sources */, - 213CA8ED1D89F66A008623EC /* AIRGoogleMapCalloutManager.m in Sources */, + 8620CC871DBD814A00B79BFE /* AIRGMSMarker.m in Sources */, 21D346661D933B8C002BAD8A /* AIRMapUrlTileManager.m in Sources */, - 213CA8EC1D89F66A008623EC /* AIRGoogleMapCallout.m in Sources */, - 213CA8EB1D89F66A008623EC /* AIRGoogleMap.m in Sources */, + 8620CC931DBD814A00B79BFE /* RCTConvert+GMSMapViewType.m in Sources */, 2166AB301D82EC56007538D7 /* AIRMapMarker.m in Sources */, 2166AB321D82EC56007538D7 /* AIRMapPolygon.m in Sources */, 13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */, - 21B248671DA4483D008FCB52 /* DummyView.m in Sources */, 2166AB3E1D82EC56007538D7 /* RCTConvert+MoreMapKit.m in Sources */, 13B07FC11A68108700A75B9A /* main.m in Sources */, 2166AB331D82EC56007538D7 /* AIRMapPolygonManager.m in Sources */, - 213CA8EE1D89F66A008623EC /* AIRGoogleMapManager.m in Sources */, + 8620CC901DBD814A00B79BFE /* AIRGoogleMapPolyline.m in Sources */, 2166AB2B1D82EC56007538D7 /* AIRMapCalloutManager.m in Sources */, + 8620CC921DBD814A00B79BFE /* DummyView.m in Sources */, 2166AB361D82EC56007538D7 /* SMCalloutView.m in Sources */, 2166AB351D82EC56007538D7 /* AIRMapPolylineManager.m in Sources */, + 8620CC911DBD814A00B79BFE /* AIRGoogleMapPolylineManager.m in Sources */, 2166AB291D82EC56007538D7 /* AIRMap.m in Sources */, 2166AB2E1D82EC56007538D7 /* AIRMapCoordinate.m in Sources */, - 213CA8EA1D89F66A008623EC /* AIRGMSMarker.m in Sources */, 2166AB341D82EC56007538D7 /* AIRMapPolyline.m in Sources */, 2166AB2F1D82EC56007538D7 /* AIRMapManager.m in Sources */, 2166AB311D82EC56007538D7 /* AIRMapMarkerManager.m in Sources */, @@ -572,6 +562,7 @@ INFOPLIST_FILE = AirMapsExplorerTests/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 8.2; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + LIBRARY_SEARCH_PATHS = "$(inherited)"; PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/AirMapsExplorer.app/AirMapsExplorer"; @@ -590,6 +581,7 @@ INFOPLIST_FILE = AirMapsExplorerTests/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 8.2; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + LIBRARY_SEARCH_PATHS = "$(inherited)"; PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/AirMapsExplorer.app/AirMapsExplorer"; @@ -598,7 +590,7 @@ }; 13B07F941A680F5B00A75B9A /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 2451EE03458E9BDA5F49B446 /* Pods-AirMapsExplorer.debug.xcconfig */; + baseConfigurationReference = 86C3F1E16CFF1D84E5317F85 /* Pods-AirMapsExplorer.debug.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; DEAD_CODE_STRIPPING = NO; @@ -621,7 +613,7 @@ }; 13B07F951A680F5B00A75B9A /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 39293F18DE5A673E1BD8D397 /* Pods-AirMapsExplorer.release.xcconfig */; + baseConfigurationReference = 309B9CD42BBCF38F87696E10 /* Pods-AirMapsExplorer.release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; FRAMEWORK_SEARCH_PATHS = ( diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index 5029967df..1f4c2d9a6 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -46,4 +46,6 @@ SPEC CHECKSUMS: GoogleMaps: 06589b9a38097bce0cd6e90f0fd9b5e4b4a9344c React: d80af5410aa500d0cb1bce2cc4493a584cf2ec92 -COCOAPODS: 0.39.0 +PODFILE CHECKSUM: be65689c848eff5d4099a483239b72acab62f6a4 + +COCOAPODS: 1.1.1 diff --git a/ios/AirGoogleMaps/AIRGoogleMap.h b/ios/AirGoogleMaps/AIRGoogleMap.h index 10a4f1f65..f1b4e2a4f 100644 --- a/ios/AirGoogleMaps/AIRGoogleMap.h +++ b/ios/AirGoogleMaps/AIRGoogleMap.h @@ -24,6 +24,8 @@ @property (nonatomic, copy) RCTDirectEventBlock onRegionChange; @property (nonatomic, copy) RCTDirectEventBlock onRegionChangeComplete; @property (nonatomic, strong) NSMutableArray *markers; +@property (nonatomic, strong) NSMutableArray *polygons; +@property (nonatomic, strong) NSMutableArray *polylines; @property (nonatomic, assign) BOOL showsBuildings; @property (nonatomic, assign) BOOL showsTraffic; diff --git a/ios/AirGoogleMaps/AIRGoogleMap.m b/ios/AirGoogleMaps/AIRGoogleMap.m index c00b82b17..fc13f5761 100644 --- a/ios/AirGoogleMaps/AIRGoogleMap.m +++ b/ios/AirGoogleMaps/AIRGoogleMap.m @@ -7,6 +7,8 @@ #import "AIRGoogleMap.h" #import "AIRGoogleMapMarker.h" +#import "AIRGoogleMapPolygon.h" +#import "AIRGoogleMapPolyline.h" #import #import #import "RCTConvert+MapKit.h" @@ -73,6 +75,8 @@ - (instancetype)init if ((self = [super init])) { _reactSubviews = [NSMutableArray new]; _markers = [NSMutableArray array]; + _polygons = [NSMutableArray array]; + _polylines = [NSMutableArray array]; _initialRegionSet = false; } return self; @@ -102,6 +106,14 @@ - (void)insertReactSubview:(id)subview atIndex:(NSInteger)atIndex AIRGoogleMapMarker *marker = (AIRGoogleMapMarker*)subview; marker.realMarker.map = self; [self.markers addObject:marker]; + } else if ([subview isKindOfClass:[AIRGoogleMapPolygon class]]) { + AIRGoogleMapPolygon *polygon = (AIRGoogleMapPolygon*)subview; + polygon.polygon.map = self; + [self.polygons addObject:polygon]; + } else if ([subview isKindOfClass:[AIRGoogleMapPolyline class]]) { + AIRGoogleMapPolyline *polyline = (AIRGoogleMapPolyline*)subview; + polyline.polyline.map = self; + [self.polylines addObject:polyline]; } [_reactSubviews insertObject:(UIView *)subview atIndex:(NSUInteger) atIndex]; } @@ -117,6 +129,14 @@ - (void)removeReactSubview:(id)subview { AIRGoogleMapMarker *marker = (AIRGoogleMapMarker*)subview; marker.realMarker.map = nil; [self.markers removeObject:marker]; + } else if ([subview isKindOfClass:[AIRGoogleMapPolygon class]]) { + AIRGoogleMapPolygon *polygon = (AIRGoogleMapPolygon*)subview; + polygon.polygon.map = nil; + [self.polygons removeObject:polygon]; + } else if ([subview isKindOfClass:[AIRGoogleMapPolyline class]]) { + AIRGoogleMapPolyline *polyline = (AIRGoogleMapPolyline*)subview; + polyline.polyline.map = nil; + [self.polylines removeObject:polyline]; } [_reactSubviews removeObject:(UIView *)subview]; } @@ -244,4 +264,5 @@ - (void)setShowsUserLocation:(BOOL)showsUserLocation { - (BOOL)showsUserLocation { return self.myLocationEnabled; } + @end diff --git a/ios/AirGoogleMaps/AIRGoogleMapManager.m b/ios/AirGoogleMaps/AIRGoogleMapManager.m index ffc9a47c7..01735990c 100644 --- a/ios/AirGoogleMaps/AIRGoogleMapManager.m +++ b/ios/AirGoogleMaps/AIRGoogleMapManager.m @@ -12,6 +12,7 @@ #import "RCTUIManager.h" #import "RCTConvert+CoreLocation.h" #import "RCTConvert+MapKit.h" +#import "RCTConvert+GMSMapViewType.h" #import "RCTEventDispatcher.h" #import "AIRGoogleMap.h" #import "UIView+React.h" @@ -61,6 +62,7 @@ - (UIView *)view RCT_EXPORT_VIEW_PROPERTY(onMarkerPress, RCTDirectEventBlock) RCT_EXPORT_VIEW_PROPERTY(onRegionChange, RCTDirectEventBlock) RCT_EXPORT_VIEW_PROPERTY(onRegionChangeComplete, RCTDirectEventBlock) +RCT_EXPORT_VIEW_PROPERTY(mapType, GMSMapViewType) RCT_EXPORT_METHOD(fitToElements:(nonnull NSNumber *)reactTag animated:(BOOL)animated) diff --git a/ios/AirGoogleMaps/AIRGoogleMapPolygon.h b/ios/AirGoogleMaps/AIRGoogleMapPolygon.h new file mode 100644 index 000000000..26f0236d8 --- /dev/null +++ b/ios/AirGoogleMaps/AIRGoogleMapPolygon.h @@ -0,0 +1,21 @@ +// +// AIRGoogleMapPolygon.h +// +// Created by Nick Italiano on 10/22/16. +// + +#import +#import "AIRMapCoordinate.h" + +@interface AIRGoogleMapPolygon : UIView + +@property (nonatomic, strong) GMSPolygon *polygon; +@property (nonatomic, strong) NSArray *coordinates; + +@property (nonatomic, assign) UIColor *fillColor; +@property (nonatomic, assign) double strokeWidth; +@property (nonatomic, assign) UIColor *strokeColor; +@property (nonatomic, assign) BOOL geodesic; +@property (nonatomic, assign) int zIndex; + +@end diff --git a/ios/AirGoogleMaps/AIRGoogleMapPolygon.m b/ios/AirGoogleMaps/AIRGoogleMapPolygon.m new file mode 100644 index 000000000..8727cad37 --- /dev/null +++ b/ios/AirGoogleMaps/AIRGoogleMapPolygon.m @@ -0,0 +1,64 @@ +// +// AIRGoogleMapPolygon.m +// +// Created by Nick Italiano on 10/22/16. +// + +#import "AIRGoogleMapPolygon.h" +#import + +@implementation AIRGoogleMapPolygon + +- (instancetype)init +{ + if (self = [super init]) { + _polygon = [[GMSPolygon alloc] init]; + } + + return self; +} + +- (void)setCoordinates:(NSArray *)coordinates +{ + _coordinates = coordinates; + + GMSMutablePath *path = [GMSMutablePath path]; + for(int i = 0; i < coordinates.count; i++) + { + [path addCoordinate:coordinates[i].coordinate]; + } + + _polygon.path = path; +} + +-(void)setFillColor:(UIColor *)fillColor +{ + _fillColor = fillColor; + _polygon.fillColor = fillColor; +} + +-(void)setStrokeWidth:(double)strokeWidth +{ + _strokeWidth = strokeWidth; + _polygon.strokeWidth = strokeWidth; +} + +-(void)setStrokeColor:(UIColor *) strokeColor +{ + _strokeColor = strokeColor; + _polygon.strokeColor = strokeColor; +} + +-(void)setGeodesic:(BOOL)geodesic +{ + _geodesic = geodesic; + _polygon.geodesic = geodesic; +} + +-(void)setZIndex:(int)zIndex +{ + _zIndex = zIndex; + _polygon.zIndex = zIndex; +} + +@end diff --git a/ios/AirGoogleMaps/AIRGoogleMapPolygonManager.h b/ios/AirGoogleMaps/AIRGoogleMapPolygonManager.h new file mode 100644 index 000000000..fd6040ca0 --- /dev/null +++ b/ios/AirGoogleMaps/AIRGoogleMapPolygonManager.h @@ -0,0 +1,11 @@ +// +// AIRGoogleMapPolylgoneManager.h +// +// Created by Nick Italiano on 10/22/16. +// + +#import "RCTViewManager.h" + +@interface AIRGoogleMapPolygonManager : RCTViewManager + +@end diff --git a/ios/AirGoogleMaps/AIRGoogleMapPolygonManager.m b/ios/AirGoogleMaps/AIRGoogleMapPolygonManager.m new file mode 100644 index 000000000..5e6c8d319 --- /dev/null +++ b/ios/AirGoogleMaps/AIRGoogleMapPolygonManager.m @@ -0,0 +1,38 @@ +// +// AIRGoogleMapPolylgoneManager.m +// +// Created by Nick Italiano on 10/22/16. +// +#import "AIRGoogleMapPolygonManager.h" + +#import "RCTBridge.h" +#import "RCTConvert.h" +#import "RCTConvert+CoreLocation.h" +#import "RCTConvert+MoreMapKit.h" +#import "RCTEventDispatcher.h" +#import "UIView+React.h" +#import "RCTViewManager.h" +#import "AIRGoogleMapPolygon.h" + +@interface AIRGoogleMapPolygonManager() + +@end + +@implementation AIRGoogleMapPolygonManager + +RCT_EXPORT_MODULE() + +- (UIView *)view +{ + AIRGoogleMapPolygon *polygon = [AIRGoogleMapPolygon new]; + return polygon; +} + +RCT_EXPORT_VIEW_PROPERTY(coordinates, AIRMapCoordinateArray) +RCT_EXPORT_VIEW_PROPERTY(fillColor, UIColor) +RCT_EXPORT_VIEW_PROPERTY(strokeWidth, double) +RCT_EXPORT_VIEW_PROPERTY(strokeColor, UIColor) +RCT_EXPORT_VIEW_PROPERTY(geodesic, BOOL) +RCT_EXPORT_VIEW_PROPERTY(zIndex, int) + +@end diff --git a/ios/AirGoogleMaps/AIRGoogleMapPolyline.h b/ios/AirGoogleMaps/AIRGoogleMapPolyline.h new file mode 100644 index 000000000..b127567a5 --- /dev/null +++ b/ios/AirGoogleMaps/AIRGoogleMapPolyline.h @@ -0,0 +1,22 @@ +// +// AIRGoogleMapPolyline.h +// +// Created by Nick Italiano on 10/22/16. +// +#import +#import +#import "AIRMapCoordinate.h" +#import "AIRGoogleMapMarker.h" + +@interface AIRGoogleMapPolyline : UIView + +@property (nonatomic, strong) GMSPolyline* polyline; +@property (nonatomic, strong) NSArray *coordinates; +@property (nonatomic, strong) UIColor *strokeColor; +@property (nonatomic, assign) double strokeWidth; +@property (nonatomic, assign) UIColor *fillColor; +@property (nonatomic, assign) BOOL geodesic; +@property (nonatomic, assign) NSString *title; +@property (nonatomic, assign) int zIndex; + +@end diff --git a/ios/AirGoogleMaps/AIRGoogleMapPolyline.m b/ios/AirGoogleMaps/AIRGoogleMapPolyline.m new file mode 100644 index 000000000..c55621e97 --- /dev/null +++ b/ios/AirGoogleMaps/AIRGoogleMapPolyline.m @@ -0,0 +1,73 @@ +// +// AIRGoogleMapPolyline.m +// +// Created by Nick Italiano on 10/22/16. +// +#import +#import "AIRGoogleMapPolyline.h" +#import "AIRMapCoordinate.h" +#import "AIRGoogleMapMarker.h" +#import "AIRGoogleMapMarkerManager.h" +#import +#import "RCTUtils.h" + +@implementation AIRGoogleMapPolyline + +- (instancetype)init +{ + if (self = [super init]) { + _polyline = [[GMSPolyline alloc] init]; + } + return self; +} + +-(void)setCoordinates:(NSArray *)coordinates +{ + _coordinates = coordinates; + + GMSMutablePath *path = [GMSMutablePath path]; + for(int i = 0; i < coordinates.count; i++) + { + [path addCoordinate:coordinates[i].coordinate]; + } + + _polyline.path = path; +} + +-(void)setStrokeColor:(UIColor *)strokeColor +{ + _strokeColor = strokeColor; + _polyline.strokeColor = strokeColor; +} + +-(void)setStrokeWidth:(double)strokeWidth +{ + _strokeWidth = strokeWidth; + _polyline.strokeWidth = strokeWidth; +} + +-(void)setFillColor:(UIColor *)fillColor +{ + _fillColor = fillColor; + _polyline.spans = @[[GMSStyleSpan spanWithColor:fillColor]]; +} + +-(void)setGeodesic:(BOOL)geodesic +{ + _geodesic = geodesic; + _polyline.geodesic = geodesic; +} + +-(void)setTitle:(NSString *)title +{ + _title = title; + _polyline.title = _title; +} + +-(void) setZIndex:(int)zIndex +{ + _zIndex = zIndex; + _polyline.zIndex = zIndex; +} + +@end diff --git a/ios/AirGoogleMaps/AIRGoogleMapPolylineManager.h b/ios/AirGoogleMaps/AIRGoogleMapPolylineManager.h new file mode 100644 index 000000000..48aaf8527 --- /dev/null +++ b/ios/AirGoogleMaps/AIRGoogleMapPolylineManager.h @@ -0,0 +1,11 @@ +// +// AIRGoogleMapPolylineManager.h +// +// Created by Nick Italiano on 10/22/16. +// + +#import "RCTViewManager.h" + +@interface AIRGoogleMapPolylineManager : RCTViewManager + +@end diff --git a/ios/AirGoogleMaps/AIRGoogleMapPolylineManager.m b/ios/AirGoogleMaps/AIRGoogleMapPolylineManager.m new file mode 100644 index 000000000..68817b138 --- /dev/null +++ b/ios/AirGoogleMaps/AIRGoogleMapPolylineManager.m @@ -0,0 +1,39 @@ +// +// AIRGoogleMapPolylineManager.m +// +// Created by Nick Italiano on 10/22/16. +// + +#import "AIRGoogleMapPolylineManager.h" + +#import "RCTBridge.h" +#import "RCTConvert.h" +#import "RCTConvert+CoreLocation.h" +#import "RCTConvert+MoreMapKit.h" +#import "RCTEventDispatcher.h" +#import "UIView+React.h" +#import "RCTViewManager.h" +#import "AIRGoogleMapPolyline.h" + +@interface AIRGoogleMapPolylineManager() + +@end + +@implementation AIRGoogleMapPolylineManager + +RCT_EXPORT_MODULE() + +- (UIView *)view +{ + AIRGoogleMapPolyline *polyline = [AIRGoogleMapPolyline new]; + return polyline; +} + +RCT_EXPORT_VIEW_PROPERTY(coordinates, AIRMapCoordinateArray) +RCT_EXPORT_VIEW_PROPERTY(fillColor, UIColor) +RCT_EXPORT_VIEW_PROPERTY(strokeColor, UIColor) +RCT_EXPORT_VIEW_PROPERTY(strokeWidth, double) +RCT_EXPORT_VIEW_PROPERTY(geodesic, BOOL) +RCT_EXPORT_VIEW_PROPERTY(zIndex, int) + +@end diff --git a/ios/AirGoogleMaps/RCTConvert+GMSMapViewType.h b/ios/AirGoogleMaps/RCTConvert+GMSMapViewType.h new file mode 100644 index 000000000..a753f4331 --- /dev/null +++ b/ios/AirGoogleMaps/RCTConvert+GMSMapViewType.h @@ -0,0 +1,13 @@ +// +// RCTConvert+GMSMapViewType.h +// +// Created by Nick Italiano on 10/23/16. +// + +#import +#import +#import "RCTConvert.h" + +@interface RCTConvert (GMSMapViewType) + +@end diff --git a/ios/AirGoogleMaps/RCTConvert+GMSMapViewType.m b/ios/AirGoogleMaps/RCTConvert+GMSMapViewType.m new file mode 100644 index 000000000..42053fb1d --- /dev/null +++ b/ios/AirGoogleMaps/RCTConvert+GMSMapViewType.m @@ -0,0 +1,21 @@ +// +// RCTConvert+GMSMapViewType.m +// +// Created by Nick Italiano on 10/23/16. +// + +#import "RCTConvert+GMSMapViewType.h" +#import +#import "RCTConvert.h" + +@implementation RCTConvert (GMSMapViewType) + RCT_ENUM_CONVERTER(GMSMapViewType, + ( + @{ + @"standard": @(kGMSTypeNormal), + @"hybrid": @(kGMSTypeHybrid), + @"terrain": @(kGMSTypeTerrain), + @"none": @(kGMSTypeNone) + } + ), kGMSTypeTerrain, intValue) +@end From 0ce4b3eadee5634dfb916f4be87b5e49d3aba599 Mon Sep 17 00:00:00 2001 From: Nick Italiano Date: Mon, 24 Oct 2016 14:34:14 -0700 Subject: [PATCH 0135/1148] Fixed typo in google maps podspec --- react-native-google-maps.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/react-native-google-maps.podspec b/react-native-google-maps.podspec index f0b23a057..e306422cd 100644 --- a/react-native-google-maps.podspec +++ b/react-native-google-maps.podspec @@ -9,7 +9,7 @@ Pod::Spec.new do |s| s.platform = :ios, "8.0" s.source = { :git => "https://github.com/airbnb/react-native-maps.git" } - s.source_files = "ios/AirMaps/**/*.{h,m}" + s.source_files = "ios/AirGoogleMaps/**/*.{h,m}" s.dependency 'React' s.dependency 'GoogleMaps', '2.0.1' From 0d62312e37c6735daa642b3c1d7f2251493330f6 Mon Sep 17 00:00:00 2001 From: Nick Italiano Date: Mon, 24 Oct 2016 15:07:14 -0700 Subject: [PATCH 0136/1148] Added google map type only check --- components/MapView.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/components/MapView.js b/components/MapView.js index 4267a475d..2250d1591 100644 --- a/components/MapView.js +++ b/components/MapView.js @@ -32,6 +32,11 @@ const MAP_TYPES = { NONE: 'none', }; +const GOOGLE_MAPS_ONLY_TYPES = [ + MAP_TYPES.TERRAIN, + MAP_TYPES.NONE, +]; + const viewConfig = { uiViewClassName: 'AIRMap', validAttributes: { @@ -498,6 +503,10 @@ class MapView extends React.Component { onMapReady: this._onMapReady, onLayout: this._onLayout, }; + if (Platform.OS === 'ios' && props.provider === ProviderConstants.PROVIDER_DEFAULT + && GOOGLE_MAPS_ONLY_TYPES.includes(props.mapType)) { + props.mapType = MAP_TYPES.standard; + } props.handlePanDrag = !!props.onPanDrag; } else { props = { From 09b233001f61807261f9ea3c5707f9ec2804f95d Mon Sep 17 00:00:00 2001 From: Nick Italiano Date: Mon, 24 Oct 2016 18:20:41 -0700 Subject: [PATCH 0137/1148] Added ios google maps circle support --- components/MapCircle.js | 4 +- components/MapPolyline.js | 5 ++ example/App.js | 2 +- example/examples/Overlays.js | 4 +- .../AirMapsExplorer.xcodeproj/project.pbxproj | 12 ++++ ios/AirGoogleMaps/AIRGoogleMap.h | 1 + ios/AirGoogleMaps/AIRGoogleMap.m | 10 ++++ ios/AirGoogleMaps/AIRGoogleMapCircle.h | 20 +++++++ ios/AirGoogleMaps/AIRGoogleMapCircle.m | 57 +++++++++++++++++++ ios/AirGoogleMaps/AIRGoogleMapCircleManager.h | 11 ++++ ios/AirGoogleMaps/AIRGoogleMapCircleManager.m | 33 +++++++++++ 11 files changed, 155 insertions(+), 4 deletions(-) create mode 100644 ios/AirGoogleMaps/AIRGoogleMapCircle.h create mode 100644 ios/AirGoogleMaps/AIRGoogleMapCircle.m create mode 100644 ios/AirGoogleMaps/AIRGoogleMapCircleManager.h create mode 100644 ios/AirGoogleMaps/AIRGoogleMapCircleManager.m diff --git a/components/MapCircle.js b/components/MapCircle.js index 054cd2b6b..25c97a787 100644 --- a/components/MapCircle.js +++ b/components/MapCircle.js @@ -4,7 +4,7 @@ import { } from 'react-native'; import decorateMapComponent, { USES_DEFAULT_IMPLEMENTATION, - NOT_SUPPORTED, + SUPPORTED, } from './decorateMapComponent'; const propTypes = { @@ -140,7 +140,7 @@ module.exports = decorateMapComponent(MapCircle, { componentType: 'Circle', providers: { google: { - ios: NOT_SUPPORTED, + ios: SUPPORTED, android: USES_DEFAULT_IMPLEMENTATION, }, }, diff --git a/components/MapPolyline.js b/components/MapPolyline.js index 1dc253dff..684e1d71d 100644 --- a/components/MapPolyline.js +++ b/components/MapPolyline.js @@ -26,6 +26,11 @@ const propTypes = { */ onPress: PropTypes.func, + /** + * The fill color to use for the path. + */ + fillColor: PropTypes.string, + /** * The stroke width to use for the path. */ diff --git a/example/App.js b/example/App.js index a53b5be16..74631f451 100644 --- a/example/App.js +++ b/example/App.js @@ -129,7 +129,7 @@ class App extends React.Component { [AnimatedViews, 'Animating with MapViews'], [AnimatedMarkers, 'Animated Marker Position'], [Callouts, 'Custom Callouts', true], - [Overlays, 'Circles, Polygons, and Polylines', true, '(ios error)'], + [Overlays, 'Circles, Polygons, and Polylines', true], [DefaultMarkers, 'Default Markers', true], [CustomMarkers, 'Custom Markers', true], [TakeSnapshot, 'Take Snapshot', true, '(incomplete)'], diff --git a/example/examples/Overlays.js b/example/examples/Overlays.js index 8006abbbc..17a976014 100644 --- a/example/examples/Overlays.js +++ b/example/examples/Overlays.js @@ -82,8 +82,10 @@ class Overlays extends React.Component { #import #import "RCTConvert+MapKit.h" @@ -77,6 +78,7 @@ - (instancetype)init _markers = [NSMutableArray array]; _polygons = [NSMutableArray array]; _polylines = [NSMutableArray array]; + _circles = [NSMutableArray array]; _initialRegionSet = false; } return self; @@ -114,6 +116,10 @@ - (void)insertReactSubview:(id)subview atIndex:(NSInteger)atIndex AIRGoogleMapPolyline *polyline = (AIRGoogleMapPolyline*)subview; polyline.polyline.map = self; [self.polylines addObject:polyline]; + } else if ([subview isKindOfClass:[AIRGoogleMapCircle class]]) { + AIRGoogleMapCircle *circle = (AIRGoogleMapCircle*)subview; + circle.circle.map = self; + [self.circles addObject:circle]; } [_reactSubviews insertObject:(UIView *)subview atIndex:(NSUInteger) atIndex]; } @@ -137,6 +143,10 @@ - (void)removeReactSubview:(id)subview { AIRGoogleMapPolyline *polyline = (AIRGoogleMapPolyline*)subview; polyline.polyline.map = nil; [self.polylines removeObject:polyline]; + } else if ([subview isKindOfClass:[AIRGoogleMapCircle class]]) { + AIRGoogleMapCircle *circle = (AIRGoogleMapCircle*)subview; + circle.circle.map = nil; + [self.circles removeObject:circle]; } [_reactSubviews removeObject:(UIView *)subview]; } diff --git a/ios/AirGoogleMaps/AIRGoogleMapCircle.h b/ios/AirGoogleMaps/AIRGoogleMapCircle.h new file mode 100644 index 000000000..685cc649e --- /dev/null +++ b/ios/AirGoogleMaps/AIRGoogleMapCircle.h @@ -0,0 +1,20 @@ +// +// AIRGoogleMapsCircle.h +// +// Created by Nick Italiano on 10/24/16. +// + +#import +#import "AIRMapCoordinate.h" + +@interface AIRGoogleMapCircle : UIView + +@property (nonatomic, strong) GMSCircle *circle; +@property (nonatomic, assign) double radius; +@property (nonatomic, assign) CLLocationCoordinate2D centerCoordinate; +@property (nonatomic, assign) UIColor *strokeColor; +@property (nonatomic, assign) double strokeWidth; +@property (nonatomic, assign) UIColor *fillColor; +@property (nonatomic, assign) int zIndex; + +@end diff --git a/ios/AirGoogleMaps/AIRGoogleMapCircle.m b/ios/AirGoogleMaps/AIRGoogleMapCircle.m new file mode 100644 index 000000000..1698bee8c --- /dev/null +++ b/ios/AirGoogleMaps/AIRGoogleMapCircle.m @@ -0,0 +1,57 @@ +// +// AIRGoogleMapsCircle.m +// +// Created by Nick Italiano on 10/24/16. +// +#import +#import "AIRGoogleMapCircle.h" +#import +#import "RCTUtils.h" + +@implementation AIRGoogleMapCircle + +- (instancetype)init +{ + if (self = [super init]) { + _circle = [[GMSCircle alloc] init]; + } + return self; +} + +- (void)setRadius:(double)radius +{ + _radius = radius; + _circle.radius = radius; +} + +- (void)setCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate +{ + _centerCoordinate = centerCoordinate; + _circle.position = centerCoordinate; +} + +-(void)setStrokeColor:(UIColor *)strokeColor +{ + _strokeColor = strokeColor; + _circle.strokeColor = strokeColor; +} + +-(void)setStrokeWidth:(double)strokeWidth +{ + _strokeWidth = strokeWidth; + _circle.strokeWidth = strokeWidth; +} + +-(void)setFillColor:(UIColor *)fillColor +{ + _fillColor = fillColor; + _circle.fillColor = fillColor; +} + +-(void)setZIndex:(int)zIndex +{ + _zIndex = zIndex; + _circle.zIndex = zIndex; +} + +@end diff --git a/ios/AirGoogleMaps/AIRGoogleMapCircleManager.h b/ios/AirGoogleMaps/AIRGoogleMapCircleManager.h new file mode 100644 index 000000000..481b6d6c5 --- /dev/null +++ b/ios/AirGoogleMaps/AIRGoogleMapCircleManager.h @@ -0,0 +1,11 @@ +// +// AIRGoogleMapCircleManager.h +// +// Created by Nick Italiano on 10/24/16. +// + +#import "RCTViewManager.h" + +@interface AIRGoogleMapCircleManager : RCTViewManager + +@end diff --git a/ios/AirGoogleMaps/AIRGoogleMapCircleManager.m b/ios/AirGoogleMaps/AIRGoogleMapCircleManager.m new file mode 100644 index 000000000..62a164d22 --- /dev/null +++ b/ios/AirGoogleMaps/AIRGoogleMapCircleManager.m @@ -0,0 +1,33 @@ +// +// AIRGoogleMapCircleManager.m +// +// Created by Nick Italiano on 10/24/16. +// + +#import "AIRGoogleMapCircleManager.h" +#import "AIRGoogleMapCircle.h" +#import "RCTBridge.h" +#import "UIView+React.h" + +@interface AIRGoogleMapCircleManager() + +@end + +@implementation AIRGoogleMapCircleManager + +RCT_EXPORT_MODULE() + +- (UIView *)view +{ + AIRGoogleMapCircle *circle = [AIRGoogleMapCircle new]; + return circle; +} + +RCT_EXPORT_VIEW_PROPERTY(radius, double) +RCT_REMAP_VIEW_PROPERTY(center, centerCoordinate, CLLocationCoordinate2D) +RCT_EXPORT_VIEW_PROPERTY(strokeColor, UIColor) +RCT_EXPORT_VIEW_PROPERTY(strokeWidth, double) +RCT_EXPORT_VIEW_PROPERTY(fillColor, UIColor) +RCT_EXPORT_VIEW_PROPERTY(zIndex, int) + +@end From 561234ab50f7f32ce2347d70a2297762b95831f5 Mon Sep 17 00:00:00 2001 From: Benjamin Toueg Date: Wed, 26 Oct 2016 17:29:56 +0200 Subject: [PATCH 0138/1148] Fix Anchor point on Google Maps iOS --- docs/marker.md | 4 ++-- ios/AirGoogleMaps/AIRGoogleMapMarker.h | 1 + ios/AirGoogleMaps/AIRGoogleMapMarker.m | 9 ++++++--- ios/AirGoogleMaps/AIRGoogleMapMarkerManager.m | 1 + 4 files changed, 10 insertions(+), 5 deletions(-) diff --git a/docs/marker.md b/docs/marker.md index 557490ab4..60da4c0f7 100644 --- a/docs/marker.md +++ b/docs/marker.md @@ -9,9 +9,9 @@ | `image` | `ImageSource` | | A custom image to be used as the marker's icon. Only local image resources are allowed to be used. | `pinColor` | `Color` | | If no custom marker view or custom image is provided, the platform default pin will be used, which can be customized by this color. Ignored if a custom marker is being used. | `coordinate` | `LatLng` | | The coordinate for the marker. -| `centerOffset` | `Point` | | The offset (in points) at which to display the view.

By default, the center point of an annotation view is placed at the coordinate point of the associated annotation. You can use this property to reposition the annotation view as needed. This x and y offset values are measured in points. Positive offset values move the annotation view down and to the right, while negative values move it up and to the left.

For android, see the `anchor` prop. +| `centerOffset` | `Point` | | The offset (in points) at which to display the view.

By default, the center point of an annotation view is placed at the coordinate point of the associated annotation. You can use this property to reposition the annotation view as needed. This x and y offset values are measured in points. Positive offset values move the annotation view down and to the right, while negative values move it up and to the left.

For Google Maps, see the `anchor` prop. | `calloutOffset` | `Point` | | The offset (in points) at which to place the callout bubble.

This property determines the additional distance by which to move the callout bubble. When this property is set to (0, 0), the anchor point of the callout bubble is placed on the top-center point of the marker view’s frame. Specifying positive offset values moves the callout bubble down and to the right, while specifying negative values moves it up and to the left.

For android, see the `calloutAnchor` prop. -| `anchor` | `Point` | | Sets the anchor point for the marker.

The anchor specifies the point in the icon image that is anchored to the marker's position on the Earth's surface.

The anchor point is specified in the continuous space [0.0, 1.0] x [0.0, 1.0], where (0, 0) is the top-left corner of the image, and (1, 1) is the bottom-right corner. The anchoring point in a W x H image is the nearest discrete grid point in a (W + 1) x (H + 1) grid, obtained by scaling the then rounding. For example, in a 4 x 2 image, the anchor point (0.7, 0.6) resolves to the grid point at (3, 1).

For ios, see the `centerOffset` prop. +| `anchor` | `Point` | | Sets the anchor point for the marker.

The anchor specifies the point in the icon image that is anchored to the marker's position on the Earth's surface.

The anchor point is specified in the continuous space [0.0, 1.0] x [0.0, 1.0], where (0, 0) is the top-left corner of the image, and (1, 1) is the bottom-right corner. The anchoring point in a W x H image is the nearest discrete grid point in a (W + 1) x (H + 1) grid, obtained by scaling the then rounding. For example, in a 4 x 2 image, the anchor point (0.7, 0.6) resolves to the grid point at (3, 1).

For MapKit on iOS, see the `centerOffset` prop. | `calloutAnchor` | `Point` | | Specifies the point in the marker image at which to anchor the callout when it is displayed. This is specified in the same coordinate system as the anchor. See the `anchor` prop for more details.

The default is the top middle of the image.

For ios, see the `calloutOffset` prop. | `flat` | `Boolean` | | Sets whether this marker should be flat against the map true or a billboard facing the camera false. | `identifier` | `String` | | An identifier used to reference this marker at a later date. diff --git a/ios/AirGoogleMaps/AIRGoogleMapMarker.h b/ios/AirGoogleMaps/AIRGoogleMapMarker.h index ff1a54508..8f1018b05 100644 --- a/ios/AirGoogleMaps/AIRGoogleMapMarker.h +++ b/ios/AirGoogleMaps/AIRGoogleMapMarker.h @@ -26,6 +26,7 @@ @property (nonatomic, copy) NSString *title; @property (nonatomic, copy) NSString *subtitle; @property (nonatomic, strong) UIColor *pinColor; +@property (nonatomic, assign) CGPoint anchor; @property (nonatomic, assign) NSInteger zIndex; @property (nonatomic, assign) BOOL draggable; diff --git a/ios/AirGoogleMaps/AIRGoogleMapMarker.m b/ios/AirGoogleMaps/AIRGoogleMapMarker.m index a31a13efc..d9fa3eb44 100644 --- a/ios/AirGoogleMaps/AIRGoogleMapMarker.m +++ b/ios/AirGoogleMaps/AIRGoogleMapMarker.m @@ -225,9 +225,6 @@ - (void)setImageSrc:(NSString *)imageSrc _iconImageView = imageView; [self iconViewInsertSubview:imageView atIndex:0]; - - // TODO: This could be a prop - //_realMarker.groundAnchor = CGPointMake(0.75, 1); }); }]; } @@ -253,6 +250,12 @@ - (void)setPinColor:(UIColor *)pinColor { _realMarker.icon = [GMSMarker markerImageWithColor:pinColor]; } +- (void)setAnchor:(CGPoint)anchor { + _anchor = anchor; + _realMarker.groundAnchor = anchor; +} + + - (void)setZIndex:(NSInteger)zIndex { _zIndex = zIndex; diff --git a/ios/AirGoogleMaps/AIRGoogleMapMarkerManager.m b/ios/AirGoogleMaps/AIRGoogleMapMarkerManager.m index 8e7c43622..ee138c25f 100644 --- a/ios/AirGoogleMaps/AIRGoogleMapMarkerManager.m +++ b/ios/AirGoogleMaps/AIRGoogleMapMarkerManager.m @@ -33,6 +33,7 @@ - (UIView *)view RCT_EXPORT_VIEW_PROPERTY(title, NSString) RCT_REMAP_VIEW_PROPERTY(description, subtitle, NSString) RCT_EXPORT_VIEW_PROPERTY(pinColor, UIColor) +RCT_EXPORT_VIEW_PROPERTY(anchor, CGPoint) RCT_EXPORT_VIEW_PROPERTY(zIndex, NSInteger) RCT_EXPORT_VIEW_PROPERTY(draggable, BOOL) RCT_EXPORT_VIEW_PROPERTY(onDragStart, RCTDirectEventBlock) From c1a30fe04c477b475ac9b5981a71777f60f78275 Mon Sep 17 00:00:00 2001 From: Benjamin Toueg Date: Mon, 31 Oct 2016 19:33:43 +0100 Subject: [PATCH 0139/1148] Fix dynamic imageSrc removal, fix flicker in #738 (#737) --- ios/AirGoogleMaps/AIRGoogleMapMarker.m | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/ios/AirGoogleMaps/AIRGoogleMapMarker.m b/ios/AirGoogleMaps/AIRGoogleMapMarker.m index d9fa3eb44..a3bbbffc0 100644 --- a/ios/AirGoogleMaps/AIRGoogleMapMarker.m +++ b/ios/AirGoogleMaps/AIRGoogleMapMarker.m @@ -182,6 +182,18 @@ - (void)setImageSrc:(NSString *)imageSrc _reloadImageCancellationBlock = nil; } + if (!_imageSrc) { + if (_iconImageView) [_iconImageView removeFromSuperview]; + return; + } + + if (!_iconImageView) { + // prevent glitch with marker (cf. https://github.com/airbnb/react-native-maps/issues/738) + UIImageView *empyImageView = [[UIImageView alloc] init]; + _iconImageView = empyImageView; + [self iconViewInsertSubview:_iconImageView atIndex:0]; + } + _reloadImageCancellationBlock = [_bridge.imageLoader loadImageWithURLRequest:[RCTConvert NSURLRequest:_imageSrc] size:self.bounds.size scale:RCTScreenScale() From 2499f559c0c6d6c53d4c555b04d39ec0633da1ce Mon Sep 17 00:00:00 2001 From: Mike Lambert Date: Mon, 31 Oct 2016 16:32:56 -0400 Subject: [PATCH 0140/1148] If we've disabled scrolling within the map, then don't capture the touch events (#664) * If we've disabled scrolling within the map, then don't capture the touch events. This allows the containing scrollview to perform a scrollview scroll by dragging on the map. (Previously, the map would absorb the touches, and then not scroll the map *or* the scrollview, which was bad.) * Minor simplification --- .../main/java/com/airbnb/android/react/maps/AirMapView.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java b/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java index e381757c8..01fabe358 100644 --- a/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java +++ b/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java @@ -571,13 +571,15 @@ public boolean dispatchTouchEvent(MotionEvent ev) { switch (action) { case (MotionEvent.ACTION_DOWN): - this.getParent().requestDisallowInterceptTouchEvent(true); + this.getParent().requestDisallowInterceptTouchEvent( + map != null && map.getUiSettings().isScrollGesturesEnabled()); isTouchDown = true; break; case (MotionEvent.ACTION_MOVE): startMonitoringRegion(); break; case (MotionEvent.ACTION_UP): + // Clear this regardless, since isScrollGesturesEnabled() may have been updated this.getParent().requestDisallowInterceptTouchEvent(false); isTouchDown = false; break; From 71151c16c3487dc0d21d554f1c675e2517c27a36 Mon Sep 17 00:00:00 2001 From: Gil Birman Date: Mon, 31 Oct 2016 13:56:00 -0700 Subject: [PATCH 0141/1148] [ios][google] implement fitToSuppliedMarkers and fitToCoordinates (#750) --- example/App.js | 4 +- ios/AirGoogleMaps/AIRGoogleMapManager.m | 58 +++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 2 deletions(-) diff --git a/example/App.js b/example/App.js index 74631f451..cc7970d2b 100644 --- a/example/App.js +++ b/example/App.js @@ -135,8 +135,8 @@ class App extends React.Component { [TakeSnapshot, 'Take Snapshot', true, '(incomplete)'], [CachedMap, 'Cached Map'], [LoadingMap, 'Map with loading'], - [FitToSuppliedMarkers, 'Focus Map On Markers'], - [FitToCoordinates, 'Fit Map To Coordinates'], + [FitToSuppliedMarkers, 'Focus Map On Markers', true], + [FitToCoordinates, 'Fit Map To Coordinates', true], [LiteMapView, 'Android Lite MapView'], [CustomTiles, 'Custom Tiles'], [ZIndexMarkers, 'Position Markers with Z-index', true], diff --git a/ios/AirGoogleMaps/AIRGoogleMapManager.m b/ios/AirGoogleMaps/AIRGoogleMapManager.m index 01735990c..be2015835 100644 --- a/ios/AirGoogleMaps/AIRGoogleMapManager.m +++ b/ios/AirGoogleMaps/AIRGoogleMapManager.m @@ -85,6 +85,64 @@ - (UIView *)view }]; } +RCT_EXPORT_METHOD(fitToSuppliedMarkers:(nonnull NSNumber *)reactTag + markers:(nonnull NSArray *)markers + animated:(BOOL)animated) +{ + [self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary *viewRegistry) { + id view = viewRegistry[reactTag]; + if (![view isKindOfClass:[AIRGoogleMap class]]) { + RCTLogError(@"Invalid view returned from registry, expecting AIRGoogleMap, got: %@", view); + } else { + AIRGoogleMap *mapView = (AIRGoogleMap *)view; + + NSPredicate *filterMarkers = [NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary *bindings) { + AIRGoogleMapMarker *marker = (AIRGoogleMapMarker *)evaluatedObject; + return [marker isKindOfClass:[AIRGoogleMapMarker class]] && [markers containsObject:marker.identifier]; + }]; + + NSArray *filteredMarkers = [mapView.markers filteredArrayUsingPredicate:filterMarkers]; + + CLLocationCoordinate2D myLocation = ((AIRGoogleMapMarker *)(filteredMarkers.firstObject)).realMarker.position; + GMSCoordinateBounds *bounds = [[GMSCoordinateBounds alloc] initWithCoordinate:myLocation coordinate:myLocation]; + + for (AIRGoogleMapMarker *marker in filteredMarkers) + bounds = [bounds includingCoordinate:marker.realMarker.position]; + + [mapView animateWithCameraUpdate:[GMSCameraUpdate fitBounds:bounds withPadding:55.0f]]; + } + }]; +} + +RCT_EXPORT_METHOD(fitToCoordinates:(nonnull NSNumber *)reactTag + coordinates:(nonnull NSArray *)coordinates + edgePadding:(nonnull NSDictionary *)edgePadding + animated:(BOOL)animated) +{ + [self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary *viewRegistry) { + id view = viewRegistry[reactTag]; + if (![view isKindOfClass:[AIRGoogleMap class]]) { + RCTLogError(@"Invalid view returned from registry, expecting AIRGoogleMap, got: %@", view); + } else { + AIRGoogleMap *mapView = (AIRGoogleMap *)view; + + CLLocationCoordinate2D myLocation = coordinates.firstObject.coordinate; + GMSCoordinateBounds *bounds = [[GMSCoordinateBounds alloc] initWithCoordinate:myLocation coordinate:myLocation]; + + for (AIRMapCoordinate *coordinate in coordinates) + bounds = [bounds includingCoordinate:coordinate.coordinate]; + + // Set Map viewport + CGFloat top = [RCTConvert CGFloat:edgePadding[@"top"]]; + CGFloat right = [RCTConvert CGFloat:edgePadding[@"right"]]; + CGFloat bottom = [RCTConvert CGFloat:edgePadding[@"bottom"]]; + CGFloat left = [RCTConvert CGFloat:edgePadding[@"left"]]; + + [mapView animateWithCameraUpdate:[GMSCameraUpdate fitBounds:bounds withEdgeInsets:UIEdgeInsetsMake(top, left, bottom, right)]]; + } + }]; +} + RCT_EXPORT_METHOD(takeSnapshot:(nonnull NSNumber *)reactTag withWidth:(nonnull NSNumber *)width withHeight:(nonnull NSNumber *)height From 7a7ed5c3a8461d25fe0aadf60e82dbf105b8f741 Mon Sep 17 00:00:00 2001 From: Felipe Lima Date: Mon, 31 Oct 2016 15:07:39 -0700 Subject: [PATCH 0142/1148] Add latest patch releases to the changelog (#752) --- CHANGELOG.md | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ecabd37a4..763902cc6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,6 +29,37 @@ [#675](https://github.com/airbnb/react-native-maps/pull/675) (@mlanter) +## 0.10.4 (October 31, 2016) + +### Patches + +* [iOS] implement fitToSuppliedMarkers and fitToCoordinates for google maps + [#750](https://github.com/airbnb/react-native-maps/pull/750) + (@gilbox) +* [android] If we've disabled scrolling within the map, then don't capture the touch events + [#664](https://github.com/airbnb/react-native-maps/pull/664) + (@mikelambert) +* [iOS] Fix Anchor point on Google Maps iOS + [#734](https://github.com/airbnb/react-native-maps/pull/734) + (@btoueg) +* [iOS] Added showsUserLocation property support for Google Maps + [#721](https://github.com/airbnb/react-native-maps/pull/721) + (@julien-rodrigues) +* [iOS][android] Add support for setting zIndex on markers + [#675](https://github.com/airbnb/react-native-maps/pull/675) + (@mlanter) +* [android] Add parameter to disable the moving on marker press + [#676](https://github.com/airbnb/react-native-maps/pull/676) + (@mlanter) +* NOTE: v0.10.3 was not published + +## 0.10.2 (October 19, 2016) + +### Patches + +* [android] Fixes crash during Activity onPause() (fixes #414) + [#694](https://github.com/airbnb/react-native-maps/pull/694) + (@felipecsl) ## 0.10.1 (October 10, 2016) From 5a8f746a8340b7515a8aa100a921e81627a1d060 Mon Sep 17 00:00:00 2001 From: Mark Uretsky Date: Mon, 31 Oct 2016 23:25:19 +0100 Subject: [PATCH 0143/1148] Update installation.md (#742) unnecessary confusing curly brackets --- docs/installation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/installation.md b/docs/installation.md index 40cd3b9d9..8a1fb95ba 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -85,7 +85,7 @@ After your `Podfile` is setup properly, run `pod install`. + android:value="Your Google maps API Key Here"/> ``` > If that doesn't work, try using an ***Android Key*** without referrer restrictions. Go to https://console.developers.google.com/apis/credentials to check your credentials. From be00dfcdf6290bdf80fd8a83104a4a563e13bb81 Mon Sep 17 00:00:00 2001 From: mlanter Date: Mon, 31 Oct 2016 18:13:34 -0700 Subject: [PATCH 0144/1148] Use latest Google Play Services (#731) * Use latest Google Play Services * Use 9.6.1 explicitly --- android/build.gradle | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/android/build.gradle b/android/build.gradle index 9cef8f1d0..db87a71be 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -53,7 +53,7 @@ android { } dependencies { - compile 'com.facebook.react:react-native:+' - compile "com.google.android.gms:play-services-base:9.4.0" - compile 'com.google.android.gms:play-services-maps:9.4.0' + compile "com.facebook.react:react-native:+" + compile "com.google.android.gms:play-services-base:9.6.1" + compile "com.google.android.gms:play-services-maps:9.6.1" } From b12503c553b746fcf882de8af044769dd0adb8cb Mon Sep 17 00:00:00 2001 From: IjzerenHein Date: Tue, 1 Nov 2016 14:59:23 +0100 Subject: [PATCH 0145/1148] Improved code for takeSnapshot function (based on airbnb feedback) --- .../android/react/maps/AirMapModule.java | 68 ++++++++++--------- 1 file changed, 35 insertions(+), 33 deletions(-) diff --git a/android/src/main/java/com/airbnb/android/react/maps/AirMapModule.java b/android/src/main/java/com/airbnb/android/react/maps/AirMapModule.java index 08566d997..2cd1ba686 100644 --- a/android/src/main/java/com/airbnb/android/react/maps/AirMapModule.java +++ b/android/src/main/java/com/airbnb/android/react/maps/AirMapModule.java @@ -12,6 +12,9 @@ import java.io.OutputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.io.Closeable; + +import javax.annotation.Nullable; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactContextBaseJavaModule; @@ -44,6 +47,14 @@ public Activity getActivity() { return getCurrentActivity(); } + public static void closeQuietly(Closeable closeable) { + if (closeable == null) return; + try { + closeable.close(); + } catch (IOException ignored) { + } + } + @ReactMethod public void takeSnapshot(final int tag, final ReadableMap options, final Promise promise) { @@ -73,50 +84,41 @@ public void execute (NativeViewHierarchyManager nvhm) { return; } view.map.snapshot(new GoogleMap.SnapshotReadyCallback() { - public void onSnapshotReady(Bitmap snapshot) { + public void onSnapshotReady(@Nullable Bitmap snapshot) { // Convert image to requested width/height if neccesary - if (snapshot != null && width != 0 && height != 0 && (width != snapshot.getWidth() || height != snapshot.getHeight())) { - snapshot = Bitmap.createScaledBitmap(snapshot, width, height, true); - } if (snapshot == null) { - promise.reject("Failed to generate bitmap"); + promise.reject("Failed to generate bitmap, snapshot = null"); return; } + if ((width != 0) && (height != 0) && (width != snapshot.getWidth() || height != snapshot.getHeight())) { + snapshot = Bitmap.createScaledBitmap(snapshot, width, height, true); + } // Save the snapshot to disk - OutputStream outputStream = null; - try { - if (result.equals(SNAPSHOT_RESULT_FILE)) { - File tempFile = File.createTempFile("AirMapSnapshot", "." + format, context.getCacheDir()); + if (result.equals(SNAPSHOT_RESULT_FILE)) { + File tempFile; + FileOutputStream outputStream; + try { + tempFile = File.createTempFile("AirMapSnapshot", "." + format, context.getCacheDir()); outputStream = new FileOutputStream(tempFile); - snapshot.compress(compressFormat, (int)(100.0 * quality), outputStream); - outputStream.close(); - outputStream = null; - String uri = Uri.fromFile(tempFile).toString(); - promise.resolve(uri); } - else if (result.equals(SNAPSHOT_RESULT_BASE64)) { - outputStream = new ByteArrayOutputStream(); - snapshot.compress(compressFormat, (int)(100.0 * quality), outputStream); - outputStream.close(); - outputStream = null; - byte[] bytes = ((ByteArrayOutputStream) outputStream).toByteArray(); - String data = Base64.encodeToString(bytes, Base64.NO_WRAP); - promise.resolve(data); + catch (Exception e) { + promise.reject(e); + return; } + snapshot.compress(compressFormat, (int)(100.0 * quality), outputStream); + closeQuietly(outputStream); + String uri = Uri.fromFile(tempFile).toString(); + promise.resolve(uri); } - catch (Exception e) { - promise.reject(e); - } - finally { - if (outputStream != null) { - try { - outputStream.close(); - } catch (IOException e) { - e.printStackTrace(); - } - } + else if (result.equals(SNAPSHOT_RESULT_BASE64)) { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + snapshot.compress(compressFormat, (int)(100.0 * quality), outputStream); + closeQuietly(outputStream); + byte[] bytes = outputStream.toByteArray(); + String data = Base64.encodeToString(bytes, Base64.NO_WRAP); + promise.resolve(data); } } }); From 715939ed4ab9439e258d519ccb14c415072fbc6e Mon Sep 17 00:00:00 2001 From: Frank Rowe Date: Tue, 1 Nov 2016 14:42:48 -0400 Subject: [PATCH 0146/1148] add onPress for polygons and polylines on iOS and Android --- .../android/react/maps/AirMapPolygon.java | 1 + .../react/maps/AirMapPolygonManager.java | 14 +++ .../android/react/maps/AirMapPolyline.java | 1 + .../react/maps/AirMapPolylineManager.java | 14 +++ .../airbnb/android/react/maps/AirMapView.java | 28 +++++ ios/AirMaps/AIRMapManager.m | 119 ++++++++++++++++-- ios/AirMaps/AIRMapPolygon.h | 1 + ios/AirMaps/AIRMapPolygonManager.m | 5 +- ios/AirMaps/AIRMapPolyline.h | 1 + ios/AirMaps/AIRMapPolylineManager.m | 6 +- 10 files changed, 173 insertions(+), 17 deletions(-) diff --git a/android/src/main/java/com/airbnb/android/react/maps/AirMapPolygon.java b/android/src/main/java/com/airbnb/android/react/maps/AirMapPolygon.java index 166172795..226bc241c 100644 --- a/android/src/main/java/com/airbnb/android/react/maps/AirMapPolygon.java +++ b/android/src/main/java/com/airbnb/android/react/maps/AirMapPolygon.java @@ -102,6 +102,7 @@ public Object getFeature() { @Override public void addToMap(GoogleMap map) { polygon = map.addPolygon(getPolygonOptions()); + polygon.setClickable(true); } @Override diff --git a/android/src/main/java/com/airbnb/android/react/maps/AirMapPolygonManager.java b/android/src/main/java/com/airbnb/android/react/maps/AirMapPolygonManager.java index f08ce0289..6f55e5a6a 100644 --- a/android/src/main/java/com/airbnb/android/react/maps/AirMapPolygonManager.java +++ b/android/src/main/java/com/airbnb/android/react/maps/AirMapPolygonManager.java @@ -8,10 +8,15 @@ import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReadableArray; +import com.facebook.react.common.MapBuilder; import com.facebook.react.uimanager.ThemedReactContext; import com.facebook.react.uimanager.ViewGroupManager; import com.facebook.react.uimanager.annotations.ReactProp; +import java.util.HashMap; +import java.util.Map; +import javax.annotation.Nullable; + public class AirMapPolygonManager extends ViewGroupManager { private final DisplayMetrics metrics; @@ -67,4 +72,13 @@ public void setGeodesic(AirMapPolygon view, boolean geodesic) { public void setZIndex(AirMapPolygon view, float zIndex) { view.setZIndex(zIndex); } + + @Override + @Nullable + public Map getExportedCustomDirectEventTypeConstants() { + Map map = MapBuilder.of( + "onPress", MapBuilder.of("registrationName", "onPress") + ); + return map; + } } diff --git a/android/src/main/java/com/airbnb/android/react/maps/AirMapPolyline.java b/android/src/main/java/com/airbnb/android/react/maps/AirMapPolyline.java index cf15dfadf..9a15fdc99 100644 --- a/android/src/main/java/com/airbnb/android/react/maps/AirMapPolyline.java +++ b/android/src/main/java/com/airbnb/android/react/maps/AirMapPolyline.java @@ -92,6 +92,7 @@ public Object getFeature() { @Override public void addToMap(GoogleMap map) { polyline = map.addPolyline(getPolylineOptions()); + polyline.setClickable(true); } @Override diff --git a/android/src/main/java/com/airbnb/android/react/maps/AirMapPolylineManager.java b/android/src/main/java/com/airbnb/android/react/maps/AirMapPolylineManager.java index 89edc861e..74f81e999 100644 --- a/android/src/main/java/com/airbnb/android/react/maps/AirMapPolylineManager.java +++ b/android/src/main/java/com/airbnb/android/react/maps/AirMapPolylineManager.java @@ -8,10 +8,15 @@ import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReadableArray; +import com.facebook.react.common.MapBuilder; import com.facebook.react.uimanager.ThemedReactContext; import com.facebook.react.uimanager.ViewGroupManager; import com.facebook.react.uimanager.annotations.ReactProp; +import java.util.HashMap; +import java.util.Map; +import javax.annotation.Nullable; + public class AirMapPolylineManager extends ViewGroupManager { private final DisplayMetrics metrics; @@ -62,4 +67,13 @@ public void setGeodesic(AirMapPolyline view, boolean geodesic) { public void setZIndex(AirMapPolyline view, float zIndex) { view.setZIndex(zIndex); } + + @Override + @Nullable + public Map getExportedCustomDirectEventTypeConstants() { + Map map = MapBuilder.of( + "onPress", MapBuilder.of("registrationName", "onPress") + ); + return map; + } } diff --git a/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java b/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java index 01fabe358..aa1542c05 100644 --- a/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java +++ b/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java @@ -39,6 +39,8 @@ import com.google.android.gms.maps.model.LatLng; import com.google.android.gms.maps.model.LatLngBounds; import com.google.android.gms.maps.model.Marker; +import com.google.android.gms.maps.model.Polygon; +import com.google.android.gms.maps.model.Polyline; import java.util.ArrayList; import java.util.Arrays; @@ -72,6 +74,8 @@ public class AirMapView extends MapView implements GoogleMap.InfoWindowAdapter, private final List features = new ArrayList<>(); private final Map markerMap = new HashMap<>(); + private final Map polylineMap = new HashMap<>(); + private final Map polygonMap = new HashMap<>(); private final ScaleGestureDetector scaleDetector; private final GestureDetectorCompat gestureDetector; private final AirMapManager manager; @@ -165,6 +169,26 @@ public boolean onMarkerClick(Marker marker) { } }); + map.setOnPolygonClickListener(new GoogleMap.OnPolygonClickListener() { + @Override + public void onPolygonClick(Polygon polygon) { + WritableMap event; + event = makeClickEventData(polygon.getPoints().get(0)); + event.putString("action", "polygon-press"); + manager.pushEvent(polygonMap.get(polygon), "onPress", event); + } + }); + + map.setOnPolylineClickListener(new GoogleMap.OnPolylineClickListener() { + @Override + public void onPolylineClick(Polyline polyline) { + WritableMap event; + event = makeClickEventData(polyline.getPoints().get(0)); + event.putString("action", "polyline-press"); + manager.pushEvent(polylineMap.get(polyline), "onPress", event); + } + }); + map.setOnInfoWindowClickListener(new GoogleMap.OnInfoWindowClickListener() { @Override public void onInfoWindowClick(Marker marker) { @@ -381,10 +405,14 @@ public void addFeature(View child, int index) { AirMapPolyline polylineView = (AirMapPolyline) child; polylineView.addToMap(map); features.add(index, polylineView); + Polyline polyline = (Polyline) polylineView.getFeature(); + polylineMap.put(polyline, polylineView); } else if (child instanceof AirMapPolygon) { AirMapPolygon polygonView = (AirMapPolygon) child; polygonView.addToMap(map); features.add(index, polygonView); + Polygon polygon = (Polygon) polygonView.getFeature(); + polygonMap.put(polygon, polygonView); } else if (child instanceof AirMapCircle) { AirMapCircle circleView = (AirMapCircle) child; circleView.addToMap(map); diff --git a/ios/AirMaps/AIRMapManager.m b/ios/AirMaps/AIRMapManager.m index c45711c3f..a8ed23423 100644 --- a/ios/AirMaps/AIRMapManager.m +++ b/ios/AirMaps/AIRMapManager.m @@ -285,7 +285,7 @@ - (void)takeMapSnapshot:(AIRMap *)mapView [pin.image drawAtPoint:point]; } } - + for (id overlay in mapView.overlays) { if ([overlay respondsToSelector:@selector(drawToSnapshot:context:)]) { [overlay drawToSnapshot:snapshot context:UIGraphicsGetCurrentContext()]; @@ -308,21 +308,75 @@ - (void)takeMapSnapshot:(AIRMap *)mapView #pragma mark Gesture Recognizer Handlers +#define MAX_DISTANCE_PX 10.0f - (void)handleMapTap:(UITapGestureRecognizer *)recognizer { AIRMap *map = (AIRMap *)recognizer.view; - if (!map.onPress) return; - CGPoint touchPoint = [recognizer locationInView:map]; - CLLocationCoordinate2D coord = [map convertPoint:touchPoint toCoordinateFromView:map]; + CGPoint tapPoint = [recognizer locationInView:map]; + CLLocationCoordinate2D tapCoordinate = [map convertPoint:tapPoint toCoordinateFromView:map]; + MKMapPoint mapPoint = MKMapPointForCoordinate(tapCoordinate); + CGPoint mapPointAsCGP = CGPointMake(mapPoint.x, mapPoint.y); + + double maxMeters = [self metersFromPixel:MAX_DISTANCE_PX atPoint:tapPoint forMap:map]; + float nearestDistance = MAXFLOAT; + AIRMapPolyline *nearestPolyline = nil; + + for (id overlay in map.overlays) { + if([overlay isKindOfClass:[AIRMapPolygon class]]){ + AIRMapPolygon *polygon = (AIRMapPolygon*) overlay; + if (polygon.onPress) { + CGMutablePathRef mpr = CGPathCreateMutable(); + + for(int i = 0; i < polygon.coordinates.count; i++) { + AIRMapCoordinate *c = polygon.coordinates[i]; + MKMapPoint mp = MKMapPointForCoordinate(c.coordinate); + if (i == 0) { + CGPathMoveToPoint(mpr, NULL, mp.x, mp.y); + } else { + CGPathAddLineToPoint(mpr, NULL, mp.x, mp.y); + } + } + + if (CGPathContainsPoint(mpr, NULL, mapPointAsCGP, FALSE)) { + id event = @{ + @"action": @"polygon-press", + }; + polygon.onPress(event); + } + + CGPathRelease(mpr); + } + } + if([overlay isKindOfClass:[AIRMapPolyline class]]){ + AIRMapPolyline *polyline = (AIRMapPolyline*) overlay; + if (polyline.onPress) { + float distance = [self distanceOfPoint:MKMapPointForCoordinate(tapCoordinate) + toPoly:overlay]; + if (distance < nearestDistance) { + nearestDistance = distance; + nearestPolyline = overlay; + } + } + } + } + + if (nearestDistance <= maxMeters) { + id event = @{ + @"action": @"polyline-press", + }; + nearestPolyline.onPress(event); + } + + if (!map.onPress) return; map.onPress(@{ @"coordinate": @{ - @"latitude": @(coord.latitude), - @"longitude": @(coord.longitude), + @"latitude": @(tapCoordinate.latitude), + @"longitude": @(tapCoordinate.longitude), }, @"position": @{ - @"x": @(touchPoint.x), - @"y": @(touchPoint.y), + @"x": @(tapPoint.x), + @"y": @(tapPoint.y), }, }); @@ -609,4 +663,53 @@ - (void)_emitRegionChangeEvent:(AIRMap *)mapView continuous:(BOOL)continuous } } +/** Returns the distance of |pt| to |poly| in meters + * + * + */ +- (double)distanceOfPoint:(MKMapPoint)pt toPoly:(AIRMapPolyline *)poly +{ + double distance = MAXFLOAT; + for (int n = 0; n < poly.coordinates.count - 1; n++) { + + MKMapPoint ptA = MKMapPointForCoordinate(poly.coordinates[n].coordinate); + MKMapPoint ptB = MKMapPointForCoordinate(poly.coordinates[n + 1].coordinate); + + double xDelta = ptB.x - ptA.x; + double yDelta = ptB.y - ptA.y; + + if (xDelta == 0.0 && yDelta == 0.0) { + continue; + } + + double u = ((pt.x - ptA.x) * xDelta + (pt.y - ptA.y) * yDelta) / (xDelta * xDelta + yDelta * yDelta); + MKMapPoint ptClosest; + if (u < 0.0) { + ptClosest = ptA; + } + else if (u > 1.0) { + ptClosest = ptB; + } + else { + ptClosest = MKMapPointMake(ptA.x + u * xDelta, ptA.y + u * yDelta); + } + + distance = MIN(distance, MKMetersBetweenMapPoints(ptClosest, pt)); + } + + return distance; +} + + +/** Converts |px| to meters at location |pt| */ +- (double)metersFromPixel:(NSUInteger)px atPoint:(CGPoint)pt forMap:(AIRMap *)mapView +{ + CGPoint ptB = CGPointMake(pt.x + px, pt.y); + + CLLocationCoordinate2D coordA = [mapView convertPoint:pt toCoordinateFromView:mapView]; + CLLocationCoordinate2D coordB = [mapView convertPoint:ptB toCoordinateFromView:mapView]; + + return MKMetersBetweenMapPoints(MKMapPointForCoordinate(coordA), MKMapPointForCoordinate(coordB)); +} + @end diff --git a/ios/AirMaps/AIRMapPolygon.h b/ios/AirMaps/AIRMapPolygon.h index 4cb13a325..7c471b04c 100644 --- a/ios/AirMaps/AIRMapPolygon.h +++ b/ios/AirMaps/AIRMapPolygon.h @@ -32,6 +32,7 @@ @property (nonatomic, assign) CGLineJoin lineJoin; @property (nonatomic, assign) CGFloat lineDashPhase; @property (nonatomic, strong) NSArray *lineDashPattern; +@property (nonatomic, copy) RCTBubblingEventBlock onPress; #pragma mark MKOverlay protocol diff --git a/ios/AirMaps/AIRMapPolygonManager.m b/ios/AirMaps/AIRMapPolygonManager.m index 153a493d5..bfc253f6c 100644 --- a/ios/AirMaps/AIRMapPolygonManager.m +++ b/ios/AirMaps/AIRMapPolygonManager.m @@ -42,10 +42,7 @@ - (UIView *)view RCT_EXPORT_VIEW_PROPERTY(miterLimit, CGFloat) RCT_EXPORT_VIEW_PROPERTY(lineDashPhase, CGFloat) RCT_EXPORT_VIEW_PROPERTY(lineDashPattern, NSArray) +RCT_EXPORT_VIEW_PROPERTY(onPress, RCTBubblingEventBlock) -// NOTE(lmr): -// for now, onPress events for overlays will be left unimplemented. Seems it is possible with some work, but -// it is difficult to achieve in both ios and android so I decided to leave it out. -//RCT_EXPORT_VIEW_PROPERTY(onPress, RCTBubblingEventBlock) @end diff --git a/ios/AirMaps/AIRMapPolyline.h b/ios/AirMaps/AIRMapPolyline.h index 390a4a1ea..2e5b4e30a 100644 --- a/ios/AirMaps/AIRMapPolyline.h +++ b/ios/AirMaps/AIRMapPolyline.h @@ -31,6 +31,7 @@ @property (nonatomic, assign) CGLineJoin lineJoin; @property (nonatomic, assign) CGFloat lineDashPhase; @property (nonatomic, strong) NSArray *lineDashPattern; +@property (nonatomic, copy) RCTBubblingEventBlock onPress; #pragma mark MKOverlay protocol diff --git a/ios/AirMaps/AIRMapPolylineManager.m b/ios/AirMaps/AIRMapPolylineManager.m index 5f0b343d3..399b46d40 100644 --- a/ios/AirMaps/AIRMapPolylineManager.m +++ b/ios/AirMaps/AIRMapPolylineManager.m @@ -41,10 +41,6 @@ - (UIView *)view RCT_EXPORT_VIEW_PROPERTY(miterLimit, CGFloat) RCT_EXPORT_VIEW_PROPERTY(lineDashPhase, CGFloat) RCT_EXPORT_VIEW_PROPERTY(lineDashPattern, NSArray) - -// NOTE(lmr): -// for now, onPress events for overlays will be left unimplemented. Seems it is possible with some work, but -// it is difficult to achieve in both ios and android so I decided to leave it out. -//RCT_EXPORT_VIEW_PROPERTY(onPress, RCTBubblingEventBlock) +RCT_EXPORT_VIEW_PROPERTY(onPress, RCTBubblingEventBlock) @end From 27f9c30474f20c6911e9d6eade52fc5f11e4aa3a Mon Sep 17 00:00:00 2001 From: mlanter Date: Thu, 3 Nov 2016 18:36:06 -0700 Subject: [PATCH 0147/1148] [marker flicker] Fix flicker of map pins on state change (#728) --- components/decorateMapComponent.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/components/decorateMapComponent.js b/components/decorateMapComponent.js index 2f5e98de5..e655c4c33 100644 --- a/components/decorateMapComponent.js +++ b/components/decorateMapComponent.js @@ -48,8 +48,8 @@ export default function decorateMapComponent(Component, { componentType, provide if (components[provider]) return components[provider]; if (provider === PROVIDER_DEFAULT) { - components.default = getDefaultComponent(); - return components.default; + components[PROVIDER_DEFAULT] = getDefaultComponent(); + return components[PROVIDER_DEFAULT]; } const providerInfo = providers[provider]; @@ -62,8 +62,8 @@ export default function decorateMapComponent(Component, { componentType, provide components[provider] = requireNativeComponent(componentName, Component); } } else { // (platformSupport === USES_DEFAULT_IMPLEMENTATION) - if (!components.default) components.default = getDefaultComponent(); - components[provider] = components.default; + if (!components[PROVIDER_DEFAULT]) components[PROVIDER_DEFAULT] = getDefaultComponent(); + components[provider] = components[PROVIDER_DEFAULT]; } return components[provider]; From ef5e3b7fc6e1ec143c48df368789f2b24a0c69c2 Mon Sep 17 00:00:00 2001 From: Frank Rowe Date: Mon, 7 Nov 2016 15:28:18 -0500 Subject: [PATCH 0148/1148] updates --- .../com/airbnb/android/react/maps/AirMapPolygonManager.java | 3 +-- .../airbnb/android/react/maps/AirMapPolylineManager.java | 3 +-- .../main/java/com/airbnb/android/react/maps/AirMapView.java | 6 ++---- 3 files changed, 4 insertions(+), 8 deletions(-) diff --git a/android/src/main/java/com/airbnb/android/react/maps/AirMapPolygonManager.java b/android/src/main/java/com/airbnb/android/react/maps/AirMapPolygonManager.java index 6f55e5a6a..3eaa0e550 100644 --- a/android/src/main/java/com/airbnb/android/react/maps/AirMapPolygonManager.java +++ b/android/src/main/java/com/airbnb/android/react/maps/AirMapPolygonManager.java @@ -76,9 +76,8 @@ public void setZIndex(AirMapPolygon view, float zIndex) { @Override @Nullable public Map getExportedCustomDirectEventTypeConstants() { - Map map = MapBuilder.of( + return MapBuilder.of( "onPress", MapBuilder.of("registrationName", "onPress") ); - return map; } } diff --git a/android/src/main/java/com/airbnb/android/react/maps/AirMapPolylineManager.java b/android/src/main/java/com/airbnb/android/react/maps/AirMapPolylineManager.java index 74f81e999..c5afc61e0 100644 --- a/android/src/main/java/com/airbnb/android/react/maps/AirMapPolylineManager.java +++ b/android/src/main/java/com/airbnb/android/react/maps/AirMapPolylineManager.java @@ -71,9 +71,8 @@ public void setZIndex(AirMapPolyline view, float zIndex) { @Override @Nullable public Map getExportedCustomDirectEventTypeConstants() { - Map map = MapBuilder.of( + return MapBuilder.of( "onPress", MapBuilder.of("registrationName", "onPress") ); - return map; } } diff --git a/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java b/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java index aa1542c05..cb7e9fb6d 100644 --- a/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java +++ b/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java @@ -172,8 +172,7 @@ public boolean onMarkerClick(Marker marker) { map.setOnPolygonClickListener(new GoogleMap.OnPolygonClickListener() { @Override public void onPolygonClick(Polygon polygon) { - WritableMap event; - event = makeClickEventData(polygon.getPoints().get(0)); + WritableMap event = makeClickEventData(polygon.getPoints().get(0)); event.putString("action", "polygon-press"); manager.pushEvent(polygonMap.get(polygon), "onPress", event); } @@ -182,8 +181,7 @@ public void onPolygonClick(Polygon polygon) { map.setOnPolylineClickListener(new GoogleMap.OnPolylineClickListener() { @Override public void onPolylineClick(Polyline polyline) { - WritableMap event; - event = makeClickEventData(polyline.getPoints().get(0)); + WritableMap event = makeClickEventData(polyline.getPoints().get(0)); event.putString("action", "polyline-press"); manager.pushEvent(polylineMap.get(polyline), "onPress", event); } From b7146a8a612140e667018340f2bf6d23ff283e7a Mon Sep 17 00:00:00 2001 From: gilbox Date: Thu, 10 Nov 2016 11:45:29 -0800 Subject: [PATCH 0149/1148] [RN][iOS][google] Set region only when view has width&height - Fix type issue in AIRMapManager - Setup Gemfile in example/ios dir to avoid problems with different versions of cocoapods - Update examples-setup.md to use bundler - Change MapView so that we only set the native region prop when there is a width and height. GoogleMaps iOS requires the width and height to properly calculate the map zoom level. --- components/MapView.js | 11 +-- docs/examples-setup.md | 13 +++- .../AirMapsExplorer.xcodeproj/project.pbxproj | 56 +++++++------- example/ios/Gemfile | 2 + example/ios/Gemfile.lock | 73 +++++++++++++++++++ ios/AirMaps/AIRMapManager.m | 4 +- 6 files changed, 117 insertions(+), 42 deletions(-) create mode 100644 example/ios/Gemfile create mode 100644 example/ios/Gemfile.lock diff --git a/components/MapView.js b/components/MapView.js index 2250d1591..74571e180 100644 --- a/components/MapView.js +++ b/components/MapView.js @@ -371,15 +371,6 @@ class MapView extends React.Component { return { provider: this.props.provider }; } - componentDidMount() { - const { region, initialRegion } = this.props; - if (region && this.state.isReady) { - this.map.setNativeProps({ region }); - } else if (initialRegion && this.state.isReady) { - this.map.setNativeProps({ region: initialRegion }); - } - } - componentWillUpdate(nextProps) { const a = this.__lastRegion; const b = nextProps.region; @@ -407,6 +398,8 @@ class MapView extends React.Component { _onLayout(e) { const { region, initialRegion, onLayout } = this.props; const { isReady } = this.state; + const { layout } = e.nativeEvent; + if (!layout.width || !layout.height) return; if (region && isReady && !this.__layoutCalled) { this.__layoutCalled = true; this.map.setNativeProps({ region }); diff --git a/docs/examples-setup.md b/docs/examples-setup.md index 35a8e6942..8599a2f15 100644 --- a/docs/examples-setup.md +++ b/docs/examples-setup.md @@ -2,17 +2,24 @@ ## iOS -1. Install dependencies and open the workspace: +1. If you don't have bundler gem installed: + +``` +gem install bundler +``` + +2. Install dependencies and open the workspace: ``` cd example npm install cd ios -pod install +bundle install +bundle exec pod install open AirMapsExplorer.xcworkspace ``` -2. Make sure the `AirMapsExplorer` target is selected and click `Run` +3. Make sure the `AirMapsExplorer` target is selected and click `Run` ## android diff --git a/example/ios/AirMapsExplorer.xcodeproj/project.pbxproj b/example/ios/AirMapsExplorer.xcodeproj/project.pbxproj index 7ae27bb68..84761f0be 100644 --- a/example/ios/AirMapsExplorer.xcodeproj/project.pbxproj +++ b/example/ios/AirMapsExplorer.xcodeproj/project.pbxproj @@ -32,6 +32,7 @@ 21E6570C1D77591A00B75EE5 /* MobileCoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 21E6570B1D77591A00B75EE5 /* MobileCoreServices.framework */; }; 21E6570E1D77591F00B75EE5 /* MapKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 21E6570D1D77591F00B75EE5 /* MapKit.framework */; }; 21E657101D77594C00B75EE5 /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 21E6570F1D77594C00B75EE5 /* AudioToolbox.framework */; }; + 3E4E0B5921E01BC4043FD8CD /* Pods_AirMapsExplorer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3591658C00398534590C8751 /* Pods_AirMapsExplorer.framework */; }; 8620CC871DBD814A00B79BFE /* AIRGMSMarker.m in Sources */ = {isa = PBXBuildFile; fileRef = 8620CC6E1DBD814A00B79BFE /* AIRGMSMarker.m */; }; 8620CC881DBD814A00B79BFE /* AIRGoogleMap.m in Sources */ = {isa = PBXBuildFile; fileRef = 8620CC701DBD814A00B79BFE /* AIRGoogleMap.m */; }; 8620CC891DBD814A00B79BFE /* AIRGoogleMapCallout.m in Sources */ = {isa = PBXBuildFile; fileRef = 8620CC721DBD814A00B79BFE /* AIRGoogleMapCallout.m */; }; @@ -47,7 +48,6 @@ 8620CC931DBD814A00B79BFE /* RCTConvert+GMSMapViewType.m in Sources */ = {isa = PBXBuildFile; fileRef = 8620CC861DBD814A00B79BFE /* RCTConvert+GMSMapViewType.m */; }; 8697D6221DBEDE6100DB7D0F /* AIRGoogleMapCircle.m in Sources */ = {isa = PBXBuildFile; fileRef = 8697D6211DBEDE6100DB7D0F /* AIRGoogleMapCircle.m */; }; 8697D6251DBEE22B00DB7D0F /* AIRGoogleMapCircleManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 8697D6241DBEE22B00DB7D0F /* AIRGoogleMapCircleManager.m */; }; - C9315A21AD5A149EB5B40F29 /* Pods_AirMapsExplorer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 24EB66BA0860A4DCD4CA3D77 /* Pods_AirMapsExplorer.framework */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -113,8 +113,7 @@ 21E6570B1D77591A00B75EE5 /* MobileCoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MobileCoreServices.framework; path = System/Library/Frameworks/MobileCoreServices.framework; sourceTree = SDKROOT; }; 21E6570D1D77591F00B75EE5 /* MapKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MapKit.framework; path = System/Library/Frameworks/MapKit.framework; sourceTree = SDKROOT; }; 21E6570F1D77594C00B75EE5 /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = System/Library/Frameworks/AudioToolbox.framework; sourceTree = SDKROOT; }; - 24EB66BA0860A4DCD4CA3D77 /* Pods_AirMapsExplorer.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_AirMapsExplorer.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 309B9CD42BBCF38F87696E10 /* Pods-AirMapsExplorer.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AirMapsExplorer.release.xcconfig"; path = "Pods/Target Support Files/Pods-AirMapsExplorer/Pods-AirMapsExplorer.release.xcconfig"; sourceTree = ""; }; + 3591658C00398534590C8751 /* Pods_AirMapsExplorer.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_AirMapsExplorer.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 8620CC6D1DBD814A00B79BFE /* AIRGMSMarker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRGMSMarker.h; sourceTree = ""; }; 8620CC6E1DBD814A00B79BFE /* AIRGMSMarker.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRGMSMarker.m; sourceTree = ""; }; 8620CC6F1DBD814A00B79BFE /* AIRGoogleMap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRGoogleMap.h; sourceTree = ""; }; @@ -145,7 +144,8 @@ 8697D6211DBEDE6100DB7D0F /* AIRGoogleMapCircle.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRGoogleMapCircle.m; sourceTree = ""; }; 8697D6231DBEE22B00DB7D0F /* AIRGoogleMapCircleManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRGoogleMapCircleManager.h; sourceTree = ""; }; 8697D6241DBEE22B00DB7D0F /* AIRGoogleMapCircleManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRGoogleMapCircleManager.m; sourceTree = ""; }; - 86C3F1E16CFF1D84E5317F85 /* Pods-AirMapsExplorer.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AirMapsExplorer.debug.xcconfig"; path = "Pods/Target Support Files/Pods-AirMapsExplorer/Pods-AirMapsExplorer.debug.xcconfig"; sourceTree = ""; }; + BE5DE1E9AE25978F88CD940A /* Pods-AirMapsExplorer.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AirMapsExplorer.debug.xcconfig"; path = "Pods/Target Support Files/Pods-AirMapsExplorer/Pods-AirMapsExplorer.debug.xcconfig"; sourceTree = ""; }; + E138AD0CDB08FE57B09B18F8 /* Pods-AirMapsExplorer.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AirMapsExplorer.release.xcconfig"; path = "Pods/Target Support Files/Pods-AirMapsExplorer/Pods-AirMapsExplorer.release.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -164,7 +164,7 @@ 21E6570E1D77591F00B75EE5 /* MapKit.framework in Frameworks */, 21E6570C1D77591A00B75EE5 /* MobileCoreServices.framework in Frameworks */, 21E6570A1D77591400B75EE5 /* SystemConfiguration.framework in Frameworks */, - C9315A21AD5A149EB5B40F29 /* Pods_AirMapsExplorer.framework in Frameworks */, + 3E4E0B5921E01BC4043FD8CD /* Pods_AirMapsExplorer.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -183,20 +183,11 @@ 21E6570D1D77591F00B75EE5 /* MapKit.framework */, 21E6570B1D77591A00B75EE5 /* MobileCoreServices.framework */, 21E657091D77591400B75EE5 /* SystemConfiguration.framework */, - 24EB66BA0860A4DCD4CA3D77 /* Pods_AirMapsExplorer.framework */, + 3591658C00398534590C8751 /* Pods_AirMapsExplorer.framework */, ); name = Frameworks; sourceTree = ""; }; - 075E864247A56626509A7315 /* Pods */ = { - isa = PBXGroup; - children = ( - 86C3F1E16CFF1D84E5317F85 /* Pods-AirMapsExplorer.debug.xcconfig */, - 309B9CD42BBCF38F87696E10 /* Pods-AirMapsExplorer.release.xcconfig */, - ); - name = Pods; - sourceTree = ""; - }; 13B07FAE1A68108700A75B9A /* AirMapsExplorer */ = { isa = PBXGroup; children = ( @@ -276,8 +267,8 @@ 13B07FAE1A68108700A75B9A /* AirMapsExplorer */, 83CBBA001A601CBA00E9B192 /* Products */, 051AB288C799B62BE091B88A /* Frameworks */, - 075E864247A56626509A7315 /* Pods */, 2BAA8C4A80B44CFBB3F83458 /* Libraries */, + C2ED0F349F22CC794F9BC33F /* Pods */, ); indentWidth = 2; sourceTree = ""; @@ -330,6 +321,15 @@ path = ../../ios/AirGoogleMaps; sourceTree = ""; }; + C2ED0F349F22CC794F9BC33F /* Pods */ = { + isa = PBXGroup; + children = ( + BE5DE1E9AE25978F88CD940A /* Pods-AirMapsExplorer.debug.xcconfig */, + E138AD0CDB08FE57B09B18F8 /* Pods-AirMapsExplorer.release.xcconfig */, + ); + name = Pods; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -355,13 +355,13 @@ isa = PBXNativeTarget; buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "AirMapsExplorer" */; buildPhases = ( - B27D5F0DA3595C3A8B5D31D9 /* [CP] Check Pods Manifest.lock */, + CD9BCC809B77B74C231EE502 /* [CP] Check Pods Manifest.lock */, 13B07F871A680F5B00A75B9A /* Sources */, 13B07F8C1A680F5B00A75B9A /* Frameworks */, 13B07F8E1A680F5B00A75B9A /* Resources */, 00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */, - A4662ADFE799D81334C129C7 /* [CP] Embed Pods Frameworks */, - DD0B426CF8A839A0248EA8C7 /* [CP] Copy Pods Resources */, + 17E7BB4CEC38ABB7449E144E /* [CP] Embed Pods Frameworks */, + A6FAA2DEE540E08939F1B2AB /* [CP] Copy Pods Resources */, ); buildRules = ( ); @@ -440,7 +440,7 @@ shellPath = /bin/sh; shellScript = "../node_modules/react-native/packager/react-native-xcode.sh"; }; - A4662ADFE799D81334C129C7 /* [CP] Embed Pods Frameworks */ = { + 17E7BB4CEC38ABB7449E144E /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -455,34 +455,34 @@ shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-AirMapsExplorer/Pods-AirMapsExplorer-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; - B27D5F0DA3595C3A8B5D31D9 /* [CP] Check Pods Manifest.lock */ = { + A6FAA2DEE540E08939F1B2AB /* [CP] Copy Pods Resources */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); - name = "[CP] Check Pods Manifest.lock"; + name = "[CP] Copy Pods Resources"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n"; + shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-AirMapsExplorer/Pods-AirMapsExplorer-resources.sh\"\n"; showEnvVarsInLog = 0; }; - DD0B426CF8A839A0248EA8C7 /* [CP] Copy Pods Resources */ = { + CD9BCC809B77B74C231EE502 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); - name = "[CP] Copy Pods Resources"; + name = "[CP] Check Pods Manifest.lock"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-AirMapsExplorer/Pods-AirMapsExplorer-resources.sh\"\n"; + shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n"; showEnvVarsInLog = 0; }; /* End PBXShellScriptBuildPhase section */ @@ -602,7 +602,7 @@ }; 13B07F941A680F5B00A75B9A /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 86C3F1E16CFF1D84E5317F85 /* Pods-AirMapsExplorer.debug.xcconfig */; + baseConfigurationReference = BE5DE1E9AE25978F88CD940A /* Pods-AirMapsExplorer.debug.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; DEAD_CODE_STRIPPING = NO; @@ -625,7 +625,7 @@ }; 13B07F951A680F5B00A75B9A /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 309B9CD42BBCF38F87696E10 /* Pods-AirMapsExplorer.release.xcconfig */; + baseConfigurationReference = E138AD0CDB08FE57B09B18F8 /* Pods-AirMapsExplorer.release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; FRAMEWORK_SEARCH_PATHS = ( diff --git a/example/ios/Gemfile b/example/ios/Gemfile new file mode 100644 index 000000000..b9ec3be2d --- /dev/null +++ b/example/ios/Gemfile @@ -0,0 +1,2 @@ +source 'https://rubygems.org' +gem 'cocoapods', '~>1.1.1' diff --git a/example/ios/Gemfile.lock b/example/ios/Gemfile.lock new file mode 100644 index 000000000..b8c6feba0 --- /dev/null +++ b/example/ios/Gemfile.lock @@ -0,0 +1,73 @@ +GEM + remote: https://rubygems.org/ + specs: + CFPropertyList (2.3.3) + activesupport (4.2.7.1) + i18n (~> 0.7) + json (~> 1.7, >= 1.7.7) + minitest (~> 5.1) + thread_safe (~> 0.3, >= 0.3.4) + tzinfo (~> 1.1) + claide (1.0.1) + cocoapods (1.1.1) + activesupport (>= 4.0.2, < 5) + claide (>= 1.0.1, < 2.0) + cocoapods-core (= 1.1.1) + cocoapods-deintegrate (>= 1.0.1, < 2.0) + cocoapods-downloader (>= 1.1.2, < 2.0) + cocoapods-plugins (>= 1.0.0, < 2.0) + cocoapods-search (>= 1.0.0, < 2.0) + cocoapods-stats (>= 1.0.0, < 2.0) + cocoapods-trunk (>= 1.1.1, < 2.0) + cocoapods-try (>= 1.1.0, < 2.0) + colored (~> 1.2) + escape (~> 0.0.4) + fourflusher (~> 2.0.1) + gh_inspector (~> 1.0) + molinillo (~> 0.5.1) + nap (~> 1.0) + xcodeproj (>= 1.3.3, < 2.0) + cocoapods-core (1.1.1) + activesupport (>= 4.0.2, < 5) + fuzzy_match (~> 2.0.4) + nap (~> 1.0) + cocoapods-deintegrate (1.0.1) + cocoapods-downloader (1.1.2) + cocoapods-plugins (1.0.0) + nap + cocoapods-search (1.0.0) + cocoapods-stats (1.0.0) + cocoapods-trunk (1.1.1) + nap (>= 0.8, < 2.0) + netrc (= 0.7.8) + cocoapods-try (1.1.0) + colored (1.2) + escape (0.0.4) + fourflusher (2.0.1) + fuzzy_match (2.0.4) + gh_inspector (1.0.2) + i18n (0.7.0) + json (1.8.3) + minitest (5.9.1) + molinillo (0.5.3) + nanaimo (0.2.2) + nap (1.1.0) + netrc (0.7.8) + thread_safe (0.3.5) + tzinfo (1.2.2) + thread_safe (~> 0.1) + xcodeproj (1.4.1) + CFPropertyList (~> 2.3.3) + activesupport (>= 3) + claide (>= 1.0.1, < 2.0) + colored (~> 1.2) + nanaimo (~> 0.2.0) + +PLATFORMS + ruby + +DEPENDENCIES + cocoapods (~> 1.1.1) + +BUNDLED WITH + 1.10.6 diff --git a/ios/AirMaps/AIRMapManager.m b/ios/AirMaps/AIRMapManager.m index a8ed23423..2f008e2be 100644 --- a/ios/AirMaps/AIRMapManager.m +++ b/ios/AirMaps/AIRMapManager.m @@ -352,10 +352,10 @@ - (void)handleMapTap:(UITapGestureRecognizer *)recognizer { AIRMapPolyline *polyline = (AIRMapPolyline*) overlay; if (polyline.onPress) { float distance = [self distanceOfPoint:MKMapPointForCoordinate(tapCoordinate) - toPoly:overlay]; + toPoly:polyline]; if (distance < nearestDistance) { nearestDistance = distance; - nearestPolyline = overlay; + nearestPolyline = polyline; } } } From 1b948350e3d4f87af19649110555b9727fed5aff Mon Sep 17 00:00:00 2001 From: Benjamin Toueg Date: Thu, 10 Nov 2016 20:55:57 +0100 Subject: [PATCH 0150/1148] Implements animateToRegion to Google Maps iOS (#779) --- ios/AirGoogleMaps/AIRGoogleMap.h | 3 + ios/AirGoogleMaps/AIRGoogleMap.m | 78 ++++++++++++------------- ios/AirGoogleMaps/AIRGoogleMapManager.m | 17 ++++++ 3 files changed, 59 insertions(+), 39 deletions(-) diff --git a/ios/AirGoogleMaps/AIRGoogleMap.h b/ios/AirGoogleMaps/AIRGoogleMap.h index cc7aad5da..e25ab4897 100644 --- a/ios/AirGoogleMaps/AIRGoogleMap.h +++ b/ios/AirGoogleMaps/AIRGoogleMap.h @@ -43,4 +43,7 @@ - (void)didChangeCameraPosition:(GMSCameraPosition *)position; - (void)idleAtCameraPosition:(GMSCameraPosition *)position; ++ (MKCoordinateRegion)makeGMSCameraPositionFromMap:(GMSMapView *)map andGMSCameraPosition:(GMSCameraPosition *)position; ++ (GMSCameraPosition*)makeGMSCameraPositionFromMap:(GMSMapView *)map andMKCoordinateRegion:(MKCoordinateRegion)region; + @end diff --git a/ios/AirGoogleMaps/AIRGoogleMap.m b/ios/AirGoogleMaps/AIRGoogleMap.m index 89059f3bc..af3019a1b 100644 --- a/ios/AirGoogleMaps/AIRGoogleMap.m +++ b/ios/AirGoogleMaps/AIRGoogleMap.m @@ -24,41 +24,6 @@ id regionAsJSON(MKCoordinateRegion region) { }; } -MKCoordinateRegion makeMKCoordinateRegionFromGMSCameraPositionOfMap(GMSMapView *map, GMSCameraPosition *position) { - // solution from here: http://stackoverflow.com/a/16587735/1102215 - GMSVisibleRegion visibleRegion = map.projection.visibleRegion; - GMSCoordinateBounds *bounds = [[GMSCoordinateBounds alloc] initWithRegion: visibleRegion]; - CLLocationCoordinate2D center; - CLLocationDegrees longitudeDelta; - CLLocationDegrees latitudeDelta = bounds.northEast.latitude - bounds.southWest.latitude; - - if(bounds.northEast.longitude >= bounds.southWest.longitude) { - //Standard case - center = CLLocationCoordinate2DMake((bounds.southWest.latitude + bounds.northEast.latitude) / 2, - (bounds.southWest.longitude + bounds.northEast.longitude) / 2); - longitudeDelta = bounds.northEast.longitude - bounds.southWest.longitude; - } else { - //Region spans the international dateline - center = CLLocationCoordinate2DMake((bounds.southWest.latitude + bounds.northEast.latitude) / 2, - (bounds.southWest.longitude + bounds.northEast.longitude + 360) / 2); - longitudeDelta = bounds.northEast.longitude + 360 - bounds.southWest.longitude; - } - MKCoordinateSpan span = MKCoordinateSpanMake(latitudeDelta, longitudeDelta); - return MKCoordinateRegionMake(center, span); -} - -GMSCameraPosition* makeGMSCameraPositionFromMKCoordinateRegionOfMap(GMSMapView *map, MKCoordinateRegion region) { - float latitudeDelta = region.span.latitudeDelta * 0.5; - float longitudeDelta = region.span.longitudeDelta * 0.5; - - CLLocationCoordinate2D a = CLLocationCoordinate2DMake(region.center.latitude + latitudeDelta, - region.center.longitude + longitudeDelta); - CLLocationCoordinate2D b = CLLocationCoordinate2DMake(region.center.latitude - latitudeDelta, - region.center.longitude - longitudeDelta); - GMSCoordinateBounds *bounds = [[GMSCoordinateBounds alloc] initWithCoordinate:a coordinate:b]; - return [map cameraForBounds:bounds insets:UIEdgeInsetsZero]; -} - @interface AIRGoogleMap () - (id)eventFromCoordinate:(CLLocationCoordinate2D)coordinate; @@ -162,12 +127,12 @@ - (void)removeReactSubview:(id)subview { - (void)setInitialRegion:(MKCoordinateRegion)initialRegion { if (_initialRegionSet) return; _initialRegionSet = true; - self.camera = makeGMSCameraPositionFromMKCoordinateRegionOfMap(self, initialRegion); + self.camera = [AIRGoogleMap makeGMSCameraPositionFromMap:self andMKCoordinateRegion:initialRegion]; } - (void)setRegion:(MKCoordinateRegion)region { // TODO: The JS component is repeatedly setting region unnecessarily. We might want to deal with that in here. - self.camera = makeGMSCameraPositionFromMKCoordinateRegionOfMap(self, region); + self.camera = [AIRGoogleMap makeGMSCameraPositionFromMap:self andMKCoordinateRegion:region]; } - (BOOL)didTapMarker:(GMSMarker *)marker { @@ -197,7 +162,7 @@ - (void)didLongPressAtCoordinate:(CLLocationCoordinate2D)coordinate { - (void)didChangeCameraPosition:(GMSCameraPosition *)position { id event = @{@"continuous": @YES, - @"region": regionAsJSON(makeMKCoordinateRegionFromGMSCameraPositionOfMap(self, position)), + @"region": regionAsJSON([AIRGoogleMap makeGMSCameraPositionFromMap:self andGMSCameraPosition:position]), }; if (self.onChange) self.onChange(event); @@ -205,7 +170,7 @@ - (void)didChangeCameraPosition:(GMSCameraPosition *)position { - (void)idleAtCameraPosition:(GMSCameraPosition *)position { id event = @{@"continuous": @NO, - @"region": regionAsJSON(makeMKCoordinateRegionFromGMSCameraPositionOfMap(self, position)), + @"region": regionAsJSON([AIRGoogleMap makeGMSCameraPositionFromMap:self andGMSCameraPosition:position]), }; if (self.onChange) self.onChange(event); // complete } @@ -275,4 +240,39 @@ - (BOOL)showsUserLocation { return self.myLocationEnabled; } ++ (MKCoordinateRegion) makeGMSCameraPositionFromMap:(GMSMapView *)map andGMSCameraPosition:(GMSCameraPosition *)position { + // solution from here: http://stackoverflow.com/a/16587735/1102215 + GMSVisibleRegion visibleRegion = map.projection.visibleRegion; + GMSCoordinateBounds *bounds = [[GMSCoordinateBounds alloc] initWithRegion: visibleRegion]; + CLLocationCoordinate2D center; + CLLocationDegrees longitudeDelta; + CLLocationDegrees latitudeDelta = bounds.northEast.latitude - bounds.southWest.latitude; + + if(bounds.northEast.longitude >= bounds.southWest.longitude) { + //Standard case + center = CLLocationCoordinate2DMake((bounds.southWest.latitude + bounds.northEast.latitude) / 2, + (bounds.southWest.longitude + bounds.northEast.longitude) / 2); + longitudeDelta = bounds.northEast.longitude - bounds.southWest.longitude; + } else { + //Region spans the international dateline + center = CLLocationCoordinate2DMake((bounds.southWest.latitude + bounds.northEast.latitude) / 2, + (bounds.southWest.longitude + bounds.northEast.longitude + 360) / 2); + longitudeDelta = bounds.northEast.longitude + 360 - bounds.southWest.longitude; + } + MKCoordinateSpan span = MKCoordinateSpanMake(latitudeDelta, longitudeDelta); + return MKCoordinateRegionMake(center, span); +} + ++ (GMSCameraPosition*) makeGMSCameraPositionFromMap:(GMSMapView *)map andMKCoordinateRegion:(MKCoordinateRegion)region { + float latitudeDelta = region.span.latitudeDelta * 0.5; + float longitudeDelta = region.span.longitudeDelta * 0.5; + + CLLocationCoordinate2D a = CLLocationCoordinate2DMake(region.center.latitude + latitudeDelta, + region.center.longitude + longitudeDelta); + CLLocationCoordinate2D b = CLLocationCoordinate2DMake(region.center.latitude - latitudeDelta, + region.center.longitude - longitudeDelta); + GMSCoordinateBounds *bounds = [[GMSCoordinateBounds alloc] initWithCoordinate:a coordinate:b]; + return [map cameraForBounds:bounds insets:UIEdgeInsetsZero]; +} + @end diff --git a/ios/AirGoogleMaps/AIRGoogleMapManager.m b/ios/AirGoogleMaps/AIRGoogleMapManager.m index be2015835..f658fc6ce 100644 --- a/ios/AirGoogleMaps/AIRGoogleMapManager.m +++ b/ios/AirGoogleMaps/AIRGoogleMapManager.m @@ -64,6 +64,23 @@ - (UIView *)view RCT_EXPORT_VIEW_PROPERTY(onRegionChangeComplete, RCTDirectEventBlock) RCT_EXPORT_VIEW_PROPERTY(mapType, GMSMapViewType) +RCT_EXPORT_METHOD(animateToRegion:(nonnull NSNumber *)reactTag + withRegion:(MKCoordinateRegion)region + withDuration:(CGFloat)duration) +{ + [self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary *viewRegistry) { + id view = viewRegistry[reactTag]; + if (![view isKindOfClass:[AIRGoogleMap class]]) { + RCTLogError(@"Invalid view returned from registry, expecting AIRGoogleMap, got: %@", view); + } else { + [AIRGoogleMap animateWithDuration:duration/1000 animations:^{ + GMSCameraPosition* camera = [AIRGoogleMap makeGMSCameraPositionFromMap:(AIRGoogleMap *)view andMKCoordinateRegion:region]; + [(AIRGoogleMap *)view animateToCameraPosition:camera]; + }]; + } + }]; +} + RCT_EXPORT_METHOD(fitToElements:(nonnull NSNumber *)reactTag animated:(BOOL)animated) { From 81865819309b6644c13e4c52aa1cadbeab4aa73c Mon Sep 17 00:00:00 2001 From: Danielle Tomlinson Date: Thu, 10 Nov 2016 21:11:55 +0100 Subject: [PATCH 0151/1148] [Docs] Fix capitalisation of Xcode and CocoaPods (#749) --- docs/installation.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/installation.md b/docs/installation.md index 8a1fb95ba..c14995999 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -15,17 +15,17 @@ add native dependencies automatically then continue the directions below dependi ## iOS -### Option 1: Cocoapods - Same as the included AirMapsExplorer example +### Option 1: CocoaPods - Same as the included AirMapsExplorer example 1. Setup your `Podfile` like the included [example/ios/Podfile](../example/ios/Podfile) then run `pod install`. (If you do not need `GoogleMaps` support for iOS, then you can probably completely skip this step.) -1. Open your project in xCode workspace +1. Open your project in Xcode workspace 1. Drag the following folder into your project: - `node_modules/react-native-maps/ios/AirMaps/` 1. If you need `GoogleMaps` support also drag this folder into your project: - `node_modules/react-native-maps/ios/AirGoogleMaps/` -### Option 2: Cocoapods -- Untested Way +### Option 2: CocoaPods -- Untested Way NOTE: If you actually get this to work, please open an issue to let us know. This is now considered the **old way** because it is untested and if it does work at all, it will only work if you **don't** have `use_frameworks!` in your `Podfile` @@ -44,13 +44,13 @@ Now if you need `GoogleMaps` support you will also have to add a bunch of other After your `Podfile` is setup properly, run `pod install`. ### Option 3: Manually -1. Open your project in XCode, right click on `Libraries` and click `Add +1. Open your project in Xcode, right click on `Libraries` and click `Add Files to "Your Project Name"` Look under `node_modules/react-native-maps/ios` and add `AIRMaps.xcodeproj`. 1. Add `libAIRMaps.a` to `Build Phases -> Link Binary With Libraries. 1. Click on `AIRMaps.xcodeproj` in `Libraries` and go the `Build Settings` tab. Double click the text to the right of `Header Search Paths` and verify that it has `$(SRCROOT)/../../react-native/React` as well as `$(SRCROOT)/../../react-native/Libraries/Image` - if they - aren't, then add them. This is so XCode is able to find the headers that + aren't, then add them. This is so Xcode is able to find the headers that the `AIRMaps` source files are referring to by pointing to the header files installed within the `react-native` `node_modules` directory. From 8e78aa3923f6530c36054d765cbb1b63638031f4 Mon Sep 17 00:00:00 2001 From: Nick Italiano Date: Thu, 10 Nov 2016 16:08:48 -0800 Subject: [PATCH 0152/1148] iOS google maps custom tile support (#770) --- components/MapUrlTile.js | 20 ++++++++--- example/App.js | 2 +- example/examples/CustomTiles.js | 15 ++++++-- .../AirMapsExplorer.xcodeproj/project.pbxproj | 13 +++++++ ios/AirGoogleMaps/AIRGoogleMap.h | 1 + ios/AirGoogleMaps/AIRGoogleMap.m | 10 ++++++ .../AIRGoogleMapURLTileManager.m | 26 ++++++++++++++ ios/AirGoogleMaps/AIRGoogleMapUrlTile.h | 15 ++++++++ ios/AirGoogleMaps/AIRGoogleMapUrlTile.m | 34 +++++++++++++++++++ .../AIRGoogleMapUrlTileManager.h | 10 ++++++ 10 files changed, 139 insertions(+), 7 deletions(-) create mode 100644 ios/AirGoogleMaps/AIRGoogleMapURLTileManager.m create mode 100644 ios/AirGoogleMaps/AIRGoogleMapUrlTile.h create mode 100644 ios/AirGoogleMaps/AIRGoogleMapUrlTile.m create mode 100644 ios/AirGoogleMaps/AIRGoogleMapUrlTileManager.h diff --git a/components/MapUrlTile.js b/components/MapUrlTile.js index 3ab1a8488..cf2770334 100644 --- a/components/MapUrlTile.js +++ b/components/MapUrlTile.js @@ -1,9 +1,14 @@ import React, { PropTypes } from 'react'; + import { View, - requireNativeComponent, } from 'react-native'; +import decorateMapComponent, { + USES_DEFAULT_IMPLEMENTATION, + SUPPORTED, +} from './decorateMapComponent'; + const propTypes = { ...View.propTypes, @@ -25,6 +30,7 @@ const propTypes = { class MapUrlTile extends React.Component { render() { + const AIRMapUrlTile = this.getAirComponent(); return ( @@ -54,6 +61,10 @@ class CustomTiles extends React.Component { } } +CustomTiles.propTypes = { + provider: MapView.ProviderPropType, +}; + const styles = StyleSheet.create({ container: { position: 'absolute', diff --git a/example/ios/AirMapsExplorer.xcodeproj/project.pbxproj b/example/ios/AirMapsExplorer.xcodeproj/project.pbxproj index 84761f0be..decbbec68 100644 --- a/example/ios/AirMapsExplorer.xcodeproj/project.pbxproj +++ b/example/ios/AirMapsExplorer.xcodeproj/project.pbxproj @@ -48,6 +48,9 @@ 8620CC931DBD814A00B79BFE /* RCTConvert+GMSMapViewType.m in Sources */ = {isa = PBXBuildFile; fileRef = 8620CC861DBD814A00B79BFE /* RCTConvert+GMSMapViewType.m */; }; 8697D6221DBEDE6100DB7D0F /* AIRGoogleMapCircle.m in Sources */ = {isa = PBXBuildFile; fileRef = 8697D6211DBEDE6100DB7D0F /* AIRGoogleMapCircle.m */; }; 8697D6251DBEE22B00DB7D0F /* AIRGoogleMapCircleManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 8697D6241DBEE22B00DB7D0F /* AIRGoogleMapCircleManager.m */; }; + 86DE6F881DCE7D21002A5053 /* AIRGoogleMapUrlTile.m in Sources */ = {isa = PBXBuildFile; fileRef = 86DE6F871DCE7D21002A5053 /* AIRGoogleMapUrlTile.m */; }; + 86DE6F8B1DCE8543002A5053 /* AIRGoogleMapURLTileManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 86DE6F8A1DCE8543002A5053 /* AIRGoogleMapURLTileManager.m */; }; + C9315A21AD5A149EB5B40F29 /* Pods_AirMapsExplorer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 24EB66BA0860A4DCD4CA3D77 /* Pods_AirMapsExplorer.framework */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -146,6 +149,10 @@ 8697D6241DBEE22B00DB7D0F /* AIRGoogleMapCircleManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRGoogleMapCircleManager.m; sourceTree = ""; }; BE5DE1E9AE25978F88CD940A /* Pods-AirMapsExplorer.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AirMapsExplorer.debug.xcconfig"; path = "Pods/Target Support Files/Pods-AirMapsExplorer/Pods-AirMapsExplorer.debug.xcconfig"; sourceTree = ""; }; E138AD0CDB08FE57B09B18F8 /* Pods-AirMapsExplorer.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AirMapsExplorer.release.xcconfig"; path = "Pods/Target Support Files/Pods-AirMapsExplorer/Pods-AirMapsExplorer.release.xcconfig"; sourceTree = ""; }; + 86DE6F861DCE7D21002A5053 /* AIRGoogleMapUrlTile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRGoogleMapUrlTile.h; sourceTree = ""; }; + 86DE6F871DCE7D21002A5053 /* AIRGoogleMapUrlTile.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRGoogleMapUrlTile.m; sourceTree = ""; }; + 86DE6F891DCE8543002A5053 /* AIRGoogleMapUrlTileManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRGoogleMapUrlTileManager.h; sourceTree = ""; }; + 86DE6F8A1DCE8543002A5053 /* AIRGoogleMapURLTileManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRGoogleMapURLTileManager.m; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -316,6 +323,10 @@ 8697D6211DBEDE6100DB7D0F /* AIRGoogleMapCircle.m */, 8697D6231DBEE22B00DB7D0F /* AIRGoogleMapCircleManager.h */, 8697D6241DBEE22B00DB7D0F /* AIRGoogleMapCircleManager.m */, + 86DE6F861DCE7D21002A5053 /* AIRGoogleMapUrlTile.h */, + 86DE6F871DCE7D21002A5053 /* AIRGoogleMapUrlTile.m */, + 86DE6F891DCE8543002A5053 /* AIRGoogleMapUrlTileManager.h */, + 86DE6F8A1DCE8543002A5053 /* AIRGoogleMapURLTileManager.m */, ); name = AirGoogleMaps; path = ../../ios/AirGoogleMaps; @@ -521,6 +532,8 @@ 2166AB3E1D82EC56007538D7 /* RCTConvert+MoreMapKit.m in Sources */, 8697D6251DBEE22B00DB7D0F /* AIRGoogleMapCircleManager.m in Sources */, 13B07FC11A68108700A75B9A /* main.m in Sources */, + 86DE6F8B1DCE8543002A5053 /* AIRGoogleMapURLTileManager.m in Sources */, + 86DE6F881DCE7D21002A5053 /* AIRGoogleMapUrlTile.m in Sources */, 2166AB331D82EC56007538D7 /* AIRMapPolygonManager.m in Sources */, 8620CC901DBD814A00B79BFE /* AIRGoogleMapPolyline.m in Sources */, 2166AB2B1D82EC56007538D7 /* AIRMapCalloutManager.m in Sources */, diff --git a/ios/AirGoogleMaps/AIRGoogleMap.h b/ios/AirGoogleMaps/AIRGoogleMap.h index e25ab4897..52480974a 100644 --- a/ios/AirGoogleMaps/AIRGoogleMap.h +++ b/ios/AirGoogleMaps/AIRGoogleMap.h @@ -27,6 +27,7 @@ @property (nonatomic, strong) NSMutableArray *polygons; @property (nonatomic, strong) NSMutableArray *polylines; @property (nonatomic, strong) NSMutableArray *circles; +@property (nonatomic, strong) NSMutableArray *tiles; @property (nonatomic, assign) BOOL showsBuildings; @property (nonatomic, assign) BOOL showsTraffic; diff --git a/ios/AirGoogleMaps/AIRGoogleMap.m b/ios/AirGoogleMaps/AIRGoogleMap.m index af3019a1b..9da6a64e7 100644 --- a/ios/AirGoogleMaps/AIRGoogleMap.m +++ b/ios/AirGoogleMaps/AIRGoogleMap.m @@ -10,6 +10,7 @@ #import "AIRGoogleMapPolygon.h" #import "AIRGoogleMapPolyline.h" #import "AIRGoogleMapCircle.h" +#import "AIRGoogleMapUrlTile.h" #import #import #import "RCTConvert+MapKit.h" @@ -44,6 +45,7 @@ - (instancetype)init _polygons = [NSMutableArray array]; _polylines = [NSMutableArray array]; _circles = [NSMutableArray array]; + _tiles = [NSMutableArray array]; _initialRegionSet = false; } return self; @@ -85,6 +87,10 @@ - (void)insertReactSubview:(id)subview atIndex:(NSInteger)atIndex AIRGoogleMapCircle *circle = (AIRGoogleMapCircle*)subview; circle.circle.map = self; [self.circles addObject:circle]; + } else if ([subview isKindOfClass:[AIRGoogleMapUrlTile class]]) { + AIRGoogleMapUrlTile *tile = (AIRGoogleMapUrlTile*)subview; + tile.tileLayer.map = self; + [self.tiles addObject:tile]; } [_reactSubviews insertObject:(UIView *)subview atIndex:(NSUInteger) atIndex]; } @@ -112,6 +118,10 @@ - (void)removeReactSubview:(id)subview { AIRGoogleMapCircle *circle = (AIRGoogleMapCircle*)subview; circle.circle.map = nil; [self.circles removeObject:circle]; + } else if ([subview isKindOfClass:[AIRGoogleMapUrlTile class]]) { + AIRGoogleMapUrlTile *tile = (AIRGoogleMapUrlTile*)subview; + tile.tileLayer.map = nil; + [self.tiles removeObject:tile]; } [_reactSubviews removeObject:(UIView *)subview]; } diff --git a/ios/AirGoogleMaps/AIRGoogleMapURLTileManager.m b/ios/AirGoogleMaps/AIRGoogleMapURLTileManager.m new file mode 100644 index 000000000..79c82fe25 --- /dev/null +++ b/ios/AirGoogleMaps/AIRGoogleMapURLTileManager.m @@ -0,0 +1,26 @@ +// +// AIRGoogleMapURLTileManager.m +// Created by Nick Italiano on 11/5/16. +// + +#import "AIRGoogleMapUrlTileManager.h" +#import "AIRGoogleMapUrlTile.h" + +@interface AIRGoogleMapUrlTileManager() + +@end + +@implementation AIRGoogleMapUrlTileManager + +RCT_EXPORT_MODULE() + +- (UIView *)view +{ + AIRGoogleMapUrlTile *tileLayer = [AIRGoogleMapUrlTile new]; + return tileLayer; +} + +RCT_EXPORT_VIEW_PROPERTY(urlTemplate, NSString) +RCT_EXPORT_VIEW_PROPERTY(zIndex, int) + +@end diff --git a/ios/AirGoogleMaps/AIRGoogleMapUrlTile.h b/ios/AirGoogleMaps/AIRGoogleMapUrlTile.h new file mode 100644 index 000000000..f76a9dc88 --- /dev/null +++ b/ios/AirGoogleMaps/AIRGoogleMapUrlTile.h @@ -0,0 +1,15 @@ +// +// AIRGoogleMapURLTile.h +// Created by Nick Italiano on 11/5/16. +// + +#import +#import + +@interface AIRGoogleMapUrlTile : UIView + +@property (nonatomic, strong) GMSURLTileLayer *tileLayer; +@property (nonatomic, assign) NSString *urlTemplate; +@property (nonatomic, assign) int zIndex; + +@end diff --git a/ios/AirGoogleMaps/AIRGoogleMapUrlTile.m b/ios/AirGoogleMaps/AIRGoogleMapUrlTile.m new file mode 100644 index 000000000..ae6333cff --- /dev/null +++ b/ios/AirGoogleMaps/AIRGoogleMapUrlTile.m @@ -0,0 +1,34 @@ +// +// AIRGoogleMapURLTile.m +// Created by Nick Italiano on 11/5/16. +// + +#import "AIRGoogleMapUrlTile.h" + +@implementation AIRGoogleMapUrlTile + +- (void)setZIndex:(int)zIndex +{ + _zIndex = zIndex; + _tileLayer.zIndex = zIndex; +} + +- (void)setUrlTemplate:(NSString *)urlTemplate +{ + _urlTemplate = urlTemplate; + _tileLayer = [GMSURLTileLayer tileLayerWithURLConstructor:[self _getTileURLConstructor]]; +} + +- (GMSTileURLConstructor)_getTileURLConstructor +{ + NSString *urlTemplate = self.urlTemplate; + GMSTileURLConstructor urls = ^(NSUInteger x, NSUInteger y, NSUInteger zoom) { + NSString *url = urlTemplate; + url = [url stringByReplacingOccurrencesOfString:@"{x}" withString:[NSString stringWithFormat: @"%ld", (long)x]]; + url = [url stringByReplacingOccurrencesOfString:@"{y}" withString:[NSString stringWithFormat: @"%ld", (long)y]]; + url = [url stringByReplacingOccurrencesOfString:@"{z}" withString:[NSString stringWithFormat: @"%ld", (long)zoom]]; + return [NSURL URLWithString:url]; + }; + return urls; +} +@end diff --git a/ios/AirGoogleMaps/AIRGoogleMapUrlTileManager.h b/ios/AirGoogleMaps/AIRGoogleMapUrlTileManager.h new file mode 100644 index 000000000..3554837d4 --- /dev/null +++ b/ios/AirGoogleMaps/AIRGoogleMapUrlTileManager.h @@ -0,0 +1,10 @@ +// +// AIRGoogleMapURLTileManager.h +// Created by Nick Italiano on 11/5/16. +// + +#import +#import "RCTViewManager.h" + +@interface AIRGoogleMapUrlTileManager : RCTViewManager +@end From b469143cee3db225ce015fecc89eee5a0cb85484 Mon Sep 17 00:00:00 2001 From: Frank Rowe Date: Sat, 12 Nov 2016 15:48:01 -0500 Subject: [PATCH 0153/1148] add example for overlay overpress and docs --- docs/polygon.md | 5 ++++ docs/polyline.md | 5 ++++ example/examples/EventListener.js | 39 +++++++++++++++++++++++++++---- 3 files changed, 45 insertions(+), 4 deletions(-) diff --git a/docs/polygon.md b/docs/polygon.md index cc9220ba0..875327a81 100644 --- a/docs/polygon.md +++ b/docs/polygon.md @@ -15,6 +15,11 @@ | `lineDashPhase` | `Number` | `0` | (iOS only) The offset (in points) at which to start drawing the dash pattern. Use this property to start drawing a dashed line partway through a segment or gap. For example, a phase value of 6 for the patter 5-2-3-2 would cause drawing to begin in the middle of the first gap. | `lineDashPattern` | `Array` | `null` | (iOS only) An array of numbers specifying the dash pattern to use for the path. The array contains one or more numbers that indicate the lengths (measured in points) of the line segments and gaps in the pattern. The values in the array alternate, starting with the first line segment length, followed by the first gap length, followed by the second line segment length, and so on. +## Events + +| Event Name | Returns | Notes +|---|---|---| +| `onPress` | | Callback that is called when the user presses on the polygon ## Types diff --git a/docs/polyline.md b/docs/polyline.md index f9950e96f..c542c4ce3 100644 --- a/docs/polyline.md +++ b/docs/polyline.md @@ -14,6 +14,11 @@ | `lineDashPhase` | `Number` | `0` | (iOS only) The offset (in points) at which to start drawing the dash pattern. Use this property to start drawing a dashed line partway through a segment or gap. For example, a phase value of 6 for the patter 5-2-3-2 would cause drawing to begin in the middle of the first gap. | `lineDashPattern` | `Array` | `null` | (iOS only) An array of numbers specifying the dash pattern to use for the path. The array contains one or more numbers that indicate the lengths (measured in points) of the line segments and gaps in the pattern. The values in the array alternate, starting with the first line segment length, followed by the first gap length, followed by the second line segment length, and so on. +## Events + +| Event Name | Returns | Notes +|---|---|---| +| `onPress` | | Callback that is called when the user presses on the polyline ## Types diff --git a/example/examples/EventListener.js b/example/examples/EventListener.js index 85b6dbcf5..0f62fbc73 100644 --- a/example/examples/EventListener.js +++ b/example/examples/EventListener.js @@ -1,4 +1,5 @@ import React, { PropTypes } from 'react'; +import SyntheticEvent from 'react/lib/SyntheticEvent'; import { StyleSheet, View, @@ -65,13 +66,15 @@ class EventListener extends React.Component { recordEvent(name) { return e => { - const { events } = this.state; - this.setState({ + if (e instanceof SyntheticEvent && typeof e.persist === 'function') { + e.persist(); + } + this.setState(prevState => ({ events: [ this.makeEvent(e, name), - ...events.slice(0, 10), + ...prevState.events.slice(0, 10), ], - }); + })); }; } @@ -123,6 +126,34 @@ class EventListener extends React.Component {
+ + From 3d28a7d9fd005d59219668cf61177fe574170b84 Mon Sep 17 00:00:00 2001 From: Mark Uretsky Date: Mon, 14 Nov 2016 19:22:14 +0100 Subject: [PATCH 0154/1148] examples-setup.md: update android instructions (#743) --- docs/examples-setup.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/examples-setup.md b/docs/examples-setup.md index 8599a2f15..048dd46e7 100644 --- a/docs/examples-setup.md +++ b/docs/examples-setup.md @@ -28,5 +28,6 @@ open AirMapsExplorer.xcworkspace 2. Install via gradle: ``` -./example/android/gradlew installDebug +# from the example/ dir: +react-native run-android ``` From c32fde19ea93715db0741f50b73f1afb3e148a1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Alfredo=20Rivera=20Acu=C3=B1a?= <1alfredorivera@gmail.com> Date: Wed, 16 Nov 2016 15:03:04 -0600 Subject: [PATCH 0155/1148] update google play services (#805) * update google play services update google play services for better compatiblity * Update play services yo 9.8.0 --- android/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/android/build.gradle b/android/build.gradle index db87a71be..d6e86e557 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -54,6 +54,6 @@ android { dependencies { compile "com.facebook.react:react-native:+" - compile "com.google.android.gms:play-services-base:9.6.1" - compile "com.google.android.gms:play-services-maps:9.6.1" + compile "com.google.android.gms:play-services-base:9.8.0" + compile "com.google.android.gms:play-services-maps:9.8.0" } From cf29b15195451089e697487accd2059d1709b737 Mon Sep 17 00:00:00 2001 From: Jordan Harband Date: Wed, 16 Nov 2016 15:21:08 -0800 Subject: [PATCH 0156/1148] Update copyright. --- LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index f6981d805..6659955b0 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2015 Leland Richardson +Copyright (c) 2015 Airbnb Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal From db42a97dbeeaf3aa7ed75e3c73d53e68651c1c8e Mon Sep 17 00:00:00 2001 From: Ali Al Amine Date: Mon, 21 Nov 2016 21:15:10 +0200 Subject: [PATCH 0157/1148] [android] Add customMapStyle prop support to MapView for android (#808) --- README.md | 22 ++ .../android/react/maps/AirMapManager.java | 6 + components/MapView.js | 20 +- example/App.js | 2 + example/examples/MapStyle.js | 222 ++++++++++++++++++ 5 files changed, 271 insertions(+), 1 deletion(-) create mode 100644 example/examples/MapStyle.js diff --git a/README.md b/README.md index 7b6d358ea..fe945bd7c 100644 --- a/README.md +++ b/README.md @@ -172,7 +172,24 @@ For Android: add the following line in your AndroidManifest.xml ``` For IOS: configure [App Transport Security](https://developer.apple.com/library/content/documentation/General/Reference/InfoPlistKeyReference/Articles/CocoaKeys.html#//apple_ref/doc/uid/TP40009251-SW33) in your app +### Customizing the map style +Create the json object, or download a generated one from the [google style generator](https://mapstyle.withgoogle.com/). + +```jsx +// The generated json object +mapStyle = [ ... ] + +render() { + return ( + + ); +} +``` ## Examples @@ -201,6 +218,11 @@ API could. ![](http://i.giphy.com/3o6UB7poyB6YJ0KPWU.gif) ![](http://i.giphy.com/xT77Yc4wK3pzZusEbm.gif) +### Changing the style of the map + +![](http://i.imgur.com/a9WqCL6.png) + + ### Arbitrary React Views as Markers diff --git a/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java b/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java index 4273a31ed..75ed5777f 100644 --- a/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java +++ b/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java @@ -20,6 +20,7 @@ import com.google.android.gms.maps.MapsInitializer; import com.google.android.gms.maps.model.LatLng; import com.google.android.gms.maps.model.LatLngBounds; +import com.google.android.gms.maps.model.MapStyleOptions; import java.util.Map; @@ -92,6 +93,11 @@ public void setMapType(AirMapView view, @Nullable String mapType) { int typeId = MAP_TYPES.get(mapType); view.map.setMapType(typeId); } + + @ReactProp(name = "customMapStyleString") + public void setMapStyle(AirMapView view, @Nullable String customMapStyleString) { + view.map.setMapStyle(new MapStyleOptions(customMapStyleString)); + } @ReactProp(name = "showsUserLocation", defaultBoolean = false) public void setShowsUserLocation(AirMapView view, boolean showUserLocation) { diff --git a/components/MapView.js b/components/MapView.js index 74571e180..25f29881f 100644 --- a/components/MapView.js +++ b/components/MapView.js @@ -61,6 +61,21 @@ const propTypes = { */ style: View.propTypes.style, + /** + * A json object that describes the style of the map. This is transformed to a string + * and saved in mayStyleString to be sent to android and ios + * https://developers.google.com/maps/documentation/ios-sdk/styling#use_a_string_resource + * https://developers.google.com/maps/documentation/android-api/styling + */ + customMapStyle: PropTypes.array, + + /** + * A json string that describes the style of the map + * https://developers.google.com/maps/documentation/ios-sdk/styling#use_a_string_resource + * https://developers.google.com/maps/documentation/android-api/styling + */ + customMapStyleString: PropTypes.string, + /** * If `true` the app will ask for the user's location. * Default value is `false`. @@ -386,12 +401,15 @@ class MapView extends React.Component { } _onMapReady() { - const { region, initialRegion } = this.props; + const { region, initialRegion, customMapStyle } = this.props; if (region) { this.map.setNativeProps({ region }); } else if (initialRegion) { this.map.setNativeProps({ region: initialRegion }); } + if (customMapStyle) { + this.map.setNativeProps({ customMapStyleString: JSON.stringify(customMapStyle) }); + } this.setState({ isReady: true }); } diff --git a/example/App.js b/example/App.js index 39e3866a5..abd02acd2 100644 --- a/example/App.js +++ b/example/App.js @@ -31,6 +31,7 @@ import LiteMapView from './examples/LiteMapView'; import CustomTiles from './examples/CustomTiles'; import ZIndexMarkers from './examples/ZIndexMarkers'; import StaticMap from './examples/StaticMap'; +import MapStyle from './examples/MapStyle'; const IOS = Platform.OS === 'ios'; const ANDROID = Platform.OS === 'android'; @@ -140,6 +141,7 @@ class App extends React.Component { [LiteMapView, 'Android Lite MapView'], [CustomTiles, 'Custom Tiles', true], [ZIndexMarkers, 'Position Markers with Z-index', true], + [MapStyle, 'Customize the style of the map', true], ] // Filter out examples that are not yet supported for Google Maps on iOS. .filter(example => ANDROID || (IOS && (example[2] || !this.state.useGoogleMaps))) diff --git a/example/examples/MapStyle.js b/example/examples/MapStyle.js new file mode 100644 index 000000000..5d3416c93 --- /dev/null +++ b/example/examples/MapStyle.js @@ -0,0 +1,222 @@ +import React from 'react'; +import { + StyleSheet, + View, + Dimensions, +} from 'react-native'; + +import MapView from 'react-native-maps'; + +const { width, height } = Dimensions.get('window'); + +const ASPECT_RATIO = width / height; +const LATITUDE = 37.78825; +const LONGITUDE = -122.4324; +const LATITUDE_DELTA = 0.0922; +const LONGITUDE_DELTA = LATITUDE_DELTA * ASPECT_RATIO; + +const customStyle = [ + { + elementType: 'geometry', + stylers: [ + { + color: '#242f3e', + }, + ], + }, + { + elementType: 'labels.text.fill', + stylers: [ + { + color: '#746855', + }, + ], + }, + { + elementType: 'labels.text.stroke', + stylers: [ + { + color: '#242f3e', + }, + ], + }, + { + featureType: 'administrative.locality', + elementType: 'labels.text.fill', + stylers: [ + { + color: '#d59563', + }, + ], + }, + { + featureType: 'poi', + elementType: 'labels.text.fill', + stylers: [ + { + color: '#d59563', + }, + ], + }, + { + featureType: 'poi.park', + elementType: 'geometry', + stylers: [ + { + color: '#263c3f', + }, + ], + }, + { + featureType: 'poi.park', + elementType: 'labels.text.fill', + stylers: [ + { + color: '#6b9a76', + }, + ], + }, + { + featureType: 'road', + elementType: 'geometry', + stylers: [ + { + color: '#38414e', + }, + ], + }, + { + featureType: 'road', + elementType: 'geometry.stroke', + stylers: [ + { + color: '#212a37', + }, + ], + }, + { + featureType: 'road', + elementType: 'labels.text.fill', + stylers: [ + { + color: '#9ca5b3', + }, + ], + }, + { + featureType: 'road.highway', + elementType: 'geometry', + stylers: [ + { + color: '#746855', + }, + ], + }, + { + featureType: 'road.highway', + elementType: 'geometry.stroke', + stylers: [ + { + color: '#1f2835', + }, + ], + }, + { + featureType: 'road.highway', + elementType: 'labels.text.fill', + stylers: [ + { + color: '#f3d19c', + }, + ], + }, + { + featureType: 'transit', + elementType: 'geometry', + stylers: [ + { + color: '#2f3948', + }, + ], + }, + { + featureType: 'transit.station', + elementType: 'labels.text.fill', + stylers: [ + { + color: '#d59563', + }, + ], + }, + { + featureType: 'water', + elementType: 'geometry', + stylers: [ + { + color: '#17263c', + }, + ], + }, + { + featureType: 'water', + elementType: 'labels.text.fill', + stylers: [ + { + color: '#515c6d', + }, + ], + }, + { + featureType: 'water', + elementType: 'labels.text.stroke', + stylers: [ + { + color: '#17263c', + }, + ], + }, +]; + +class MapStyle extends React.Component { + constructor(props) { + super(props); + + this.state = { + }; + } + + render() { + return ( + + + + ); + } +} + +MapStyle.propTypes = { + provider: MapView.ProviderPropType, +}; + +const styles = StyleSheet.create({ + container: { + ...StyleSheet.absoluteFillObject, + justifyContent: 'flex-end', + alignItems: 'center', + }, + map: { + ...StyleSheet.absoluteFillObject, + }, +}); + +module.exports = MapStyle; From 6a978b37dcf655c5cfe33b93c9d0df48f9979f1b Mon Sep 17 00:00:00 2001 From: Ali Al Amine Date: Tue, 22 Nov 2016 22:07:41 +0200 Subject: [PATCH 0158/1148] Adds support to ios for the google maps styling customMapStyle prop (#817) --- components/MapView.js | 18 ++++++++++++++---- ios/AirGoogleMaps/AIRGoogleMap.h | 1 + ios/AirGoogleMaps/AIRGoogleMap.m | 12 ++++++++++++ ios/AirGoogleMaps/AIRGoogleMapManager.m | 1 + 4 files changed, 28 insertions(+), 4 deletions(-) diff --git a/components/MapView.js b/components/MapView.js index 25f29881f..91e0c14b1 100644 --- a/components/MapView.js +++ b/components/MapView.js @@ -400,16 +400,26 @@ class MapView extends React.Component { } } + componentDidMount() { + const { isReady } = this.state; + if (isReady) { + this._updateStyle(); + } + } + + _updateStyle() { + const { customMapStyle } = this.props; + this.map.setNativeProps({ customMapStyleString: JSON.stringify(customMapStyle) }); + } + _onMapReady() { - const { region, initialRegion, customMapStyle } = this.props; + const { region, initialRegion } = this.props; if (region) { this.map.setNativeProps({ region }); } else if (initialRegion) { this.map.setNativeProps({ region: initialRegion }); } - if (customMapStyle) { - this.map.setNativeProps({ customMapStyleString: JSON.stringify(customMapStyle) }); - } + this._updateStyle(); this.setState({ isReady: true }); } diff --git a/ios/AirGoogleMaps/AIRGoogleMap.h b/ios/AirGoogleMaps/AIRGoogleMap.h index 52480974a..bf16a2ef4 100644 --- a/ios/AirGoogleMaps/AIRGoogleMap.h +++ b/ios/AirGoogleMaps/AIRGoogleMap.h @@ -17,6 +17,7 @@ // TODO: don't use MK region? @property (nonatomic, assign) MKCoordinateRegion initialRegion; @property (nonatomic, assign) MKCoordinateRegion region; +@property (nonatomic, assign) NSString *customMapStyleString; @property (nonatomic, copy) RCTBubblingEventBlock onPress; @property (nonatomic, copy) RCTBubblingEventBlock onLongPress; @property (nonatomic, copy) RCTBubblingEventBlock onMarkerPress; diff --git a/ios/AirGoogleMaps/AIRGoogleMap.m b/ios/AirGoogleMaps/AIRGoogleMap.m index 9da6a64e7..50f148eb1 100644 --- a/ios/AirGoogleMaps/AIRGoogleMap.m +++ b/ios/AirGoogleMaps/AIRGoogleMap.m @@ -238,6 +238,18 @@ - (void)setShowsCompass:(BOOL)showsCompass { self.settings.compassButton = showsCompass; } +- (void)setCustomMapStyleString:(NSString *)customMapStyleString { + NSError *error; + + GMSMapStyle *style = [GMSMapStyle styleWithJSONString:customMapStyleString error:&error]; + + if (!style) { + NSLog(@"The style definition could not be loaded: %@", error); + } + + self.mapStyle = style; +} + - (BOOL)showsCompass { return self.settings.compassButton; } diff --git a/ios/AirGoogleMaps/AIRGoogleMapManager.m b/ios/AirGoogleMaps/AIRGoogleMapManager.m index f658fc6ce..a04186e7e 100644 --- a/ios/AirGoogleMaps/AIRGoogleMapManager.m +++ b/ios/AirGoogleMaps/AIRGoogleMapManager.m @@ -56,6 +56,7 @@ - (UIView *)view RCT_EXPORT_VIEW_PROPERTY(scrollEnabled, BOOL) RCT_EXPORT_VIEW_PROPERTY(pitchEnabled, BOOL) RCT_EXPORT_VIEW_PROPERTY(showsUserLocation, BOOL) +RCT_EXPORT_VIEW_PROPERTY(customMapStyleString, NSString) RCT_EXPORT_VIEW_PROPERTY(onPress, RCTBubblingEventBlock) RCT_EXPORT_VIEW_PROPERTY(onLongPress, RCTBubblingEventBlock) RCT_EXPORT_VIEW_PROPERTY(onChange, RCTBubblingEventBlock) From 7421dd98c0e7d110cf82337f7cb5d61ec42ec4f4 Mon Sep 17 00:00:00 2001 From: Peter Pistorius Date: Mon, 28 Nov 2016 20:47:36 +0100 Subject: [PATCH 0159/1148] Clarified documentation for `onRegionChange` (#836) --- docs/mapview.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/mapview.md b/docs/mapview.md index c3e5e0bea..3b11e6273 100644 --- a/docs/mapview.md +++ b/docs/mapview.md @@ -34,8 +34,8 @@ | Event Name | Returns | Notes |---|---|---| -| `onRegionChange` | `Region` | Callback that is called continuously when the user is dragging the map. -| `onRegionChangeComplete` | `Region` | Callback that is called once, when the user is done moving the map. +| `onRegionChange` | `Region` | Callback that is called continuously when the region changes, such as when a user is dragging the map. +| `onRegionChangeComplete` | `Region` | Callback that is called once when the region changes, such as when the user is done moving the map. | `onPress` | `{ coordinate: LatLng, position: Point }` | Callback that is called when user taps on the map. | `onPanDrag` | `{ coordinate: LatLng, position: Point }` | Callback that is called when user presses and drags the map. **NOTE**: for iOS `scrollEnabled` should be set to false to trigger the event | `onLongPress` | `{ coordinate: LatLng, position: Point }` | Callback that is called when user makes a "long press" somewhere on the map. From fd2219fe101940bf999969e6601127a35f30cc1a Mon Sep 17 00:00:00 2001 From: Peter Pistorius Date: Tue, 29 Nov 2016 18:53:22 +0100 Subject: [PATCH 0160/1148] Added more help to the Podfile. (#838) --- example/ios/Podfile | 1 + 1 file changed, 1 insertion(+) diff --git a/example/ios/Podfile b/example/ios/Podfile index 085aad454..4da2704b9 100644 --- a/example/ios/Podfile +++ b/example/ios/Podfile @@ -8,6 +8,7 @@ source 'https://github.com/CocoaPods/Specs.git' platform :ios, '8.0' use_frameworks! +# Change 'AirMapsExplorer' to match the target in your Xcode project. target 'AirMapsExplorer' do pod 'React', path: '../node_modules/react-native', :subspecs => [ 'Core', From f1b478bcd87686eead01809d17a1443dc37f384f Mon Sep 17 00:00:00 2001 From: Gilles Date: Wed, 30 Nov 2016 15:10:22 -0800 Subject: [PATCH 0161/1148] Add support for polygon holes for Apple Maps and Google Maps on iOS (#801) * Add support for polygon holes for Apple Maps and Google Maps on iOS * Add PropTypes for polygon holes * Add support for polygon holes in Polygon Creator example --- components/MapPolygon.js | 11 ++++ example/examples/PolygonCreator.js | 62 ++++++++++++++++++- ios/AirGoogleMaps/AIRGoogleMapPolygon.h | 1 + ios/AirGoogleMaps/AIRGoogleMapPolygon.m | 21 +++++++ .../AIRGoogleMapPolygonManager.m | 1 + ios/AirMaps/AIRMapPolygon.h | 4 +- ios/AirMaps/AIRMapPolygon.m | 22 ++++++- ios/AirMaps/AIRMapPolygonManager.m | 1 + ios/AirMaps/RCTConvert+MoreMapKit.m | 7 ++- 9 files changed, 124 insertions(+), 6 deletions(-) diff --git a/components/MapPolygon.js b/components/MapPolygon.js index d04b7e0e3..38c972e0c 100644 --- a/components/MapPolygon.js +++ b/components/MapPolygon.js @@ -21,6 +21,17 @@ const propTypes = { longitude: PropTypes.number.isRequired, })), + /** + * An array of array of coordinates to describe the polygon holes + */ + holes: PropTypes.arrayOf(PropTypes.arrayOf(PropTypes.shape({ + /** + * Latitude/Longitude coordinates + */ + latitude: PropTypes.number.isRequired, + longitude: PropTypes.number.isRequired, + }))), + /** * Callback that is called when the user presses on the polygon */ diff --git a/example/examples/PolygonCreator.js b/example/examples/PolygonCreator.js index 99b02809e..c0d1e44f5 100644 --- a/example/examples/PolygonCreator.js +++ b/example/examples/PolygonCreator.js @@ -31,6 +31,7 @@ class PolygonCreator extends React.Component { }, polygons: [], editing: null, + creatingHole: false, }; } @@ -39,19 +40,49 @@ class PolygonCreator extends React.Component { this.setState({ polygons: [...polygons, editing], editing: null, + creatingHole: false, }); } + createHole() { + const { editing, creatingHole } = this.state; + if (!creatingHole) { + this.setState({ + creatingHole: true, + editing: { + ...editing, + holes: [ + ...editing.holes, + [], + ], + }, + }); + } else { + const holes = [...editing.holes]; + if (holes[holes.length - 1].length === 0) { + holes.pop(); + this.setState({ + editing: { + ...editing, + holes, + }, + }); + } + this.setState({ creatingHole: false }); + } + } + onPress(e) { - const { editing } = this.state; + const { editing, creatingHole } = this.state; if (!editing) { this.setState({ editing: { id: id++, coordinates: [e.nativeEvent.coordinate], + holes: [], }, }); - } else { + } else if (!creatingHole) { this.setState({ editing: { ...editing, @@ -61,6 +92,22 @@ class PolygonCreator extends React.Component { ], }, }); + } else { + const holes = [...editing.holes]; + holes[holes.length - 1] = [ + ...holes[holes.length - 1], + e.nativeEvent.coordinate, + ]; + this.setState({ + editing: { + ...editing, + id: id++, // keep incrementing id to trigger display refresh + coordinates: [ + ...editing.coordinates, + ], + holes, + }, + }); } } @@ -88,6 +135,7 @@ class PolygonCreator extends React.Component { + {this.state.editing && ( + this.createHole()} + style={[styles.bubble, styles.button]} + > + {this.state.creatingHole ? 'Finish Hole' : 'Create Hole'} + + )} {this.state.editing && ( this.finish()} diff --git a/ios/AirGoogleMaps/AIRGoogleMapPolygon.h b/ios/AirGoogleMaps/AIRGoogleMapPolygon.h index 26f0236d8..12a207128 100644 --- a/ios/AirGoogleMaps/AIRGoogleMapPolygon.h +++ b/ios/AirGoogleMaps/AIRGoogleMapPolygon.h @@ -11,6 +11,7 @@ @property (nonatomic, strong) GMSPolygon *polygon; @property (nonatomic, strong) NSArray *coordinates; +@property (nonatomic, strong) NSArray *> *holes; @property (nonatomic, assign) UIColor *fillColor; @property (nonatomic, assign) double strokeWidth; diff --git a/ios/AirGoogleMaps/AIRGoogleMapPolygon.m b/ios/AirGoogleMaps/AIRGoogleMapPolygon.m index 8727cad37..ea31b5008 100644 --- a/ios/AirGoogleMaps/AIRGoogleMapPolygon.m +++ b/ios/AirGoogleMaps/AIRGoogleMapPolygon.m @@ -31,6 +31,27 @@ - (void)setCoordinates:(NSArray *)coordinates _polygon.path = path; } +- (void)setHoles:(NSArray *> *)holes +{ + _holes = holes; + + if (holes.count) + { + NSMutableArray *interiorPolygons = [NSMutableArray array]; + for(int h = 0; h < holes.count; h++) + { + GMSMutablePath *path = [GMSMutablePath path]; + for(int i = 0; i < holes[h].count; i++) + { + [path addCoordinate:holes[h][i].coordinate]; + } + [interiorPolygons addObject:path]; + } + + _polygon.holes = interiorPolygons; + } +} + -(void)setFillColor:(UIColor *)fillColor { _fillColor = fillColor; diff --git a/ios/AirGoogleMaps/AIRGoogleMapPolygonManager.m b/ios/AirGoogleMaps/AIRGoogleMapPolygonManager.m index 5e6c8d319..383bb6527 100644 --- a/ios/AirGoogleMaps/AIRGoogleMapPolygonManager.m +++ b/ios/AirGoogleMaps/AIRGoogleMapPolygonManager.m @@ -29,6 +29,7 @@ - (UIView *)view } RCT_EXPORT_VIEW_PROPERTY(coordinates, AIRMapCoordinateArray) +RCT_EXPORT_VIEW_PROPERTY(holes, AIRMapCoordinateArrayArray) RCT_EXPORT_VIEW_PROPERTY(fillColor, UIColor) RCT_EXPORT_VIEW_PROPERTY(strokeWidth, double) RCT_EXPORT_VIEW_PROPERTY(strokeColor, UIColor) diff --git a/ios/AirMaps/AIRMapPolygon.h b/ios/AirMaps/AIRMapPolygon.h index 7c471b04c..d028e67fb 100644 --- a/ios/AirMaps/AIRMapPolygon.h +++ b/ios/AirMaps/AIRMapPolygon.h @@ -22,8 +22,10 @@ @property (nonatomic, strong) MKPolygon *polygon; @property (nonatomic, strong) MKPolygonRenderer *renderer; +@property (nonatomic, strong) NSArray *interiorPolygons; @property (nonatomic, strong) NSArray *coordinates; +@property (nonatomic, strong) NSArray *> *holes; @property (nonatomic, strong) UIColor *fillColor; @property (nonatomic, strong) UIColor *strokeColor; @property (nonatomic, assign) CGFloat strokeWidth; @@ -41,4 +43,4 @@ - (BOOL)intersectsMapRect:(MKMapRect)mapRect; - (BOOL)canReplaceMapContent; -@end \ No newline at end of file +@end diff --git a/ios/AirMaps/AIRMapPolygon.m b/ios/AirMaps/AIRMapPolygon.m index e3784cf26..3ee378d0f 100644 --- a/ios/AirMaps/AIRMapPolygon.m +++ b/ios/AirMaps/AIRMapPolygon.m @@ -58,13 +58,31 @@ - (void)setCoordinates:(NSArray *)coordinates { { coords[i] = coordinates[i].coordinate; } - self.polygon = [MKPolygon polygonWithCoordinates:coords count:coordinates.count]; + self.polygon = [MKPolygon polygonWithCoordinates:coords count:coordinates.count interiorPolygons:_interiorPolygons]; // TODO: we could lazy-initialize the polygon, since we don't need it until the // polygon is in view. self.renderer = [[MKPolygonRenderer alloc] initWithPolygon:self.polygon]; [self update]; } +- (void)setHoles:(NSArray *> *)holes { + _holes = holes; + if (holes.count) + { + NSMutableArray *polygons = [NSMutableArray array]; + for(int h = 0; h < holes.count; h++) + { + CLLocationCoordinate2D coords[holes[h].count]; + for(int i = 0; i < holes[h].count; i++) + { + coords[i] = holes[h][i].coordinate; + } + [polygons addObject:[MKPolygon polygonWithCoordinates:coords count:holes[h].count]]; + } + _interiorPolygons = polygons; + } +} + - (void) update { if (!_renderer) return; @@ -157,4 +175,4 @@ - (BOOL)canReplaceMapContent -@end \ No newline at end of file +@end diff --git a/ios/AirMaps/AIRMapPolygonManager.m b/ios/AirMaps/AIRMapPolygonManager.m index bfc253f6c..1299dee12 100644 --- a/ios/AirMaps/AIRMapPolygonManager.m +++ b/ios/AirMaps/AIRMapPolygonManager.m @@ -34,6 +34,7 @@ - (UIView *)view } RCT_EXPORT_VIEW_PROPERTY(coordinates, AIRMapCoordinateArray) +RCT_EXPORT_VIEW_PROPERTY(holes, AIRMapCoordinateArrayArray) RCT_EXPORT_VIEW_PROPERTY(fillColor, UIColor) RCT_EXPORT_VIEW_PROPERTY(strokeColor, UIColor) RCT_EXPORT_VIEW_PROPERTY(strokeWidth, CGFloat) diff --git a/ios/AirMaps/RCTConvert+MoreMapKit.m b/ios/AirMaps/RCTConvert+MoreMapKit.m index 2292cb878..9f18553d1 100644 --- a/ios/AirMaps/RCTConvert+MoreMapKit.m +++ b/ios/AirMaps/RCTConvert+MoreMapKit.m @@ -24,4 +24,9 @@ + (AIRMapCoordinate *)AIRMapCoordinate:(id)json RCT_ARRAY_CONVERTER(AIRMapCoordinate) -@end \ No newline at end of file ++ (NSArray *> *)AIRMapCoordinateArrayArray:(id)json +{ + return RCTConvertArrayValue(@selector(AIRMapCoordinateArray:), json); +} + +@end From a39f1b2c84b47639c491207582a1d5fba1f99350 Mon Sep 17 00:00:00 2001 From: Sascha Knobloch Date: Tue, 6 Dec 2016 11:26:55 +0100 Subject: [PATCH 0162/1148] Update mapview.md (#855) --- docs/mapview.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/mapview.md b/docs/mapview.md index 3b11e6273..50d1ac4cb 100644 --- a/docs/mapview.md +++ b/docs/mapview.md @@ -27,7 +27,7 @@ | `loadingEnabled` | `Boolean` | `false` | If `true` a loading indicator will show while the map is loading. | `loadingIndicatorColor` | `Color` | `#606060` | Sets loading indicator color, default to `#606060`. | `loadingBackgroundColor` | `Color` | `#FFFFFF` | Sets loading background color, default to `#FFFFFF`. - +| `moveOnMarkerPress` | `Boolean` | `true` | `Android only` If `false` the map won't move when a marker is pressed. ## Events From 792406d93bb46ab9f85dfb8bf0d3130d5d0bd0b5 Mon Sep 17 00:00:00 2001 From: Kovacs Nicolas Date: Tue, 6 Dec 2016 11:27:36 +0100 Subject: [PATCH 0163/1148] Update installation (#847) Help fixing issue blank map on android --- docs/installation.md | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/docs/installation.md b/docs/installation.md index c14995999..71fccd75b 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -109,7 +109,7 @@ Source: https://developers.google.com/maps/documentation/android-api/signup ## Troubleshooting -If you have a blank map issue, ([#118](https://github.com/airbnb/react-native-maps/issues/118), [#176](https://github.com/airbnb/react-native-maps/issues/176)) try the following lines : +If you have a blank map issue, ([#118](https://github.com/airbnb/react-native-maps/issues/118), [#176](https://github.com/airbnb/react-native-maps/issues/176), [#684](https://github.com/airbnb/react-native-maps/issues/684)), try the following lines : ### On iOS: @@ -120,6 +120,19 @@ You have to link dependencies with rnpm and re-run the build: ### On Android: +1. Be sure to have `new MapsPackage()` in your `MainApplication.java` : + ``` + import com.airbnb.android.react.maps.MapsPackage; + ... + @Override + protected List getPackages() { + return Arrays.asList( + new MainReactPackage(), + new MapsPackage() + ); + } + ``` + 1. Set this Stylesheet in your map component ``` ... From 8e7f854e939a2be5488dc01489e25234b86d4ae3 Mon Sep 17 00:00:00 2001 From: Seph Soliman Date: Tue, 6 Dec 2016 20:44:52 +0100 Subject: [PATCH 0164/1148] Fixes #470. Support legalLabelInsets on Apple Maps (#840) * Fixes #470 for iOS and Apple Maps This will add support for `legalLabelInsets` prop on iOS with Apple Maps. Code is adapted from RN core. * Pluralize updateLegalLabelInset(s) for consistency * Removed arrow notation * Added legalLabelInsets example --- example/App.js | 2 + example/examples/LegalLabel.js | 113 +++++++++++++++++++++++++++++++++ ios/AirMaps/AIRMap.m | 20 ++++++ 3 files changed, 135 insertions(+) create mode 100644 example/examples/LegalLabel.js diff --git a/example/App.js b/example/App.js index abd02acd2..696682ba0 100644 --- a/example/App.js +++ b/example/App.js @@ -32,6 +32,7 @@ import CustomTiles from './examples/CustomTiles'; import ZIndexMarkers from './examples/ZIndexMarkers'; import StaticMap from './examples/StaticMap'; import MapStyle from './examples/MapStyle'; +import LegalLabel from './examples/LegalLabel'; const IOS = Platform.OS === 'ios'; const ANDROID = Platform.OS === 'android'; @@ -142,6 +143,7 @@ class App extends React.Component { [CustomTiles, 'Custom Tiles', true], [ZIndexMarkers, 'Position Markers with Z-index', true], [MapStyle, 'Customize the style of the map', true], + [LegalLabel, 'Reposition the legal label', true], ] // Filter out examples that are not yet supported for Google Maps on iOS. .filter(example => ANDROID || (IOS && (example[2] || !this.state.useGoogleMaps))) diff --git a/example/examples/LegalLabel.js b/example/examples/LegalLabel.js new file mode 100644 index 000000000..7715648f7 --- /dev/null +++ b/example/examples/LegalLabel.js @@ -0,0 +1,113 @@ +import React from 'react'; +import { + StyleSheet, + View, + Text, + Dimensions, +} from 'react-native'; + +import MapView from 'react-native-maps'; + +const screen = Dimensions.get('window'); + +class LegalLabel extends React.Component { + static propTypes = { + provider: MapView.ProviderPropType, + } + + render() { + const latlng = { + latitude: 37.78825, + longitude: -122.4324, + }; + + const ASPECT_RATIO = screen.width / screen.height; + const LATITUDE_DELTA = 0.0922; + const LONGITUDE_DELTA = LATITUDE_DELTA * ASPECT_RATIO; + + return ( + + + + + + + Username + + + + + Bio description lorem ipsum Ullamco exercitation + aliqua ullamco nostrud dolor et aliquip fugiat do + aute fugiat velit in aliqua sit. + + + + + + + Profile Photo + + + + + ); + } +} + +const padding = 10; +const photoSize = 80; +const mapHeight = screen.height - 130; +const styles = StyleSheet.create({ + bio: { + marginHorizontal: padding, + marginBottom: 0, + paddingVertical: padding / 2, + }, + bioText: { + fontSize: 16, + lineHeight: 16 * 1.5, + }, + username: { + paddingLeft: photoSize + padding + padding, + paddingTop: padding, + }, + usernameText: { + fontSize: 36, + lineHeight: 36, + }, + photo: { + padding: 2, + position: 'absolute', + top: mapHeight - (photoSize / 2), + left: padding, + borderRadius: 5, + borderWidth: StyleSheet.hairlineWidth, + backgroundColor: '#ccc', + width: photoSize, + height: photoSize, + }, + photoInner: { + alignItems: 'center', + justifyContent: 'center', + flex: 1, + }, + photoText: { + fontSize: 9, + textAlign: 'center', + }, + map: { + height: mapHeight, + }, +}); + +module.exports = LegalLabel; diff --git a/ios/AirMaps/AIRMap.m b/ios/AirMaps/AIRMap.m index 9efe1b4aa..9683bfd3a 100644 --- a/ios/AirMaps/AIRMap.m +++ b/ios/AirMaps/AIRMap.m @@ -381,6 +381,26 @@ - (void)cacheViewIfNeeded { [self updateScrollEnabled]; [self updateZoomEnabled]; + [self updateLegalLabelInsets]; + } +} + +- (void)updateLegalLabelInsets { + if (_legalLabel) { + dispatch_async(dispatch_get_main_queue(), ^{ + CGRect frame = _legalLabel.frame; + if (_legalLabelInsets.left) { + frame.origin.x = _legalLabelInsets.left; + } else if (_legalLabelInsets.right) { + frame.origin.x = self.frame.size.width - _legalLabelInsets.right - frame.size.width; + } + if (_legalLabelInsets.top) { + frame.origin.y = _legalLabelInsets.top; + } else if (_legalLabelInsets.bottom) { + frame.origin.y = self.frame.size.height - _legalLabelInsets.bottom - frame.size.height; + } + _legalLabel.frame = frame; + }); } } From e0e61ad0ca1ea392d1129825201fce43c50a7a1e Mon Sep 17 00:00:00 2001 From: gilbox Date: Tue, 6 Dec 2016 13:34:18 -0800 Subject: [PATCH 0165/1148] 0.12.0 --- CHANGELOG.md | 68 ++++++++++++++++++++++++++++++++ android/gradle.properties | 2 +- react-native-google-maps.podspec | 2 +- react-native-maps.podspec | 2 +- 4 files changed, 71 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 763902cc6..e3676445e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,75 @@ # Change Log +## 0.12.0 (December 6, 2016) + +### Breaking Changes + +* [android] If we've disabled scrolling within the map, then don't capture the touch events + [#664](https://github.com/airbnb/react-native-maps/pull/664) + (@mikelambert) +* [android] Use latest Google Play Services + [#731](https://github.com/airbnb/react-native-maps/pull/731) + (@mlanter) +* [android] update google play services + [#805](https://github.com/airbnb/react-native-maps/pull/805) + (@lrivera) + +### Patches + +* [iOS] Support iOS SDK < 10 ( XCode < 8 ) + [#708](https://github.com/airbnb/react-native-maps/pull/708) + (@rops) +* [iOS] Added showsUserLocation property support for Google Maps + [#721](https://github.com/airbnb/react-native-maps/pull/721) + (@julien-rodrigues) +* [iOS] Added Google Maps Circle, Polygon, Polyline, MapType Support + [#722](https://github.com/airbnb/react-native-maps/pull/722) + (@unboundfire) +* [iOS] Fix Anchor point on Google Maps iOS + [#734](https://github.com/airbnb/react-native-maps/pull/734) + (@btoueg) +* [Google Maps iOS] Marker init with image props. + [#738](https://github.com/airbnb/react-native-maps/pull/738) + (@btoueg) +* [iOS] Fix dynamic imageSrc removal + [#737](https://github.com/airbnb/react-native-maps/pull/737) + (@btoueg) +* [iOS] implement fitToSuppliedMarkers and fitToCoordinates for google + [#750](https://github.com/airbnb/react-native-maps/pull/750) + (@gilbox) +* [iOS][android] Add onPress for polygons and polylines on iOS and Android + [#760](https://github.com/airbnb/react-native-maps/pull/760) + (@frankrowe) +* [iOS] Fix flicker of map pins on state change + [#728](https://github.com/airbnb/react-native-maps/pull/728) + (@mlanter) +* [iOS] Set region only when view has width&height + [#785](https://github.com/airbnb/react-native-maps/pull/785) + (@gilbox) +* [iOS] Implements animateToRegion for Google + [#779](https://github.com/airbnb/react-native-maps/pull/779) + (@btoueg) +* [iOS] Google Maps Custom Tile Support + [#770](https://github.com/airbnb/react-native-maps/pull/770) + (@unboundfire) +* [android] Map Styling for android + [#808](https://github.com/airbnb/react-native-maps/pull/808) + (@ali-alamine using @azt3k code) +* [iOS] IOS Google Map styling + [#817](https://github.com/airbnb/react-native-maps/pull/817) + (@ali-alamine using @azt3k code) +* [iOS] Add support for polygon holes for Apple Maps and Google Maps on iOS + [#801](https://github.com/airbnb/react-native-maps/pull/801) + (@therealgilles) +* [iOS] Fixes #470. Support legalLabelInsets on Apple Maps + [#840](https://github.com/airbnb/react-native-maps/pull/840) + (@scarlac) + ## 0.11.0 (October 16, 2016) +NOTE: `0.10.4` was released *after* this version, and it's possible +`0.11.0` does not include everything in `0.10.4`. (see #851) + ### Breaking Changes * Update example app for RN 0.35, fix Gmaps bug for 0.35 diff --git a/android/gradle.properties b/android/gradle.properties index ff024eb51..a6d6c4f56 100644 --- a/android/gradle.properties +++ b/android/gradle.properties @@ -1,5 +1,5 @@ VERSION_CODE=2 -VERSION_NAME=0.11.0 +VERSION_NAME=0.12.0 GROUP=com.airbnb.android POM_DESCRIPTION=React Native Map view component for Android diff --git a/react-native-google-maps.podspec b/react-native-google-maps.podspec index e306422cd..0ed52b808 100644 --- a/react-native-google-maps.podspec +++ b/react-native-google-maps.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "react-native-google-maps" - s.version = "0.11.0" + s.version = "0.12.0" s.summary = "React Native Mapview component for iOS + Android" s.authors = { "intelligibabble" => "leland.m.richardson@gmail.com" } diff --git a/react-native-maps.podspec b/react-native-maps.podspec index 73607d2b0..df7164453 100644 --- a/react-native-maps.podspec +++ b/react-native-maps.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "react-native-maps" - s.version = "0.11.0" + s.version = "0.12.0" s.summary = "React Native Mapview component for iOS + Android" s.authors = { "intelligibabble" => "leland.m.richardson@gmail.com" } From 0f05de9cc355e9e2702a29c2d10adda11400c07d Mon Sep 17 00:00:00 2001 From: gilbox Date: Tue, 6 Dec 2016 13:39:20 -0800 Subject: [PATCH 0166/1148] 0.12.1 --- CHANGELOG.md | 6 ++++++ android/gradle.properties | 2 +- package.json | 2 +- react-native-google-maps.podspec | 2 +- react-native-maps.podspec | 2 +- 5 files changed, 10 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e3676445e..6e9de4544 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,13 @@ # Change Log +## 0.12.1 (December 6, 2016) + +This release only corrects the version in package.json. + ## 0.12.0 (December 6, 2016) +NOTE: This version was not published because package.json was not properly updated + ### Breaking Changes * [android] If we've disabled scrolling within the map, then don't capture the touch events diff --git a/android/gradle.properties b/android/gradle.properties index a6d6c4f56..2423c0458 100644 --- a/android/gradle.properties +++ b/android/gradle.properties @@ -1,5 +1,5 @@ VERSION_CODE=2 -VERSION_NAME=0.12.0 +VERSION_NAME=0.12.1 GROUP=com.airbnb.android POM_DESCRIPTION=React Native Map view component for Android diff --git a/package.json b/package.json index e611648f0..3967b5b80 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "description": "React Native Mapview component for iOS + Android", "main": "index.js", "author": "Leland Richardson ", - "version": "0.11.0", + "version": "0.12.1", "scripts": { "start": "react-native start", "lint": "eslint ." diff --git a/react-native-google-maps.podspec b/react-native-google-maps.podspec index 0ed52b808..3e4ff9756 100644 --- a/react-native-google-maps.podspec +++ b/react-native-google-maps.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "react-native-google-maps" - s.version = "0.12.0" + s.version = "0.12.1" s.summary = "React Native Mapview component for iOS + Android" s.authors = { "intelligibabble" => "leland.m.richardson@gmail.com" } diff --git a/react-native-maps.podspec b/react-native-maps.podspec index df7164453..ef9df382c 100644 --- a/react-native-maps.podspec +++ b/react-native-maps.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "react-native-maps" - s.version = "0.12.0" + s.version = "0.12.1" s.summary = "React Native Mapview component for iOS + Android" s.authors = { "intelligibabble" => "leland.m.richardson@gmail.com" } From 6eb18321523b40fc652c3993475115432e500eb2 Mon Sep 17 00:00:00 2001 From: Diogo do Carmo Date: Wed, 7 Dec 2016 19:39:58 -0200 Subject: [PATCH 0167/1148] Update mapview.md (#866) * Update mapview.md Updated documentation to match the example here (https://github.com/airbnb/react-native-maps/blob/master/example/examples/FitToCoordinates.js) * Changed name from 'arguments' to 'options' --- docs/mapview.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/mapview.md b/docs/mapview.md index 50d1ac4cb..a10fbe58d 100644 --- a/docs/mapview.md +++ b/docs/mapview.md @@ -57,7 +57,7 @@ | `animateToCoordinate` | `region: Coordinate`, `duration: Number` | | `fitToElements` | `animated: Boolean` | | `fitToSuppliedMarkers` | `markerIDs: String[]` | If you need to use this in `ComponentDidMount`, make sure you put it in a timeout or it will cause performance problems. -| `fitToCoordinates` | `coordinates: Array, edgePadding: EdgePadding, animated: Boolean` | +| `fitToCoordinates` | `coordinates: Array, options: { edgePadding: EdgePadding, animated: Boolean }` | From 8d654fba132e7c0cf7018f6ae7206eb2540470af Mon Sep 17 00:00:00 2001 From: Arman Date: Fri, 9 Dec 2016 00:56:23 +0330 Subject: [PATCH 0168/1148] Added rotation attribute (#871) --- docs/marker.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/marker.md b/docs/marker.md index 60da4c0f7..dee0e019d 100644 --- a/docs/marker.md +++ b/docs/marker.md @@ -15,6 +15,7 @@ | `calloutAnchor` | `Point` | | Specifies the point in the marker image at which to anchor the callout when it is displayed. This is specified in the same coordinate system as the anchor. See the `anchor` prop for more details.

The default is the top middle of the image.

For ios, see the `calloutOffset` prop. | `flat` | `Boolean` | | Sets whether this marker should be flat against the map true or a billboard facing the camera false. | `identifier` | `String` | | An identifier used to reference this marker at a later date. +| `rotation` | `Float` | | A float number indicating marker's rotation angle. ## Events From 7869dfd277d59d8738f2d851d029a43c6bf5a3b9 Mon Sep 17 00:00:00 2001 From: Seph Soliman Date: Thu, 8 Dec 2016 22:41:21 +0100 Subject: [PATCH 0169/1148] Allow legalLabelInsets to be changed and animated (#873) * Allow legalLabelInsets to be changed and animated Updated example to include a button to animate the legal label. * Docs for legalLabelInsets prop While structurally identical to EdgePadding, they serve completely different purposes. Default left empty since it's an OS default (around {left: 10, bottom: 10}) * Spacing / linting --- docs/mapview.md | 10 +++++++++ example/examples/LegalLabel.js | 38 ++++++++++++++++++++++++++++++++-- ios/AirMaps/AIRMap.m | 6 ++++++ 3 files changed, 52 insertions(+), 2 deletions(-) diff --git a/docs/mapview.md b/docs/mapview.md index a10fbe58d..f05867bd2 100644 --- a/docs/mapview.md +++ b/docs/mapview.md @@ -28,6 +28,7 @@ | `loadingIndicatorColor` | `Color` | `#606060` | Sets loading indicator color, default to `#606060`. | `loadingBackgroundColor` | `Color` | `#FFFFFF` | Sets loading background color, default to `#FFFFFF`. | `moveOnMarkerPress` | `Boolean` | `true` | `Android only` If `false` the map won't move when a marker is pressed. +| `legalLabelInsets` | `EdgeInsets` | | If set, changes the position of the "Legal" label link from the OS default. **Note:** iOS only. ## Events @@ -103,3 +104,12 @@ type EdgePadding { left: Number } ``` + +``` +type EdgeInsets { + top: Number, + left: Number, + bottom: Number, + right: Number +} +``` \ No newline at end of file diff --git a/example/examples/LegalLabel.js b/example/examples/LegalLabel.js index 7715648f7..6d5894c85 100644 --- a/example/examples/LegalLabel.js +++ b/example/examples/LegalLabel.js @@ -3,7 +3,9 @@ import { StyleSheet, View, Text, + Animated, Dimensions, + TouchableOpacity, } from 'react-native'; import MapView from 'react-native-maps'; @@ -15,6 +17,34 @@ class LegalLabel extends React.Component { provider: MapView.ProviderPropType, } + state = { + _legalLabelPositionY: new Animated.Value(10), + legalLabelPositionY: 10, + } + + componentDidMount() { + this.state._legalLabelPositionY.addListener(({ value }) => { + this.setState({ + legalLabelPositionY: value, + }); + }); + } + + componentWillUnmount() { + this.state._legalLabelPositionY.removeAllListeners(); + } + + onPressAnimate = () => { + Animated.sequence([ + Animated.spring(this.state._legalLabelPositionY, { + toValue: 100, + }), + Animated.spring(this.state._legalLabelPositionY, { + toValue: 10, + }), + ]).start(); + } + render() { const latlng = { latitude: 37.78825, @@ -30,7 +60,7 @@ class LegalLabel extends React.Component { - Username + + Animate + @@ -84,6 +116,8 @@ const styles = StyleSheet.create({ usernameText: { fontSize: 36, lineHeight: 36, + color: 'blue', + textDecorationLine: 'underline', }, photo: { padding: 2, diff --git a/ios/AirMaps/AIRMap.m b/ios/AirMaps/AIRMap.m index 9683bfd3a..4c2d164c9 100644 --- a/ios/AirMaps/AIRMap.m +++ b/ios/AirMaps/AIRMap.m @@ -404,6 +404,12 @@ - (void)updateLegalLabelInsets { } } + +- (void)setLegalLabelInsets:(UIEdgeInsets)legalLabelInsets { + _legalLabelInsets = legalLabelInsets; + [self updateLegalLabelInsets]; +} + - (void)beginLoading { if ((!self.hasShownInitialLoading && self.loadingEnabled) || (self.cacheEnabled && self.cacheImageView.image == nil)) { self.loadingView.hidden = NO; From 5a7b55f5ff7a01ac14d334cae17790085f44d8d8 Mon Sep 17 00:00:00 2001 From: Spike Brehm Date: Fri, 9 Dec 2016 16:08:12 -0800 Subject: [PATCH 0170/1148] 0.12.2 --- CHANGELOG.md | 16 ++++++++++++++++ android/gradle.properties | 2 +- package.json | 2 +- react-native-google-maps.podspec | 2 +- react-native-maps.podspec | 2 +- 5 files changed, 20 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6e9de4544..9d92f700c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,21 @@ # Change Log +## 0.12.2 (December 9, 2016) + +* [Android] Added support for taking snapshots on Android + [#625](https://github.com/airbnb/react-native-maps/pull/625) + (@IjzerenHein) +* [iOS] Allow legalLabelInsets to be changed and animated + [#873](https://github.com/airbnb/react-native-maps/pull/873) + (@scarlac) +* Added rotation attribute documentation + [#](https://github.com/airbnb/react-native-maps/pull/) + (@Arman92) +* Update mapview.md documentation + [#866](https://github.com/airbnb/react-native-maps/pull/866) + (@dccarmo) + + ## 0.12.1 (December 6, 2016) This release only corrects the version in package.json. diff --git a/android/gradle.properties b/android/gradle.properties index 2423c0458..efa308fce 100644 --- a/android/gradle.properties +++ b/android/gradle.properties @@ -1,5 +1,5 @@ VERSION_CODE=2 -VERSION_NAME=0.12.1 +VERSION_NAME=0.12.2 GROUP=com.airbnb.android POM_DESCRIPTION=React Native Map view component for Android diff --git a/package.json b/package.json index 3967b5b80..c7f56595e 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "description": "React Native Mapview component for iOS + Android", "main": "index.js", "author": "Leland Richardson ", - "version": "0.12.1", + "version": "0.12.2", "scripts": { "start": "react-native start", "lint": "eslint ." diff --git a/react-native-google-maps.podspec b/react-native-google-maps.podspec index 3e4ff9756..e32dda3be 100644 --- a/react-native-google-maps.podspec +++ b/react-native-google-maps.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "react-native-google-maps" - s.version = "0.12.1" + s.version = "0.12.2" s.summary = "React Native Mapview component for iOS + Android" s.authors = { "intelligibabble" => "leland.m.richardson@gmail.com" } diff --git a/react-native-maps.podspec b/react-native-maps.podspec index ef9df382c..cb2cffa26 100644 --- a/react-native-maps.podspec +++ b/react-native-maps.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "react-native-maps" - s.version = "0.12.1" + s.version = "0.12.2" s.summary = "React Native Mapview component for iOS + Android" s.authors = { "intelligibabble" => "leland.m.richardson@gmail.com" } From 3db28b8ae065d9509d7aff4a1cdd709b956db346 Mon Sep 17 00:00:00 2001 From: Spike Brehm Date: Fri, 9 Dec 2016 16:17:23 -0800 Subject: [PATCH 0171/1148] Update CHANGELOG; tweaks for 0.12.2 --- CHANGELOG.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9d92f700c..ab346a877 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## 0.12.2 (December 9, 2016) +### Patches + * [Android] Added support for taking snapshots on Android [#625](https://github.com/airbnb/react-native-maps/pull/625) (@IjzerenHein) @@ -9,7 +11,7 @@ [#873](https://github.com/airbnb/react-native-maps/pull/873) (@scarlac) * Added rotation attribute documentation - [#](https://github.com/airbnb/react-native-maps/pull/) + [#871](https://github.com/airbnb/react-native-maps/pull/871) (@Arman92) * Update mapview.md documentation [#866](https://github.com/airbnb/react-native-maps/pull/866) From 5de4dc7bc7b05d7e39f2da69a0b3decee7f2ba95 Mon Sep 17 00:00:00 2001 From: David Boyd Date: Sat, 17 Dec 2016 11:32:22 -0800 Subject: [PATCH 0172/1148] - Clarified what happens with "react-native link" command (#904) - Updated descriptions of getting and using Android API Keys. It works differently than when this was originally written. - Added fix for DexException - Added "import" in map component code --- docs/installation.md | 69 +++++++++++++++++++++++--------------------- 1 file changed, 36 insertions(+), 33 deletions(-) diff --git a/docs/installation.md b/docs/installation.md index 71fccd75b..512994d5e 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -6,10 +6,12 @@ First, download the library from npm: npm install react-native-maps --save ``` -Then you must install the native dependencies: You can use `rnpm` (now part of `react-native` core) to +Second, install the native dependencies: You can use `rnpm` (now part of `react-native` core via `link`) to add native dependencies automatically then continue the directions below depending on your target OS. - `$ react-native link` +``` +react-native link +``` >This installation should work in physical devices. For Genymotion, be sure to check Android installation about Google Play Services @@ -17,7 +19,7 @@ add native dependencies automatically then continue the directions below dependi ### Option 1: CocoaPods - Same as the included AirMapsExplorer example -1. Setup your `Podfile` like the included [example/ios/Podfile](../example/ios/Podfile) then run `pod install`. +1. Setup your `Podfile` like the included [example/ios/Podfile](../example/ios/Podfile), replace all references to `AirMapExplorer` with your project name, and then run `pod install`. (If you do not need `GoogleMaps` support for iOS, then you can probably completely skip this step.) 1. Open your project in Xcode workspace 1. Drag the following folder into your project: @@ -44,6 +46,8 @@ Now if you need `GoogleMaps` support you will also have to add a bunch of other After your `Podfile` is setup properly, run `pod install`. ### Option 3: Manually + >This was already done for you if you ran "react-native link" + 1. Open your project in Xcode, right click on `Libraries` and click `Add Files to "Your Project Name"` Look under `node_modules/react-native-maps/ios` and add `AIRMaps.xcodeproj`. 1. Add `libAIRMaps.a` to `Build Phases -> Link Binary With Libraries. @@ -60,6 +64,8 @@ After your `Podfile` is setup properly, run `pod install`. ## Android 1. In your `android/app/build.gradle` add: + >This step is not necessary if you ran "react-native link" + ```groovy ... dependencies { @@ -69,6 +75,8 @@ After your `Podfile` is setup properly, run `pod install`. ``` 1. In your `android/settings.gradle` add: + >This step is not necessary if you ran "react-native link" + ```groovy ... include ':react-native-maps' @@ -76,9 +84,9 @@ After your `Podfile` is setup properly, run `pod install`. ``` 1. Specify your Google Maps API Key: - > For development, it is recommended to use a ***Browser Key*** without referrer restrictions. Go to https://console.developers.google.com/apis/credentials to check your credentials. + > For development, you need to get a ***API Key***. Go to https://console.developers.google.com/apis/credentials to check your credentials. - Add your **Browser** API key to your manifest file (`android\app\src\main\AndroidManifest.xml`): + Add your API key to your manifest file (`android\app\src\main\AndroidManifest.xml`): ```xml @@ -87,18 +95,6 @@ After your `Podfile` is setup properly, run `pod install`. android:name="com.google.android.geo.API_KEY" android:value="Your Google maps API Key Here"/> - ``` - > If that doesn't work, try using an ***Android Key*** without referrer restrictions. Go to https://console.developers.google.com/apis/credentials to check your credentials. - - Add your **Android** API key to your manifest file: - - ```xml - - - - ``` > Note: As shown above, com.google.android.geo.API_KEY is the recommended metadata name for the API key. A key with this name can be used to authenticate to multiple Google Maps-based APIs on the Android platform, including the Google Maps Android API. For backwards compatibility, the API also supports the name com.google.android.maps.v2.API_KEY. This legacy name allows authentication to the Android Maps API v2 only. An application can specify only one of the API key metadata names. If both are specified, the API throws an exception. Source: https://developers.google.com/maps/documentation/android-api/signup @@ -115,12 +111,14 @@ If you have a blank map issue, ([#118](https://github.com/airbnb/react-native-ma You have to link dependencies with rnpm and re-run the build: -1. `rnpm link` +1. `react-native link` 1. `react-native run-ios` ### On Android: 1. Be sure to have `new MapsPackage()` in your `MainApplication.java` : + >This step is not necessary if you ran "react-native link" + ``` import com.airbnb.android.react.maps.MapsPackage; ... @@ -135,6 +133,7 @@ You have to link dependencies with rnpm and re-run the build: 1. Set this Stylesheet in your map component ``` + import MapView from 'react-native-maps'; ... const styles = StyleSheet.create({ container: { @@ -171,26 +170,30 @@ You have to link dependencies with rnpm and re-run the build: } } ``` -1. Run "android" and make sure every packages is updated. +1. Run "android" and make sure all packages are up-to-date. 1. If not installed yet, you have to install the following packages : - Extras / Google Play services - Extras / Google Repository - - Android 6.0 (API 23) / Google APIs Intel x86 Atom System Image Rev. 13 -1. Check manual installation steps -1. Generate your SHA1 key : - `keytool -list -v -keystore ~/.android/debug.keystore -alias androiddebugkey -storepass android -keypass android` - -1. Go to [Google API Console](https://console.developers.google.com/flows/enableapi?apiid=maps_android_backend) and select your project, or create one. -In `Overview -> Google Maps API -> Google Maps Android API ` -> Check if it's enabled -Create a new key by clicking on `Create credentials -> API Key -> Android Key`, enter the name of the API key and your SHA1 key, generated before, and create it. -Check installation step 4. - -1. Clean the cache : - `watchman watch-del-all` - `npm cache clean` + - Android 6.0 (API 23) / Google APIs Intel x86 Atom System Image Rev. 19 +1. Check manual installation steps if you didn't run "react-native link" +1. Go to [Google API Console](https://console.developers.google.com/flows/enableapi?apiid=maps_android_backend) and select your project, or create one. +Then, once enabled, select `Go to credentials`. +Select `Google Maps Android API` and create a new key. +Enter the name of the API key and create it. + +1. Clean the cache : + ``` + watchman watch-del-all + npm cache clean + ``` 1. When starting emulator, make sure you have enabled `Wipe user data`. 1. Run `react-native run-android` -1. At this step it should work, but if not, go to your [Google API Console](https://console.developers.google.com/flows/enableapi?apiid=maps_android_backend&keyType=CLIENT_SIDE_ANDROID&pli=1) and create a `Browser key` instead of a `Android key` and go to step 6. +1. If you encounter `com.android.dex.DexException: Multiple dex files define Landroid/support/v7/appcompat/R$anim`, then clear build folder. + ``` + cd android + gradlew clean + cd .. + ``` From f9246497a83526dc8f7a5359d06399419c34cdcc Mon Sep 17 00:00:00 2001 From: anami Date: Sat, 17 Dec 2016 19:32:49 +0000 Subject: [PATCH 0173/1148] Update marker.md to include the draggable prop. (#902) --- docs/marker.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/marker.md b/docs/marker.md index dee0e019d..4246befc3 100644 --- a/docs/marker.md +++ b/docs/marker.md @@ -16,6 +16,7 @@ | `flat` | `Boolean` | | Sets whether this marker should be flat against the map true or a billboard facing the camera false. | `identifier` | `String` | | An identifier used to reference this marker at a later date. | `rotation` | `Float` | | A float number indicating marker's rotation angle. +| `draggable` | `` | | This is a non-value based prop. Adding this allows the marker to be draggable (re-positioned). ## Events From 4a055c0d3bc5b7d1166e55e4322bba52c2de8b17 Mon Sep 17 00:00:00 2001 From: Ali Al Amine Date: Tue, 27 Dec 2016 20:23:03 +0200 Subject: [PATCH 0174/1148] [doc, android] Adding section to fix gradle problems (#910) * Updating the android installation docs This adds a method to fix the mismatch between the play-services in case the user wants to use a different version * Fix syntax for some versions of gradle Fixed some syntax as suggested by @Froelund as the previous one doesn't work on some versions of gradle. --- docs/installation.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/docs/installation.md b/docs/installation.md index 512994d5e..80c604ac5 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -73,6 +73,21 @@ After your `Podfile` is setup properly, run `pod install`. compile project(':react-native-maps') } ``` + + If you have a different play serivces than the one included in this library, use the following instead (switch 10.0.1 for the desired version): + + ```groovy + ... + dependencies { + ... + compile(project(':react-native-maps')){ + exclude group: 'com.google.android.gms', module: 'play-services-base' + exclude group: 'com.google.android.gms', module: 'play-services-maps' + } + compile 'com.google.android.gms:play-services-base:10.0.1' + compile 'com.google.android.gms:play-services-maps:10.0.1' + } + ``` 1. In your `android/settings.gradle` add: >This step is not necessary if you ran "react-native link" From a6d345d3c9644e787ce389916b20d717934e5d6f Mon Sep 17 00:00:00 2001 From: Javier Cuevas Date: Tue, 27 Dec 2016 19:23:34 +0100 Subject: [PATCH 0175/1148] =?UTF-8?q?Fix=20=E2=80=9CAnimating=20with=20Map?= =?UTF-8?q?Views=E2=80=9D=20example=20=E2=80=93=C2=A0fixes=20#763=20(#888)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- example/examples/AnimatedViews.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/example/examples/AnimatedViews.js b/example/examples/AnimatedViews.js index eea711905..884f11a37 100644 --- a/example/examples/AnimatedViews.js +++ b/example/examples/AnimatedViews.js @@ -191,7 +191,7 @@ class AnimatedViews extends React.Component { scale, translateY, markers, - region: new Animated.Region({ + region: new MapView.AnimatedRegion({ latitude: LATITUDE, longitude: LONGITUDE, latitudeDelta: LATITUDE_DELTA, @@ -220,7 +220,7 @@ class AnimatedViews extends React.Component { }).start(); } - onStartShouldSetPanResponder(e) { + onStartShouldSetPanResponder = (e) => { // we only want to move the view if they are starting the gesture on top // of the view, so this calculates that and returns true if so. If we return // false, the gesture should get passed to the map view appropriately. @@ -232,7 +232,7 @@ class AnimatedViews extends React.Component { return topOfTap < topOfMainWindow; } - onMoveShouldSetPanResponder(e) { + onMoveShouldSetPanResponder = (e) => { const { panY } = this.state; const { pageY } = e.nativeEvent; const topOfMainWindow = ITEM_PREVIEW_HEIGHT + panY.__getValue(); @@ -241,7 +241,7 @@ class AnimatedViews extends React.Component { return topOfTap < topOfMainWindow; } - onPanXChange({ value }) { + onPanXChange = ({ value }) => { const { index } = this.state; const newIndex = Math.floor(((-1 * value) + (SNAP_WIDTH / 2)) / SNAP_WIDTH); if (index !== newIndex) { @@ -249,7 +249,7 @@ class AnimatedViews extends React.Component { } } - onPanYChange({ value }) { + onPanYChange = ({ value }) => { const { canMoveHorizontal, region, scrollY, scrollX, markers, index } = this.state; const shouldBeMovable = Math.abs(value) < 2; if (shouldBeMovable !== canMoveHorizontal) { From 51d94da6030ab1c53eb80598f9217eb0f4545ec7 Mon Sep 17 00:00:00 2001 From: mlanter Date: Tue, 27 Dec 2016 13:23:49 -0500 Subject: [PATCH 0176/1148] [android crash] Fix exception when animating region during initialization (#901) --- .../com/airbnb/android/react/maps/AirMapView.java | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java b/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java index cb7e9fb6d..5d8de64af 100644 --- a/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java +++ b/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java @@ -479,13 +479,17 @@ public void updateExtraData(Object extraData) { } public void animateToRegion(LatLngBounds bounds, int duration) { - startMonitoringRegion(); - map.animateCamera(CameraUpdateFactory.newLatLngBounds(bounds, 0), duration, null); + if (map != null) { + startMonitoringRegion(); + map.animateCamera(CameraUpdateFactory.newLatLngBounds(bounds, 0), duration, null); + } } public void animateToCoordinate(LatLng coordinate, int duration) { - startMonitoringRegion(); - map.animateCamera(CameraUpdateFactory.newLatLng(coordinate), duration, null); + if (map != null) { + startMonitoringRegion(); + map.animateCamera(CameraUpdateFactory.newLatLng(coordinate), duration, null); + } } public void fitToElements(boolean animated) { From 1e71a21f39e7b88554852951f773c731c94680c9 Mon Sep 17 00:00:00 2001 From: Vjeran Crnjak Date: Tue, 27 Dec 2016 19:26:45 +0100 Subject: [PATCH 0177/1148] fixes Option 2 building (#900) * fixes Option 2 building - afaik `GMSMapStyle` is not present in 2.0.x * Update installation.md * Update installation.md --- docs/installation.md | 7 +++---- react-native-google-maps.podspec | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/docs/installation.md b/docs/installation.md index 80c604ac5..a236fbda1 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -27,10 +27,9 @@ react-native link 1. If you need `GoogleMaps` support also drag this folder into your project: - `node_modules/react-native-maps/ios/AirGoogleMaps/` -### Option 2: CocoaPods -- Untested Way -NOTE: If you actually get this to work, please open an issue to let us know. -This is now considered the **old way** because it is untested and if it does work at all, it -will only work if you **don't** have `use_frameworks!` in your `Podfile` +### Option 2: CocoaPods +This is now considered the **old way** because it will only work if you **don't** have +`use_frameworks!` in your `Podfile`. To install using Cocoapods, simply insert the following line into your `Podfile`: diff --git a/react-native-google-maps.podspec b/react-native-google-maps.podspec index e32dda3be..8ec70ea43 100644 --- a/react-native-google-maps.podspec +++ b/react-native-google-maps.podspec @@ -12,5 +12,5 @@ Pod::Spec.new do |s| s.source_files = "ios/AirGoogleMaps/**/*.{h,m}" s.dependency 'React' - s.dependency 'GoogleMaps', '2.0.1' + s.dependency 'GoogleMaps', '2.1.1' end From 1af45a707e20c5e9187e24420b20f94baf0c8766 Mon Sep 17 00:00:00 2001 From: rajkumarpunchh Date: Thu, 5 Jan 2017 13:57:11 +0530 Subject: [PATCH 0178/1148] Fixed issue #751. https://github.com/airbnb/react-native-maps/issues/751 --- ios/AirMaps/AIRMapManager.m | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ios/AirMaps/AIRMapManager.m b/ios/AirMaps/AIRMapManager.m index 4fedef3b8..2bb916970 100644 --- a/ios/AirMaps/AIRMapManager.m +++ b/ios/AirMaps/AIRMapManager.m @@ -158,7 +158,9 @@ - (UIView *)view } else { AIRMap *mapView = (AIRMap *)view; // TODO(lmr): we potentially want to include overlays here... and could concat the two arrays together. - [mapView showAnnotations:mapView.annotations animated:animated]; + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.1 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{ + [mapView showAnnotations:mapView.annotations animated:animated]; + }); } }]; } From d274eb48a98034295410ed498897f4ed384ceee8 Mon Sep 17 00:00:00 2001 From: James Ide Date: Fri, 30 Dec 2016 21:15:06 -0800 Subject: [PATCH 0179/1148] [RN 0.40] Update iOS header imports and JS SyntheticEvent import for RN 0.40 React Native 0.40 (coming soon) changes the way its iOS headers should be imported. The headers are now under a directory called "React" that is in the compiler's include path, hence the new import style. On the JS side, RN 0.40 now peer-depends on React 15.4.x which moved SyntheticEvent from `react/lib` to deep inside `react-native`, so update that import as well. Test Plan: Follow the setup instructions (https://github.com/airbnb/react-native-maps/blob/master/docs/examples-setup.md) and run the explorer app (notably verify that it compiles). --- example/examples/EventListener.js | 3 ++- example/ios/AirMapsExplorer/AppDelegate.m | 2 +- .../AirMapsExplorerTests.m | 4 ++-- example/package.json | 6 +++--- ios/AirGoogleMaps/AIRGMSMarker.h | 2 +- ios/AirGoogleMaps/AIRGoogleMap.h | 4 ++-- ios/AirGoogleMaps/AIRGoogleMap.m | 4 ++-- ios/AirGoogleMaps/AIRGoogleMapCallout.h | 2 +- ios/AirGoogleMaps/AIRGoogleMapCallout.m | 6 +++--- .../AIRGoogleMapCalloutManager.h | 2 +- .../AIRGoogleMapCalloutManager.m | 2 +- ios/AirGoogleMaps/AIRGoogleMapCircle.m | 2 +- ios/AirGoogleMaps/AIRGoogleMapCircleManager.h | 2 +- ios/AirGoogleMaps/AIRGoogleMapCircleManager.m | 4 ++-- ios/AirGoogleMaps/AIRGoogleMapManager.h | 2 +- ios/AirGoogleMaps/AIRGoogleMapManager.m | 18 ++++++++-------- ios/AirGoogleMaps/AIRGoogleMapMarker.h | 2 +- ios/AirGoogleMaps/AIRGoogleMapMarker.m | 8 +++---- ios/AirGoogleMaps/AIRGoogleMapMarkerManager.h | 2 +- ios/AirGoogleMaps/AIRGoogleMapMarkerManager.m | 4 ++-- .../AIRGoogleMapPolygonManager.h | 2 +- .../AIRGoogleMapPolygonManager.m | 12 +++++------ ios/AirGoogleMaps/AIRGoogleMapPolyline.m | 2 +- .../AIRGoogleMapPolylineManager.h | 2 +- .../AIRGoogleMapPolylineManager.m | 12 +++++------ .../AIRGoogleMapUrlTileManager.h | 2 +- ios/AirGoogleMaps/RCTConvert+GMSMapViewType.h | 2 +- ios/AirGoogleMaps/RCTConvert+GMSMapViewType.m | 2 +- ios/AirMaps/AIRMap.h | 4 ++-- ios/AirMaps/AIRMap.m | 4 ++-- ios/AirMaps/AIRMapCallout.h | 2 +- ios/AirMaps/AIRMapCalloutManager.h | 2 +- ios/AirMaps/AIRMapCalloutManager.m | 12 +++++------ ios/AirMaps/AIRMapCircle.h | 11 +++++----- ios/AirMaps/AIRMapCircle.m | 2 +- ios/AirMaps/AIRMapCircleManager.h | 2 +- ios/AirMaps/AIRMapCircleManager.m | 12 +++++------ ios/AirMaps/AIRMapManager.h | 2 +- ios/AirMaps/AIRMapManager.m | 21 +++++++++---------- ios/AirMaps/AIRMapMarker.h | 4 ++-- ios/AirMaps/AIRMapMarker.m | 12 +++++------ ios/AirMaps/AIRMapMarkerManager.h | 2 +- ios/AirMaps/AIRMapMarkerManager.m | 6 +++--- ios/AirMaps/AIRMapPolygon.h | 6 +++--- ios/AirMaps/AIRMapPolygon.m | 2 +- ios/AirMaps/AIRMapPolygonManager.h | 2 +- ios/AirMaps/AIRMapPolygonManager.m | 12 +++++------ ios/AirMaps/AIRMapPolyline.h | 8 +++---- ios/AirMaps/AIRMapPolyline.m | 2 +- ios/AirMaps/AIRMapPolylineManager.h | 2 +- ios/AirMaps/AIRMapPolylineManager.m | 12 +++++------ ios/AirMaps/AIRMapUrlTile.h | 6 +++--- ios/AirMaps/AIRMapUrlTile.m | 2 +- ios/AirMaps/AIRMapUrlTileManager.h | 2 +- ios/AirMaps/AIRMapUrlTileManager.m | 13 ++++++------ ios/AirMaps/RCTConvert+MoreMapKit.h | 2 +- ios/AirMaps/RCTConvert+MoreMapKit.m | 4 ++-- package.json | 4 ++-- 58 files changed, 146 insertions(+), 148 deletions(-) diff --git a/example/examples/EventListener.js b/example/examples/EventListener.js index 0f62fbc73..0876c621d 100644 --- a/example/examples/EventListener.js +++ b/example/examples/EventListener.js @@ -1,5 +1,4 @@ import React, { PropTypes } from 'react'; -import SyntheticEvent from 'react/lib/SyntheticEvent'; import { StyleSheet, View, @@ -7,6 +6,8 @@ import { Dimensions, ScrollView, } from 'react-native'; +// eslint-disable-next-line max-len +import SyntheticEvent from 'react-native/Libraries/Renderer/src/renderers/shared/stack/event/SyntheticEvent'; import MapView from 'react-native-maps'; import PriceMarker from './PriceMarker'; diff --git a/example/ios/AirMapsExplorer/AppDelegate.m b/example/ios/AirMapsExplorer/AppDelegate.m index 91ae54c48..6f006087f 100644 --- a/example/ios/AirMapsExplorer/AppDelegate.m +++ b/example/ios/AirMapsExplorer/AppDelegate.m @@ -9,7 +9,7 @@ #import "AppDelegate.h" -#import "RCTRootView.h" +#import #import diff --git a/example/ios/AirMapsExplorerTests/AirMapsExplorerTests.m b/example/ios/AirMapsExplorerTests/AirMapsExplorerTests.m index 31dab00aa..a93b699bd 100644 --- a/example/ios/AirMapsExplorerTests/AirMapsExplorerTests.m +++ b/example/ios/AirMapsExplorerTests/AirMapsExplorerTests.m @@ -10,8 +10,8 @@ #import #import -#import "RCTLog.h" -#import "RCTRootView.h" +#import +#import #define TIMEOUT_SECONDS 240 #define TEXT_TO_LOOK_FOR @"Welcome to React Native!" diff --git a/example/package.json b/example/package.json index a303d3cff..eca9884a4 100644 --- a/example/package.json +++ b/example/package.json @@ -9,9 +9,9 @@ "dev": "concurrently 'npm run watch' 'npm run packager'" }, "dependencies": { - "react": "^15.3.1", - "react-native": "^0.35.0", - "react-native-maps": "../" + "react": "~15.4.1", + "react-native": "^0.40.0", + "react-native-maps": "file:../" }, "devDependencies": { "concurrently": "^2.2.0", diff --git a/ios/AirGoogleMaps/AIRGMSMarker.h b/ios/AirGoogleMaps/AIRGMSMarker.h index baf89341d..89723ca2a 100644 --- a/ios/AirGoogleMaps/AIRGMSMarker.h +++ b/ios/AirGoogleMaps/AIRGMSMarker.h @@ -6,7 +6,7 @@ // #import -#import "UIView+React.h" +#import @class AIRGoogleMapMarker; diff --git a/ios/AirGoogleMaps/AIRGoogleMap.h b/ios/AirGoogleMaps/AIRGoogleMap.h index bf16a2ef4..925aa4746 100644 --- a/ios/AirGoogleMaps/AIRGoogleMap.h +++ b/ios/AirGoogleMaps/AIRGoogleMap.h @@ -6,10 +6,10 @@ // #import -#import "RCTComponent.h" +#import +#import #import #import -#import "RCTConvert+MapKit.h" #import "AIRGMSMarker.h" @interface AIRGoogleMap : GMSMapView diff --git a/ios/AirGoogleMaps/AIRGoogleMap.m b/ios/AirGoogleMaps/AIRGoogleMap.m index 50f148eb1..39c8bb3a6 100644 --- a/ios/AirGoogleMaps/AIRGoogleMap.m +++ b/ios/AirGoogleMaps/AIRGoogleMap.m @@ -13,8 +13,8 @@ #import "AIRGoogleMapUrlTile.h" #import #import -#import "RCTConvert+MapKit.h" -#import "UIView+React.h" +#import +#import id regionAsJSON(MKCoordinateRegion region) { return @{ diff --git a/ios/AirGoogleMaps/AIRGoogleMapCallout.h b/ios/AirGoogleMaps/AIRGoogleMapCallout.h index 61558e6bc..784bcf613 100644 --- a/ios/AirGoogleMaps/AIRGoogleMapCallout.h +++ b/ios/AirGoogleMaps/AIRGoogleMapCallout.h @@ -7,7 +7,7 @@ // #import -#import "RCTView.h" +#import @interface AIRGoogleMapCallout : UIView @property (nonatomic, assign) BOOL tooltip; diff --git a/ios/AirGoogleMaps/AIRGoogleMapCallout.m b/ios/AirGoogleMaps/AIRGoogleMapCallout.m index c64a6e03b..acc6b86b7 100644 --- a/ios/AirGoogleMaps/AIRGoogleMapCallout.m +++ b/ios/AirGoogleMaps/AIRGoogleMapCallout.m @@ -7,9 +7,9 @@ // #import "AIRGoogleMapCallout.h" -#import "RCTUtils.h" -#import "RCTView.h" -#import "RCTBridge.h" +#import +#import +#import @implementation AIRGoogleMapCallout @end diff --git a/ios/AirGoogleMaps/AIRGoogleMapCalloutManager.h b/ios/AirGoogleMaps/AIRGoogleMapCalloutManager.h index be0e1a72f..e5514087e 100644 --- a/ios/AirGoogleMaps/AIRGoogleMapCalloutManager.h +++ b/ios/AirGoogleMaps/AIRGoogleMapCalloutManager.h @@ -5,7 +5,7 @@ // Created by Gil Birman on 9/6/16. // // -#import "RCTViewManager.h" +#import @interface AIRGoogleMapCalloutManager : RCTViewManager diff --git a/ios/AirGoogleMaps/AIRGoogleMapCalloutManager.m b/ios/AirGoogleMaps/AIRGoogleMapCalloutManager.m index 9a2a20998..1828beb8a 100644 --- a/ios/AirGoogleMaps/AIRGoogleMapCalloutManager.m +++ b/ios/AirGoogleMaps/AIRGoogleMapCalloutManager.m @@ -8,7 +8,7 @@ #import "AIRGoogleMapCalloutManager.h" #import "AIRGoogleMapCallout.h" -#import "RCTView.h" +#import @implementation AIRGoogleMapCalloutManager RCT_EXPORT_MODULE() diff --git a/ios/AirGoogleMaps/AIRGoogleMapCircle.m b/ios/AirGoogleMaps/AIRGoogleMapCircle.m index 1698bee8c..28741b9f3 100644 --- a/ios/AirGoogleMaps/AIRGoogleMapCircle.m +++ b/ios/AirGoogleMaps/AIRGoogleMapCircle.m @@ -6,7 +6,7 @@ #import #import "AIRGoogleMapCircle.h" #import -#import "RCTUtils.h" +#import @implementation AIRGoogleMapCircle diff --git a/ios/AirGoogleMaps/AIRGoogleMapCircleManager.h b/ios/AirGoogleMaps/AIRGoogleMapCircleManager.h index 481b6d6c5..c1de72318 100644 --- a/ios/AirGoogleMaps/AIRGoogleMapCircleManager.h +++ b/ios/AirGoogleMaps/AIRGoogleMapCircleManager.h @@ -4,7 +4,7 @@ // Created by Nick Italiano on 10/24/16. // -#import "RCTViewManager.h" +#import @interface AIRGoogleMapCircleManager : RCTViewManager diff --git a/ios/AirGoogleMaps/AIRGoogleMapCircleManager.m b/ios/AirGoogleMaps/AIRGoogleMapCircleManager.m index 62a164d22..93afa145f 100644 --- a/ios/AirGoogleMaps/AIRGoogleMapCircleManager.m +++ b/ios/AirGoogleMaps/AIRGoogleMapCircleManager.m @@ -6,8 +6,8 @@ #import "AIRGoogleMapCircleManager.h" #import "AIRGoogleMapCircle.h" -#import "RCTBridge.h" -#import "UIView+React.h" +#import +#import @interface AIRGoogleMapCircleManager() diff --git a/ios/AirGoogleMaps/AIRGoogleMapManager.h b/ios/AirGoogleMaps/AIRGoogleMapManager.h index b726eae65..ac841c7bf 100644 --- a/ios/AirGoogleMaps/AIRGoogleMapManager.h +++ b/ios/AirGoogleMaps/AIRGoogleMapManager.h @@ -5,7 +5,7 @@ // Created by Gil Birman on 9/1/16. // -#import "RCTViewManager.h" +#import @interface AIRGoogleMapManager : RCTViewManager diff --git a/ios/AirGoogleMaps/AIRGoogleMapManager.m b/ios/AirGoogleMaps/AIRGoogleMapManager.m index a04186e7e..e306de1d8 100644 --- a/ios/AirGoogleMaps/AIRGoogleMapManager.m +++ b/ios/AirGoogleMaps/AIRGoogleMapManager.m @@ -7,18 +7,18 @@ #import "AIRGoogleMapManager.h" -#import "RCTViewManager.h" -#import "RCTBridge.h" -#import "RCTUIManager.h" -#import "RCTConvert+CoreLocation.h" -#import "RCTConvert+MapKit.h" +#import +#import +#import +#import +#import +#import +#import +#import +#import #import "RCTConvert+GMSMapViewType.h" -#import "RCTEventDispatcher.h" #import "AIRGoogleMap.h" -#import "UIView+React.h" #import "AIRMapMarker.h" -#import "RCTViewManager.h" -#import "RCTConvert.h" #import "AIRMapPolyline.h" #import "AIRMapPolygon.h" #import "AIRMapCircle.h" diff --git a/ios/AirGoogleMaps/AIRGoogleMapMarker.h b/ios/AirGoogleMaps/AIRGoogleMapMarker.h index 8f1018b05..ca6a5cc12 100644 --- a/ios/AirGoogleMaps/AIRGoogleMapMarker.h +++ b/ios/AirGoogleMaps/AIRGoogleMapMarker.h @@ -6,8 +6,8 @@ // #import +#import #import "AIRGMSMarker.h" -#import "RCTBridge.h" #import "AIRGoogleMap.h" #import "AIRGoogleMapCallout.h" diff --git a/ios/AirGoogleMaps/AIRGoogleMapMarker.m b/ios/AirGoogleMaps/AIRGoogleMapMarker.m index a3bbbffc0..4bb10dede 100644 --- a/ios/AirGoogleMaps/AIRGoogleMapMarker.m +++ b/ios/AirGoogleMaps/AIRGoogleMapMarker.m @@ -7,10 +7,10 @@ #import "AIRGoogleMapMarker.h" #import +#import +#import #import "AIRGMSMarker.h" #import "AIRGoogleMapCallout.h" -#import "RCTImageLoader.h" -#import "RCTUtils.h" #import "DummyView.h" CGRect unionRect(CGRect a, CGRect b) { @@ -186,14 +186,14 @@ - (void)setImageSrc:(NSString *)imageSrc if (_iconImageView) [_iconImageView removeFromSuperview]; return; } - + if (!_iconImageView) { // prevent glitch with marker (cf. https://github.com/airbnb/react-native-maps/issues/738) UIImageView *empyImageView = [[UIImageView alloc] init]; _iconImageView = empyImageView; [self iconViewInsertSubview:_iconImageView atIndex:0]; } - + _reloadImageCancellationBlock = [_bridge.imageLoader loadImageWithURLRequest:[RCTConvert NSURLRequest:_imageSrc] size:self.bounds.size scale:RCTScreenScale() diff --git a/ios/AirGoogleMaps/AIRGoogleMapMarkerManager.h b/ios/AirGoogleMaps/AIRGoogleMapMarkerManager.h index 657f6b044..f2698dcd0 100644 --- a/ios/AirGoogleMaps/AIRGoogleMapMarkerManager.h +++ b/ios/AirGoogleMaps/AIRGoogleMapMarkerManager.h @@ -5,7 +5,7 @@ // Created by Gil Birman on 9/2/16. // -#import "RCTViewManager.h" +#import @interface AIRGoogleMapMarkerManager : RCTViewManager diff --git a/ios/AirGoogleMaps/AIRGoogleMapMarkerManager.m b/ios/AirGoogleMaps/AIRGoogleMapMarkerManager.m index ee138c25f..0d29c3fac 100644 --- a/ios/AirGoogleMaps/AIRGoogleMapMarkerManager.m +++ b/ios/AirGoogleMaps/AIRGoogleMapMarkerManager.m @@ -8,8 +8,8 @@ #import "AIRGoogleMapMarkerManager.h" #import "AIRGoogleMapMarker.h" #import -#import "RCTConvert+MapKit.h" -#import "RCTUIManager.h" +#import +#import @implementation AIRGoogleMapMarkerManager diff --git a/ios/AirGoogleMaps/AIRGoogleMapPolygonManager.h b/ios/AirGoogleMaps/AIRGoogleMapPolygonManager.h index fd6040ca0..3380c61e3 100644 --- a/ios/AirGoogleMaps/AIRGoogleMapPolygonManager.h +++ b/ios/AirGoogleMaps/AIRGoogleMapPolygonManager.h @@ -4,7 +4,7 @@ // Created by Nick Italiano on 10/22/16. // -#import "RCTViewManager.h" +#import @interface AIRGoogleMapPolygonManager : RCTViewManager diff --git a/ios/AirGoogleMaps/AIRGoogleMapPolygonManager.m b/ios/AirGoogleMaps/AIRGoogleMapPolygonManager.m index 383bb6527..5c7ce2a66 100644 --- a/ios/AirGoogleMaps/AIRGoogleMapPolygonManager.m +++ b/ios/AirGoogleMaps/AIRGoogleMapPolygonManager.m @@ -5,13 +5,13 @@ // #import "AIRGoogleMapPolygonManager.h" -#import "RCTBridge.h" -#import "RCTConvert.h" -#import "RCTConvert+CoreLocation.h" +#import +#import +#import +#import +#import +#import #import "RCTConvert+MoreMapKit.h" -#import "RCTEventDispatcher.h" -#import "UIView+React.h" -#import "RCTViewManager.h" #import "AIRGoogleMapPolygon.h" @interface AIRGoogleMapPolygonManager() diff --git a/ios/AirGoogleMaps/AIRGoogleMapPolyline.m b/ios/AirGoogleMaps/AIRGoogleMapPolyline.m index c55621e97..009d90bfb 100644 --- a/ios/AirGoogleMaps/AIRGoogleMapPolyline.m +++ b/ios/AirGoogleMaps/AIRGoogleMapPolyline.m @@ -9,7 +9,7 @@ #import "AIRGoogleMapMarker.h" #import "AIRGoogleMapMarkerManager.h" #import -#import "RCTUtils.h" +#import @implementation AIRGoogleMapPolyline diff --git a/ios/AirGoogleMaps/AIRGoogleMapPolylineManager.h b/ios/AirGoogleMaps/AIRGoogleMapPolylineManager.h index 48aaf8527..82e7b8e20 100644 --- a/ios/AirGoogleMaps/AIRGoogleMapPolylineManager.h +++ b/ios/AirGoogleMaps/AIRGoogleMapPolylineManager.h @@ -4,7 +4,7 @@ // Created by Nick Italiano on 10/22/16. // -#import "RCTViewManager.h" +#import @interface AIRGoogleMapPolylineManager : RCTViewManager diff --git a/ios/AirGoogleMaps/AIRGoogleMapPolylineManager.m b/ios/AirGoogleMaps/AIRGoogleMapPolylineManager.m index 68817b138..8ccaa7080 100644 --- a/ios/AirGoogleMaps/AIRGoogleMapPolylineManager.m +++ b/ios/AirGoogleMaps/AIRGoogleMapPolylineManager.m @@ -6,13 +6,13 @@ #import "AIRGoogleMapPolylineManager.h" -#import "RCTBridge.h" -#import "RCTConvert.h" -#import "RCTConvert+CoreLocation.h" +#import +#import +#import +#import +#import +#import #import "RCTConvert+MoreMapKit.h" -#import "RCTEventDispatcher.h" -#import "UIView+React.h" -#import "RCTViewManager.h" #import "AIRGoogleMapPolyline.h" @interface AIRGoogleMapPolylineManager() diff --git a/ios/AirGoogleMaps/AIRGoogleMapUrlTileManager.h b/ios/AirGoogleMaps/AIRGoogleMapUrlTileManager.h index 3554837d4..affd718b4 100644 --- a/ios/AirGoogleMaps/AIRGoogleMapUrlTileManager.h +++ b/ios/AirGoogleMaps/AIRGoogleMapUrlTileManager.h @@ -4,7 +4,7 @@ // #import -#import "RCTViewManager.h" +#import @interface AIRGoogleMapUrlTileManager : RCTViewManager @end diff --git a/ios/AirGoogleMaps/RCTConvert+GMSMapViewType.h b/ios/AirGoogleMaps/RCTConvert+GMSMapViewType.h index a753f4331..7e02d66a0 100644 --- a/ios/AirGoogleMaps/RCTConvert+GMSMapViewType.h +++ b/ios/AirGoogleMaps/RCTConvert+GMSMapViewType.h @@ -6,7 +6,7 @@ #import #import -#import "RCTConvert.h" +#import @interface RCTConvert (GMSMapViewType) diff --git a/ios/AirGoogleMaps/RCTConvert+GMSMapViewType.m b/ios/AirGoogleMaps/RCTConvert+GMSMapViewType.m index 42053fb1d..bd339f30e 100644 --- a/ios/AirGoogleMaps/RCTConvert+GMSMapViewType.m +++ b/ios/AirGoogleMaps/RCTConvert+GMSMapViewType.m @@ -6,7 +6,7 @@ #import "RCTConvert+GMSMapViewType.h" #import -#import "RCTConvert.h" +#import @implementation RCTConvert (GMSMapViewType) RCT_ENUM_CONVERTER(GMSMapViewType, diff --git a/ios/AirMaps/AIRMap.h b/ios/AirMaps/AIRMap.h index 6b061fe42..fd4ed0f25 100644 --- a/ios/AirMaps/AIRMap.h +++ b/ios/AirMaps/AIRMap.h @@ -10,8 +10,8 @@ #import #import -#import "RCTConvert+MapKit.h" -#import "RCTComponent.h" +#import +#import #import "SMCalloutView.h" extern const CLLocationDegrees AIRMapDefaultSpan; diff --git a/ios/AirMaps/AIRMap.m b/ios/AirMaps/AIRMap.m index 4c2d164c9..1126c3825 100644 --- a/ios/AirMaps/AIRMap.m +++ b/ios/AirMaps/AIRMap.m @@ -9,9 +9,9 @@ #import "AIRMap.h" -#import "RCTEventDispatcher.h" +#import +#import #import "AIRMapMarker.h" -#import "UIView+React.h" #import "AIRMapPolyline.h" #import "AIRMapPolygon.h" #import "AIRMapCircle.h" diff --git a/ios/AirMaps/AIRMapCallout.h b/ios/AirMaps/AIRMapCallout.h index 876409f7f..6e53ce1d5 100644 --- a/ios/AirMaps/AIRMapCallout.h +++ b/ios/AirMaps/AIRMapCallout.h @@ -4,7 +4,7 @@ // #import -#import "RCTView.h" +#import @interface AIRMapCallout : RCTView diff --git a/ios/AirMaps/AIRMapCalloutManager.h b/ios/AirMaps/AIRMapCalloutManager.h index b5bbadff8..411739a8d 100644 --- a/ios/AirMaps/AIRMapCalloutManager.h +++ b/ios/AirMaps/AIRMapCalloutManager.h @@ -3,7 +3,7 @@ // Copyright (c) 2015 Facebook. All rights reserved. // -#import "RCTViewManager.h" +#import @interface AIRMapCalloutManager : RCTViewManager diff --git a/ios/AirMaps/AIRMapCalloutManager.m b/ios/AirMaps/AIRMapCalloutManager.m index fbd1804ea..bc1a8e7a3 100644 --- a/ios/AirMaps/AIRMapCalloutManager.m +++ b/ios/AirMaps/AIRMapCalloutManager.m @@ -9,13 +9,13 @@ #import "AIRMapCalloutManager.h" -#import "RCTBridge.h" -#import "RCTConvert.h" -#import "RCTConvert+CoreLocation.h" -#import "RCTEventDispatcher.h" -#import "UIView+React.h" +#import +#import +#import +#import +#import +#import #import "AIRMapMarker.h" -#import "RCTViewManager.h" #import "AIRMapCallout.h" @interface AIRMapCalloutManager() diff --git a/ios/AirMaps/AIRMapCircle.h b/ios/AirMaps/AIRMapCircle.h index dffacb246..44755a9ee 100644 --- a/ios/AirMaps/AIRMapCircle.h +++ b/ios/AirMaps/AIRMapCircle.h @@ -8,13 +8,12 @@ #import #import -#import "RCTConvert+MapKit.h" -#import "RCTComponent.h" +#import +#import +#import + #import "AIRMapCoordinate.h" #import "AIRMap.h" -#import "RCTView.h" - - @interface AIRMapCircle: MKAnnotationView @@ -42,4 +41,4 @@ - (BOOL)intersectsMapRect:(MKMapRect)mapRect; - (BOOL)canReplaceMapContent; -@end \ No newline at end of file +@end diff --git a/ios/AirMaps/AIRMapCircle.m b/ios/AirMaps/AIRMapCircle.m index 5e23c1155..540c4d437 100644 --- a/ios/AirMaps/AIRMapCircle.m +++ b/ios/AirMaps/AIRMapCircle.m @@ -4,7 +4,7 @@ // #import "AIRMapCircle.h" -#import "UIView+React.h" +#import @implementation AIRMapCircle { diff --git a/ios/AirMaps/AIRMapCircleManager.h b/ios/AirMaps/AIRMapCircleManager.h index a752c2d3c..55f52a0ca 100644 --- a/ios/AirMaps/AIRMapCircleManager.h +++ b/ios/AirMaps/AIRMapCircleManager.h @@ -3,7 +3,7 @@ // Copyright (c) 2015 Facebook. All rights reserved. // -#import "RCTViewManager.h" +#import @interface AIRMapCircleManager : RCTViewManager diff --git a/ios/AirMaps/AIRMapCircleManager.m b/ios/AirMaps/AIRMapCircleManager.m index 022e124a8..c7c4a2ac5 100644 --- a/ios/AirMaps/AIRMapCircleManager.m +++ b/ios/AirMaps/AIRMapCircleManager.m @@ -9,13 +9,13 @@ #import "AIRMapCircleManager.h" -#import "RCTBridge.h" -#import "RCTConvert.h" -#import "RCTConvert+CoreLocation.h" -#import "RCTEventDispatcher.h" -#import "UIView+React.h" +#import +#import +#import +#import +#import +#import #import "AIRMapMarker.h" -#import "RCTViewManager.h" #import "AIRMapCircle.h" @interface AIRMapCircleManager() diff --git a/ios/AirMaps/AIRMapManager.h b/ios/AirMaps/AIRMapManager.h index f3ffd4515..cc9a8c75b 100644 --- a/ios/AirMaps/AIRMapManager.h +++ b/ios/AirMaps/AIRMapManager.h @@ -7,7 +7,7 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -#import "RCTViewManager.h" +#import @interface AIRMapManager : RCTViewManager diff --git a/ios/AirMaps/AIRMapManager.m b/ios/AirMaps/AIRMapManager.m index 4fedef3b8..e4ecadf39 100644 --- a/ios/AirMaps/AIRMapManager.m +++ b/ios/AirMaps/AIRMapManager.m @@ -7,19 +7,18 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -#import "RCTViewManager.h" #import "AIRMapManager.h" -#import "RCTBridge.h" -#import "RCTUIManager.h" -#import "RCTConvert+CoreLocation.h" -#import "RCTConvert+MapKit.h" -#import "RCTEventDispatcher.h" +#import +#import +#import +#import +#import +#import +#import +#import #import "AIRMap.h" -#import "UIView+React.h" #import "AIRMapMarker.h" -#import "RCTViewManager.h" -#import "RCTConvert.h" #import "AIRMapPolyline.h" #import "AIRMapPolygon.h" #import "AIRMapCircle.h" @@ -307,7 +306,7 @@ - (void)takeMapSnapshot:(AIRMap *)mapView UIImage *compositeImage = UIGraphicsGetImageFromCurrentImageContext(); NSData *data; - if ([format isEqualToString:@"png"]) { + if ([format isEqualToString:@"png"]) { data = UIImagePNGRepresentation(compositeImage); } else if([format isEqualToString:@"jpg"]) { @@ -325,7 +324,7 @@ - (void)takeMapSnapshot:(AIRMap *)mapView // In the initial (iOS only) implementation of takeSnapshot, // both the uri and the base64 encoded string were returned. - // Returning both is rarely useful and in fact causes a + // Returning both is rarely useful and in fact causes a // performance penalty when only the file URI is desired. // In that case the base64 encoded string was always marshalled // over the JS-bridge (which is quite slow). diff --git a/ios/AirMaps/AIRMapMarker.h b/ios/AirMaps/AIRMapMarker.h index 187cbad0a..97440639f 100644 --- a/ios/AirMaps/AIRMapMarker.h +++ b/ios/AirMaps/AIRMapMarker.h @@ -13,8 +13,8 @@ #import #import -#import "RCTConvert+MapKit.h" -#import "RCTComponent.h" +#import +#import #import "AIRMap.h" #import "SMCalloutView.h" diff --git a/ios/AirMaps/AIRMapMarker.m b/ios/AirMaps/AIRMapMarker.m index 983f5fabe..2d7d086d4 100644 --- a/ios/AirMaps/AIRMapMarker.m +++ b/ios/AirMaps/AIRMapMarker.m @@ -9,11 +9,11 @@ #import "AIRMapMarker.h" -#import "RCTEventDispatcher.h" -#import "UIView+React.h" -#import "RCTBridge.h" -#import "RCTUtils.h" -#import "RCTImageLoader.h" +#import +#import +#import +#import +#import @implementation AIREmptyCalloutBackgroundView @end @@ -232,7 +232,7 @@ - (void)setImageSrc:(NSString *)imageSrc - (void)setPinColor:(UIColor *)pinColor { _pinColor = pinColor; - + if ([_pinView respondsToSelector:@selector(setPinTintColor:)]) { _pinView.pinTintColor = _pinColor; } diff --git a/ios/AirMaps/AIRMapMarkerManager.h b/ios/AirMaps/AIRMapMarkerManager.h index baea30735..1fc44601d 100644 --- a/ios/AirMaps/AIRMapMarkerManager.h +++ b/ios/AirMaps/AIRMapMarkerManager.h @@ -7,7 +7,7 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -#import "RCTViewManager.h" +#import @interface AIRMapMarkerManager : RCTViewManager diff --git a/ios/AirMaps/AIRMapMarkerManager.m b/ios/AirMaps/AIRMapMarkerManager.m index ceecf0148..493d6cc2e 100644 --- a/ios/AirMaps/AIRMapMarkerManager.m +++ b/ios/AirMaps/AIRMapMarkerManager.m @@ -9,9 +9,9 @@ #import "AIRMapMarkerManager.h" -#import "RCTUIManager.h" -#import "RCTConvert+CoreLocation.h" -#import "UIView+React.h" +#import +#import +#import #import "AIRMapMarker.h" @interface AIRMapMarkerManager () diff --git a/ios/AirMaps/AIRMapPolygon.h b/ios/AirMaps/AIRMapPolygon.h index d028e67fb..33e752cf0 100644 --- a/ios/AirMaps/AIRMapPolygon.h +++ b/ios/AirMaps/AIRMapPolygon.h @@ -8,11 +8,11 @@ #import #import -#import "RCTConvert+MapKit.h" -#import "RCTComponent.h" +#import +#import +#import #import "AIRMapCoordinate.h" #import "AIRMap.h" -#import "RCTView.h" diff --git a/ios/AirMaps/AIRMapPolygon.m b/ios/AirMaps/AIRMapPolygon.m index 3ee378d0f..3ab7eb7c2 100644 --- a/ios/AirMaps/AIRMapPolygon.m +++ b/ios/AirMaps/AIRMapPolygon.m @@ -4,7 +4,7 @@ // #import "AIRMapPolygon.h" -#import "UIView+React.h" +#import @implementation AIRMapPolygon { diff --git a/ios/AirMaps/AIRMapPolygonManager.h b/ios/AirMaps/AIRMapPolygonManager.h index 6321e9d21..5dbfb6c04 100644 --- a/ios/AirMaps/AIRMapPolygonManager.h +++ b/ios/AirMaps/AIRMapPolygonManager.h @@ -3,7 +3,7 @@ // Copyright (c) 2015 Facebook. All rights reserved. // -#import "RCTViewManager.h" +#import @interface AIRMapPolygonManager : RCTViewManager diff --git a/ios/AirMaps/AIRMapPolygonManager.m b/ios/AirMaps/AIRMapPolygonManager.m index 1299dee12..a8177c180 100644 --- a/ios/AirMaps/AIRMapPolygonManager.m +++ b/ios/AirMaps/AIRMapPolygonManager.m @@ -9,14 +9,14 @@ #import "AIRMapPolygonManager.h" -#import "RCTBridge.h" -#import "RCTConvert.h" +#import +#import +#import +#import +#import +#import #import "RCTConvert+MoreMapKit.h" -#import "RCTConvert+CoreLocation.h" -#import "RCTEventDispatcher.h" -#import "UIView+React.h" #import "AIRMapMarker.h" -#import "RCTViewManager.h" #import "AIRMapPolygon.h" @interface AIRMapPolygonManager() diff --git a/ios/AirMaps/AIRMapPolyline.h b/ios/AirMaps/AIRMapPolyline.h index 2e5b4e30a..5629b1fd4 100644 --- a/ios/AirMaps/AIRMapPolyline.h +++ b/ios/AirMaps/AIRMapPolyline.h @@ -8,11 +8,11 @@ #import #import -#import "RCTConvert+MapKit.h" -#import "RCTComponent.h" +#import +#import +#import #import "AIRMapCoordinate.h" #import "AIRMap.h" -#import "RCTView.h" @interface AIRMapPolyline: MKAnnotationView @@ -40,4 +40,4 @@ - (BOOL)intersectsMapRect:(MKMapRect)mapRect; - (BOOL)canReplaceMapContent; -@end \ No newline at end of file +@end diff --git a/ios/AirMaps/AIRMapPolyline.m b/ios/AirMaps/AIRMapPolyline.m index 5b28167fd..8e07a63b3 100644 --- a/ios/AirMaps/AIRMapPolyline.m +++ b/ios/AirMaps/AIRMapPolyline.m @@ -4,7 +4,7 @@ // #import "AIRMapPolyline.h" -#import "UIView+React.h" +#import @implementation AIRMapPolyline { diff --git a/ios/AirMaps/AIRMapPolylineManager.h b/ios/AirMaps/AIRMapPolylineManager.h index a529a837a..aa5313b32 100644 --- a/ios/AirMaps/AIRMapPolylineManager.h +++ b/ios/AirMaps/AIRMapPolylineManager.h @@ -3,7 +3,7 @@ // Copyright (c) 2015 Facebook. All rights reserved. // -#import "RCTViewManager.h" +#import @interface AIRMapPolylineManager : RCTViewManager diff --git a/ios/AirMaps/AIRMapPolylineManager.m b/ios/AirMaps/AIRMapPolylineManager.m index 399b46d40..70ba3eb1f 100644 --- a/ios/AirMaps/AIRMapPolylineManager.m +++ b/ios/AirMaps/AIRMapPolylineManager.m @@ -9,14 +9,14 @@ #import "AIRMapPolylineManager.h" -#import "RCTBridge.h" -#import "RCTConvert.h" -#import "RCTConvert+CoreLocation.h" +#import +#import +#import +#import +#import +#import #import "RCTConvert+MoreMapKit.h" -#import "RCTEventDispatcher.h" -#import "UIView+React.h" #import "AIRMapMarker.h" -#import "RCTViewManager.h" #import "AIRMapPolyline.h" @interface AIRMapPolylineManager() diff --git a/ios/AirMaps/AIRMapUrlTile.h b/ios/AirMaps/AIRMapUrlTile.h index 184fe2231..509331414 100644 --- a/ios/AirMaps/AIRMapUrlTile.h +++ b/ios/AirMaps/AIRMapUrlTile.h @@ -10,11 +10,11 @@ #import #import -#import "RCTConvert+MapKit.h" -#import "RCTComponent.h" +#import +#import +#import #import "AIRMapCoordinate.h" #import "AIRMap.h" -#import "RCTView.h" @interface AIRMapUrlTile : MKAnnotationView diff --git a/ios/AirMaps/AIRMapUrlTile.m b/ios/AirMaps/AIRMapUrlTile.m index 5fbe1a3b8..fdefbf3bc 100644 --- a/ios/AirMaps/AIRMapUrlTile.m +++ b/ios/AirMaps/AIRMapUrlTile.m @@ -7,7 +7,7 @@ // #import "AIRMapUrlTile.h" -#import "UIView+React.h" +#import @implementation AIRMapUrlTile { BOOL _urlTemplateSet; diff --git a/ios/AirMaps/AIRMapUrlTileManager.h b/ios/AirMaps/AIRMapUrlTileManager.h index 6a79b2233..aaee4e431 100644 --- a/ios/AirMaps/AIRMapUrlTileManager.h +++ b/ios/AirMaps/AIRMapUrlTileManager.h @@ -7,7 +7,7 @@ // -#import "RCTViewManager.h" +#import @interface AIRMapUrlTileManager : RCTViewManager diff --git a/ios/AirMaps/AIRMapUrlTileManager.m b/ios/AirMaps/AIRMapUrlTileManager.m index decec5170..4ae4abffc 100644 --- a/ios/AirMaps/AIRMapUrlTileManager.m +++ b/ios/AirMaps/AIRMapUrlTileManager.m @@ -6,13 +6,13 @@ // Copyright © 2016. All rights reserved. // -#import "RCTBridge.h" -#import "RCTConvert.h" -#import "RCTConvert+CoreLocation.h" -#import "RCTEventDispatcher.h" -#import "UIView+React.h" +#import +#import +#import +#import +#import +#import #import "AIRMapMarker.h" -#import "RCTViewManager.h" #import "AIRMapUrlTile.h" #import "AIRMapUrlTileManager.h" @@ -35,4 +35,3 @@ - (UIView *)view RCT_EXPORT_VIEW_PROPERTY(urlTemplate, NSString) @end - diff --git a/ios/AirMaps/RCTConvert+MoreMapKit.h b/ios/AirMaps/RCTConvert+MoreMapKit.h index 96c99a599..2d2475890 100644 --- a/ios/AirMaps/RCTConvert+MoreMapKit.h +++ b/ios/AirMaps/RCTConvert+MoreMapKit.h @@ -5,7 +5,7 @@ #import #import -#import "RCTConvert.h" +#import @interface RCTConvert (MoreMapKit) diff --git a/ios/AirMaps/RCTConvert+MoreMapKit.m b/ios/AirMaps/RCTConvert+MoreMapKit.m index 9f18553d1..11f19a4a8 100644 --- a/ios/AirMaps/RCTConvert+MoreMapKit.m +++ b/ios/AirMaps/RCTConvert+MoreMapKit.m @@ -4,9 +4,9 @@ // #import "RCTConvert+MoreMapKit.h" -#import "AIRMapCoordinate.h" -#import "RCTConvert+CoreLocation.h" +#import +#import "AIRMapCoordinate.h" @implementation RCTConvert (MoreMapKit) diff --git a/package.json b/package.json index c7f56595e..83444baa6 100644 --- a/package.json +++ b/package.json @@ -22,8 +22,8 @@ "mapkit" ], "peerDependencies": { - "react": ">=15.3.1", - "react-native": ">=0.35" + "react": ">=15.4.0", + "react-native": ">=0.40" }, "devDependencies": { "babel-eslint": "^6.1.2", From 9c88e848a4c9740c3f45c8ac41edfd144cd0d9f0 Mon Sep 17 00:00:00 2001 From: James Ide Date: Thu, 5 Jan 2017 12:18:19 -0800 Subject: [PATCH 0180/1148] [Podfile] Update the example Podfile for RN 0.40 Tested it with Google Maps support. --- .../AirMapsExplorer.xcodeproj/project.pbxproj | 13 +++--- example/ios/Podfile | 36 +++------------ example/ios/Podfile.lock | 45 +++++++++++-------- 3 files changed, 39 insertions(+), 55 deletions(-) diff --git a/example/ios/AirMapsExplorer.xcodeproj/project.pbxproj b/example/ios/AirMapsExplorer.xcodeproj/project.pbxproj index decbbec68..df5a3a05b 100644 --- a/example/ios/AirMapsExplorer.xcodeproj/project.pbxproj +++ b/example/ios/AirMapsExplorer.xcodeproj/project.pbxproj @@ -32,7 +32,6 @@ 21E6570C1D77591A00B75EE5 /* MobileCoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 21E6570B1D77591A00B75EE5 /* MobileCoreServices.framework */; }; 21E6570E1D77591F00B75EE5 /* MapKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 21E6570D1D77591F00B75EE5 /* MapKit.framework */; }; 21E657101D77594C00B75EE5 /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 21E6570F1D77594C00B75EE5 /* AudioToolbox.framework */; }; - 3E4E0B5921E01BC4043FD8CD /* Pods_AirMapsExplorer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3591658C00398534590C8751 /* Pods_AirMapsExplorer.framework */; }; 8620CC871DBD814A00B79BFE /* AIRGMSMarker.m in Sources */ = {isa = PBXBuildFile; fileRef = 8620CC6E1DBD814A00B79BFE /* AIRGMSMarker.m */; }; 8620CC881DBD814A00B79BFE /* AIRGoogleMap.m in Sources */ = {isa = PBXBuildFile; fileRef = 8620CC701DBD814A00B79BFE /* AIRGoogleMap.m */; }; 8620CC891DBD814A00B79BFE /* AIRGoogleMapCallout.m in Sources */ = {isa = PBXBuildFile; fileRef = 8620CC721DBD814A00B79BFE /* AIRGoogleMapCallout.m */; }; @@ -50,7 +49,7 @@ 8697D6251DBEE22B00DB7D0F /* AIRGoogleMapCircleManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 8697D6241DBEE22B00DB7D0F /* AIRGoogleMapCircleManager.m */; }; 86DE6F881DCE7D21002A5053 /* AIRGoogleMapUrlTile.m in Sources */ = {isa = PBXBuildFile; fileRef = 86DE6F871DCE7D21002A5053 /* AIRGoogleMapUrlTile.m */; }; 86DE6F8B1DCE8543002A5053 /* AIRGoogleMapURLTileManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 86DE6F8A1DCE8543002A5053 /* AIRGoogleMapURLTileManager.m */; }; - C9315A21AD5A149EB5B40F29 /* Pods_AirMapsExplorer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 24EB66BA0860A4DCD4CA3D77 /* Pods_AirMapsExplorer.framework */; }; + A622B8115793E41C70169A8B /* libPods-AirMapsExplorer.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 0E5044A406006E7C2A53E05C /* libPods-AirMapsExplorer.a */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -66,6 +65,7 @@ /* Begin PBXFileReference section */ 008F07F21AC5B25A0029DE68 /* main.jsbundle */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = main.jsbundle; sourceTree = ""; }; 00E356EE1AD99517003FC87E /* AirMapsExplorerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = AirMapsExplorerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 0E5044A406006E7C2A53E05C /* libPods-AirMapsExplorer.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-AirMapsExplorer.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 13B07F961A680F5B00A75B9A /* AirMapsExplorer.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = AirMapsExplorer.app; sourceTree = BUILT_PRODUCTS_DIR; }; 13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = AirMapsExplorer/AppDelegate.h; sourceTree = ""; }; 13B07FB01A68108700A75B9A /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AppDelegate.m; path = AirMapsExplorer/AppDelegate.m; sourceTree = ""; }; @@ -116,7 +116,6 @@ 21E6570B1D77591A00B75EE5 /* MobileCoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MobileCoreServices.framework; path = System/Library/Frameworks/MobileCoreServices.framework; sourceTree = SDKROOT; }; 21E6570D1D77591F00B75EE5 /* MapKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MapKit.framework; path = System/Library/Frameworks/MapKit.framework; sourceTree = SDKROOT; }; 21E6570F1D77594C00B75EE5 /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = System/Library/Frameworks/AudioToolbox.framework; sourceTree = SDKROOT; }; - 3591658C00398534590C8751 /* Pods_AirMapsExplorer.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_AirMapsExplorer.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 8620CC6D1DBD814A00B79BFE /* AIRGMSMarker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRGMSMarker.h; sourceTree = ""; }; 8620CC6E1DBD814A00B79BFE /* AIRGMSMarker.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRGMSMarker.m; sourceTree = ""; }; 8620CC6F1DBD814A00B79BFE /* AIRGoogleMap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRGoogleMap.h; sourceTree = ""; }; @@ -147,12 +146,12 @@ 8697D6211DBEDE6100DB7D0F /* AIRGoogleMapCircle.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRGoogleMapCircle.m; sourceTree = ""; }; 8697D6231DBEE22B00DB7D0F /* AIRGoogleMapCircleManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRGoogleMapCircleManager.h; sourceTree = ""; }; 8697D6241DBEE22B00DB7D0F /* AIRGoogleMapCircleManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRGoogleMapCircleManager.m; sourceTree = ""; }; - BE5DE1E9AE25978F88CD940A /* Pods-AirMapsExplorer.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AirMapsExplorer.debug.xcconfig"; path = "Pods/Target Support Files/Pods-AirMapsExplorer/Pods-AirMapsExplorer.debug.xcconfig"; sourceTree = ""; }; - E138AD0CDB08FE57B09B18F8 /* Pods-AirMapsExplorer.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AirMapsExplorer.release.xcconfig"; path = "Pods/Target Support Files/Pods-AirMapsExplorer/Pods-AirMapsExplorer.release.xcconfig"; sourceTree = ""; }; 86DE6F861DCE7D21002A5053 /* AIRGoogleMapUrlTile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRGoogleMapUrlTile.h; sourceTree = ""; }; 86DE6F871DCE7D21002A5053 /* AIRGoogleMapUrlTile.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRGoogleMapUrlTile.m; sourceTree = ""; }; 86DE6F891DCE8543002A5053 /* AIRGoogleMapUrlTileManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRGoogleMapUrlTileManager.h; sourceTree = ""; }; 86DE6F8A1DCE8543002A5053 /* AIRGoogleMapURLTileManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRGoogleMapURLTileManager.m; sourceTree = ""; }; + BE5DE1E9AE25978F88CD940A /* Pods-AirMapsExplorer.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AirMapsExplorer.debug.xcconfig"; path = "Pods/Target Support Files/Pods-AirMapsExplorer/Pods-AirMapsExplorer.debug.xcconfig"; sourceTree = ""; }; + E138AD0CDB08FE57B09B18F8 /* Pods-AirMapsExplorer.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AirMapsExplorer.release.xcconfig"; path = "Pods/Target Support Files/Pods-AirMapsExplorer/Pods-AirMapsExplorer.release.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -171,7 +170,7 @@ 21E6570E1D77591F00B75EE5 /* MapKit.framework in Frameworks */, 21E6570C1D77591A00B75EE5 /* MobileCoreServices.framework in Frameworks */, 21E6570A1D77591400B75EE5 /* SystemConfiguration.framework in Frameworks */, - 3E4E0B5921E01BC4043FD8CD /* Pods_AirMapsExplorer.framework in Frameworks */, + A622B8115793E41C70169A8B /* libPods-AirMapsExplorer.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -190,7 +189,7 @@ 21E6570D1D77591F00B75EE5 /* MapKit.framework */, 21E6570B1D77591A00B75EE5 /* MobileCoreServices.framework */, 21E657091D77591400B75EE5 /* SystemConfiguration.framework */, - 3591658C00398534590C8751 /* Pods_AirMapsExplorer.framework */, + 0E5044A406006E7C2A53E05C /* libPods-AirMapsExplorer.a */, ); name = Frameworks; sourceTree = ""; diff --git a/example/ios/Podfile b/example/ios/Podfile index 4da2704b9..80b14bdc1 100644 --- a/example/ios/Podfile +++ b/example/ios/Podfile @@ -1,18 +1,14 @@ -# You Podfile should look similar to this file. Whether you use_frameworks! or not, the following configuration should work. -# -# However if you DO NOT use_frameworks! and you prefer to install pods instead of -# dragging the AirMaps directory into your project, refer to the comments below (steps 1~4) - +# You Podfile should look similar to this file. React Native currently does not support use_frameworks! source 'https://github.com/CocoaPods/Specs.git' platform :ios, '8.0' -use_frameworks! # Change 'AirMapsExplorer' to match the target in your Xcode project. target 'AirMapsExplorer' do pod 'React', path: '../node_modules/react-native', :subspecs => [ 'Core', 'RCTActionSheet', + 'RCTAnimation', 'RCTGeolocation', 'RCTImage', 'RCTLinkingIOS', @@ -23,29 +19,9 @@ target 'AirMapsExplorer' do 'RCTWebSocket' ] -# when not using frameworks we can do this instead of including the source files in our project (1/4): -# pod 'react-native-maps', path: '../../' -# pod 'react-native-google-maps', path: '../../' # <~~ if you need GoogleMaps support on iOS - -# when not using frameworks we can remove this line (2/4): pod 'GoogleMaps' # <~~ remove this line if you do not want to support GoogleMaps on iOS -end -# when not using frameworks this might be necessary, but try without it first and see if `pod install` works (3/4): -# THIS IS ONLY NECESSARY IF YOU NEED GoogleMaps SUPPORT -# pre_install do |installer| - # # copied from https://github.com/CocoaPods/CocoaPods/issues/2926 - # # workaround for https://github.com/CocoaPods/CocoaPods/issues/3289 - # def installer.verify_no_static_framework_transitive_dependencies; end -# end - -# when not using frameworks (4/4): -# THIS IS ONLY NECESSARY IF YOU NEED GoogleMaps SUPPORT -# #Crud, this shouldn't be necessary, but https://github.com/CocoaPods/CocoaPods/issues/5429 -# post_install do |installer| -# installer.pods_project.targets.each do |target| -# target.build_configurations.each do |config| -# config.build_settings['CLANG_ENABLE_MODULES'] = 'NO' -# end -# end -# end +# when not using frameworks we can do this instead of including the source files in our project (1/4): +# pod 'react-native-maps', path: '../../' +# pod 'react-native-google-maps', path: '../../' # <~~ if you need GoogleMaps support on iOS +end diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index 1f4c2d9a6..5e689bb4a 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -1,34 +1,43 @@ PODS: - - GoogleMaps (2.1.0): - - GoogleMaps/Maps (= 2.1.0) - - GoogleMaps/Base (2.1.0) - - GoogleMaps/Maps (2.1.0): - - GoogleMaps/Base (= 2.1.0) - - React/Core (0.35.0) - - React/RCTActionSheet (0.35.0): + - GoogleMaps (2.1.1): + - GoogleMaps/Maps (= 2.1.1) + - GoogleMaps/Base (2.1.1) + - GoogleMaps/Maps (2.1.1): + - GoogleMaps/Base + - React/Core (0.40.0): + - React/cxxreact + - React/yoga + - React/cxxreact (0.40.0): + - React/jschelpers + - React/jschelpers (0.40.0) + - React/RCTActionSheet (0.40.0): - React/Core - - React/RCTGeolocation (0.35.0): + - React/RCTAnimation (0.40.0): - React/Core - - React/RCTImage (0.35.0): + - React/RCTGeolocation (0.40.0): + - React/Core + - React/RCTImage (0.40.0): - React/Core - React/RCTNetwork - - React/RCTLinkingIOS (0.35.0): + - React/RCTLinkingIOS (0.40.0): - React/Core - - React/RCTNetwork (0.35.0): + - React/RCTNetwork (0.40.0): - React/Core - - React/RCTSettings (0.35.0): + - React/RCTSettings (0.40.0): - React/Core - - React/RCTText (0.35.0): + - React/RCTText (0.40.0): - React/Core - - React/RCTVibration (0.35.0): + - React/RCTVibration (0.40.0): - React/Core - - React/RCTWebSocket (0.35.0): + - React/RCTWebSocket (0.40.0): - React/Core + - React/yoga (0.40.0) DEPENDENCIES: - GoogleMaps - React/Core (from `../node_modules/react-native`) - React/RCTActionSheet (from `../node_modules/react-native`) + - React/RCTAnimation (from `../node_modules/react-native`) - React/RCTGeolocation (from `../node_modules/react-native`) - React/RCTImage (from `../node_modules/react-native`) - React/RCTLinkingIOS (from `../node_modules/react-native`) @@ -43,9 +52,9 @@ EXTERNAL SOURCES: :path: "../node_modules/react-native" SPEC CHECKSUMS: - GoogleMaps: 06589b9a38097bce0cd6e90f0fd9b5e4b4a9344c - React: d80af5410aa500d0cb1bce2cc4493a584cf2ec92 + GoogleMaps: a5b5bbe47734e2443bde781a6aa64e69fdb6d785 + React: 6dfb2f72edb1d74a800127ae157af038646673ce -PODFILE CHECKSUM: be65689c848eff5d4099a483239b72acab62f6a4 +PODFILE CHECKSUM: ffbc20bd08f662256d501d07a70e77862684f702 COCOAPODS: 1.1.1 From 39e9e1e8ee6fc01e665162ef0635c4bebd700a0f Mon Sep 17 00:00:00 2001 From: Spike Brehm Date: Fri, 6 Jan 2017 17:39:55 -0800 Subject: [PATCH 0181/1148] Update CHANGELOG for 0.12.3 --- CHANGELOG.md | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ab346a877..9454e2c6d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,37 @@ # Change Log +## 0.12.3 (January 6, 2017) + +### Patches + +* Fix "Animating with MapViews" example – fixes #763 + [#888](https://github.com/airbnb/react-native-maps/pull/888) + (@javiercr) +* [iOS] Fix "Option 2" method of building Google Maps + [#900](https://github.com/airbnb/react-native-maps/pull/900) + (@vjeranc) +* [Android] Fix exception when animating region during initialization + [#901](https://github.com/airbnb/react-native-maps/pull/901) + (@mlanter) +* Updated documentation + [#902](https://github.com/airbnb/react-native-maps/pull/902), + [#904](https://github.com/airbnb/react-native-maps/pull/904), + [#910](https://github.com/airbnb/react-native-maps/pull/910) + (@anami, @dboydor, @ali-alamine) +* + [#](https://github.com/airbnb/react-native-maps/pull/) + (@) +* + [#](https://github.com/airbnb/react-native-maps/pull/) + (@) +* + [#](https://github.com/airbnb/react-native-maps/pull/) + (@) +* + [#](https://github.com/airbnb/react-native-maps/pull/) + (@) + + ## 0.12.2 (December 9, 2016) ### Patches From f3d371213da32583f0b5ebb3d328a918a021b4d6 Mon Sep 17 00:00:00 2001 From: Spike Brehm Date: Fri, 6 Jan 2017 17:40:11 -0800 Subject: [PATCH 0182/1148] 0.12.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 83444baa6..c6caed556 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "description": "React Native Mapview component for iOS + Android", "main": "index.js", "author": "Leland Richardson ", - "version": "0.12.2", + "version": "0.12.3", "scripts": { "start": "react-native start", "lint": "eslint ." From ff9bf142119bcdb24a2f91648afa987874c86a1b Mon Sep 17 00:00:00 2001 From: Spike Brehm Date: Fri, 6 Jan 2017 17:43:17 -0800 Subject: [PATCH 0183/1148] Update version in all the places --- android/gradle.properties | 2 +- react-native-google-maps.podspec | 2 +- react-native-maps.podspec | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/android/gradle.properties b/android/gradle.properties index efa308fce..dd20adf2b 100644 --- a/android/gradle.properties +++ b/android/gradle.properties @@ -1,5 +1,5 @@ VERSION_CODE=2 -VERSION_NAME=0.12.2 +VERSION_NAME=0.12.3 GROUP=com.airbnb.android POM_DESCRIPTION=React Native Map view component for Android diff --git a/react-native-google-maps.podspec b/react-native-google-maps.podspec index 8ec70ea43..3bac5a282 100644 --- a/react-native-google-maps.podspec +++ b/react-native-google-maps.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "react-native-google-maps" - s.version = "0.12.2" + s.version = "0.12.3" s.summary = "React Native Mapview component for iOS + Android" s.authors = { "intelligibabble" => "leland.m.richardson@gmail.com" } diff --git a/react-native-maps.podspec b/react-native-maps.podspec index cb2cffa26..0b783ac2e 100644 --- a/react-native-maps.podspec +++ b/react-native-maps.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "react-native-maps" - s.version = "0.12.2" + s.version = "0.12.3" s.summary = "React Native Mapview component for iOS + Android" s.authors = { "intelligibabble" => "leland.m.richardson@gmail.com" } From 67d958efdd0bdecd980a5081ac75c13336a6bf64 Mon Sep 17 00:00:00 2001 From: Spike Brehm Date: Fri, 6 Jan 2017 17:48:30 -0800 Subject: [PATCH 0184/1148] Update CHANGELOG for 0.13.0 --- CHANGELOG.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9454e2c6d..a4c8766a3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,19 @@ # Change Log +## 0.13.0 (January 6, 2017) + +### Breaking Changes + +* Update iOS header imports and JS SyntheticEvent import for RN 0.40 + [#923](https://github.com/airbnb/react-native-maps/pull/923) + (@ide) + +### Patches + +* Fix issue where callouts sometimes overlap or don't appear + [#936](https://github.com/airbnb/react-native-maps/pull/936) + (@RajkumarPunchh) + ## 0.12.3 (January 6, 2017) ### Patches From edec7e88d36ef50eede860720de908490cf99549 Mon Sep 17 00:00:00 2001 From: Spike Brehm Date: Fri, 6 Jan 2017 17:48:50 -0800 Subject: [PATCH 0185/1148] 0.13.0 --- android/gradle.properties | 2 +- package.json | 2 +- react-native-google-maps.podspec | 2 +- react-native-maps.podspec | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/android/gradle.properties b/android/gradle.properties index dd20adf2b..81ab2a1bd 100644 --- a/android/gradle.properties +++ b/android/gradle.properties @@ -1,5 +1,5 @@ VERSION_CODE=2 -VERSION_NAME=0.12.3 +VERSION_NAME=0.13.0 GROUP=com.airbnb.android POM_DESCRIPTION=React Native Map view component for Android diff --git a/package.json b/package.json index c6caed556..016a69c97 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "description": "React Native Mapview component for iOS + Android", "main": "index.js", "author": "Leland Richardson ", - "version": "0.12.3", + "version": "0.13.0", "scripts": { "start": "react-native start", "lint": "eslint ." diff --git a/react-native-google-maps.podspec b/react-native-google-maps.podspec index 3bac5a282..6f6b28703 100644 --- a/react-native-google-maps.podspec +++ b/react-native-google-maps.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "react-native-google-maps" - s.version = "0.12.3" + s.version = "0.13.0" s.summary = "React Native Mapview component for iOS + Android" s.authors = { "intelligibabble" => "leland.m.richardson@gmail.com" } diff --git a/react-native-maps.podspec b/react-native-maps.podspec index 0b783ac2e..601e4eb71 100644 --- a/react-native-maps.podspec +++ b/react-native-maps.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "react-native-maps" - s.version = "0.12.3" + s.version = "0.13.0" s.summary = "React Native Mapview component for iOS + Android" s.authors = { "intelligibabble" => "leland.m.richardson@gmail.com" } From 4b3a2963a8125410d9158a5c4c1d6e595f619842 Mon Sep 17 00:00:00 2001 From: Spike Brehm Date: Fri, 6 Jan 2017 17:51:08 -0800 Subject: [PATCH 0186/1148] Remove cruft from CHANGELOG --- CHANGELOG.md | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a4c8766a3..0fc969558 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,18 +32,6 @@ [#904](https://github.com/airbnb/react-native-maps/pull/904), [#910](https://github.com/airbnb/react-native-maps/pull/910) (@anami, @dboydor, @ali-alamine) -* - [#](https://github.com/airbnb/react-native-maps/pull/) - (@) -* - [#](https://github.com/airbnb/react-native-maps/pull/) - (@) -* - [#](https://github.com/airbnb/react-native-maps/pull/) - (@) -* - [#](https://github.com/airbnb/react-native-maps/pull/) - (@) ## 0.12.2 (December 9, 2016) From a4565b933de8fdc86f67a0149408a7eeb613532b Mon Sep 17 00:00:00 2001 From: Stan Bershadskiy Date: Mon, 9 Jan 2017 12:36:34 -0500 Subject: [PATCH 0187/1148] add identifier to marker press event --- .../main/java/com/airbnb/android/react/maps/AirMapView.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java b/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java index 5d8de64af..ea316c195 100644 --- a/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java +++ b/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java @@ -149,13 +149,16 @@ public void onMapReady(final GoogleMap map) { @Override public boolean onMarkerClick(Marker marker) { WritableMap event; + AirMapMarker airMapMarker = markerMap.get(marker); event = makeClickEventData(marker.getPosition()); event.putString("action", "marker-press"); + event.putString("id", airMapMarker.getIdentifier()); manager.pushEvent(view, "onMarkerPress", event); event = makeClickEventData(marker.getPosition()); event.putString("action", "marker-press"); + event.putString("id", airMapMarker.getIdentifier()); manager.pushEvent(markerMap.get(marker), "onPress", event); // Return false to open the callout info window and center on the marker From f5bb3df969950a8b6454141decb4c338b95f5780 Mon Sep 17 00:00:00 2001 From: rajkumarpunchh Date: Thu, 12 Jan 2017 15:49:31 +0530 Subject: [PATCH 0188/1148] =?UTF-8?q?Fixed=20issue=20#286.=20onPress=20and?= =?UTF-8?q?=20onCalloutPress=20not=20doesn=E2=80=99t=20trigger=20on=20mark?= =?UTF-8?q?ers=20in=20iOS.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ios/AirMaps/AIRMapMarker.h | 1 + ios/AirMaps/AIRMapMarker.m | 51 +++++++++++++++++++++++++++++++ ios/AirMaps/AIRMapMarkerManager.m | 41 +------------------------ 3 files changed, 53 insertions(+), 40 deletions(-) diff --git a/ios/AirMaps/AIRMapMarker.h b/ios/AirMaps/AIRMapMarker.h index 97440639f..828357b70 100644 --- a/ios/AirMaps/AIRMapMarker.h +++ b/ios/AirMaps/AIRMapMarker.h @@ -48,6 +48,7 @@ - (BOOL)shouldShowCalloutView; - (void)showCalloutView; - (void)hideCalloutView; +- (void)addTapGestureRecognizer; @end diff --git a/ios/AirMaps/AIRMapMarker.m b/ios/AirMaps/AIRMapMarker.m index 2d7d086d4..9f40d06a6 100644 --- a/ios/AirMaps/AIRMapMarker.m +++ b/ios/AirMaps/AIRMapMarker.m @@ -71,6 +71,7 @@ - (MKAnnotationView *)getAnnotationView // In this case, we want to render a platform "default" marker. if (_pinView == nil) { _pinView = [[MKPinAnnotationView alloc] initWithAnnotation:self reuseIdentifier: nil]; + [self addGestureRecognizerToView:_pinView]; _pinView.annotation = self; } @@ -167,6 +168,56 @@ - (void)showCalloutView animated:YES]; } +#pragma mark - Tap Gesture & Events. + +- (void)addTapGestureRecognizer { + [self addGestureRecognizerToView:nil]; +} + +- (void)addGestureRecognizerToView:(UIView *)view { + if (!view) { + view = self; + } + UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(_handleTap:)]; + // setting this to NO allows the parent MapView to continue receiving marker selection events + tapGestureRecognizer.cancelsTouchesInView = NO; + [view addGestureRecognizer:tapGestureRecognizer]; +} + +- (void)_handleTap:(UITapGestureRecognizer *)recognizer { + AIRMapMarker *marker = self; + if (!marker) return; + + if (marker.selected) { + CGPoint touchPoint = [recognizer locationInView:marker.map.calloutView]; + if ([marker.map.calloutView hitTest:touchPoint withEvent:nil]) { + + // the callout got clicked, not the marker + id event = @{ + @"action": @"callout-press", + }; + + if (marker.onCalloutPress) marker.onCalloutPress(event); + if (marker.calloutView && marker.calloutView.onPress) marker.calloutView.onPress(event); + if (marker.map.onCalloutPress) marker.map.onCalloutPress(event); + return; + } + } + + // the actual marker got clicked + id event = @{ + @"action": @"marker-press", + @"id": marker.identifier ?: @"unknown", + @"coordinate": @{ + @"latitude": @(marker.coordinate.latitude), + @"longitude": @(marker.coordinate.longitude) + } + }; + + if (marker.onPress) marker.onPress(event); + if (marker.map.onMarkerPress) marker.map.onMarkerPress(event); +} + - (void)hideCalloutView { // hide the callout view diff --git a/ios/AirMaps/AIRMapMarkerManager.m b/ios/AirMaps/AIRMapMarkerManager.m index 493d6cc2e..38a6d5a25 100644 --- a/ios/AirMaps/AIRMapMarkerManager.m +++ b/ios/AirMaps/AIRMapMarkerManager.m @@ -25,10 +25,7 @@ @implementation AIRMapMarkerManager - (UIView *)view { AIRMapMarker *marker = [AIRMapMarker new]; - UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(_handleTap:)]; - // setting this to NO allows the parent MapView to continue receiving marker selection events - tapGestureRecognizer.cancelsTouchesInView = NO; - [marker addGestureRecognizer:tapGestureRecognizer]; + [marker addTapGestureRecognizer]; marker.bridge = self.bridge; return marker; } @@ -78,40 +75,4 @@ - (UIView *)view }]; } -#pragma mark - Events - -- (void)_handleTap:(UITapGestureRecognizer *)recognizer { - AIRMapMarker *marker = (AIRMapMarker *)recognizer.view; - if (!marker) return; - - if (marker.selected) { - CGPoint touchPoint = [recognizer locationInView:marker.map.calloutView]; - if ([marker.map.calloutView hitTest:touchPoint withEvent:nil]) { - - // the callout got clicked, not the marker - id event = @{ - @"action": @"callout-press", - }; - - if (marker.onCalloutPress) marker.onCalloutPress(event); - if (marker.calloutView && marker.calloutView.onPress) marker.calloutView.onPress(event); - if (marker.map.onCalloutPress) marker.map.onCalloutPress(event); - return; - } - } - - // the actual marker got clicked - id event = @{ - @"action": @"marker-press", - @"id": marker.identifier ?: @"unknown", - @"coordinate": @{ - @"latitude": @(marker.coordinate.latitude), - @"longitude": @(marker.coordinate.longitude) - } - }; - - if (marker.onPress) marker.onPress(event); - if (marker.map.onMarkerPress) marker.map.onMarkerPress(event); -} - @end From c3e05b58fa7c961948311443b7aa44e32df69820 Mon Sep 17 00:00:00 2001 From: Mike Zou Date: Thu, 12 Jan 2017 13:54:16 -0500 Subject: [PATCH 0189/1148] Update doc for polyline (#956) Fix the minor error: polygon => polyline --- docs/polyline.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/polyline.md b/docs/polyline.md index c542c4ce3..89ef9de25 100644 --- a/docs/polyline.md +++ b/docs/polyline.md @@ -4,7 +4,7 @@ | Prop | Type | Default | Note | |---|---|---|---| -| `coordinates` | `Array` | (Required) | An array of coordinates to describe the polygon +| `coordinates` | `Array` | (Required) | An array of coordinates to describe the polyline | `strokeWidth` | `Number` | `1` | The stroke width to use for the path. | `strokeColor` | `String` | `#000` | The stroke color to use for the path. | `lineCap` | `String` | `round` | The line cap style to apply to the open ends of the path. From 9384bb62c9733eb39e76dbd39fe916b0d58996d6 Mon Sep 17 00:00:00 2001 From: Nick Italiano Date: Sat, 31 Dec 2016 10:54:39 -0800 Subject: [PATCH 0190/1148] Added setNativeProps support to shape overlays --- components/MapCircle.js | 6 +- components/MapMarker.js | 4 + components/MapPolygon.js | 6 +- components/MapPolyline.js | 6 +- example/App.js | 2 + example/examples/SetNativePropsOverlays.js | 162 +++++++++++++++++++++ 6 files changed, 183 insertions(+), 3 deletions(-) create mode 100644 example/examples/SetNativePropsOverlays.js diff --git a/components/MapCircle.js b/components/MapCircle.js index 25c97a787..aab1ba8f1 100644 --- a/components/MapCircle.js +++ b/components/MapCircle.js @@ -125,10 +125,14 @@ const defaultProps = { }; class MapCircle extends React.Component { + setNativeProps(props) { + this.circle.setNativeProps(props); + } + render() { const AIRMapCircle = this.getAirComponent(); return ( - + { this.circle = ref; }} /> ); } } diff --git a/components/MapMarker.js b/components/MapMarker.js index 45ed6c300..72adbd767 100644 --- a/components/MapMarker.js +++ b/components/MapMarker.js @@ -212,6 +212,10 @@ class MapMarker extends React.Component { this.hideCallout = this.hideCallout.bind(this); } + setNativeProps(props) { + this.marker.setNativeProps(props); + } + showCallout() { this._runCommand('showCallout', []); } diff --git a/components/MapPolygon.js b/components/MapPolygon.js index 38c972e0c..7baea77db 100644 --- a/components/MapPolygon.js +++ b/components/MapPolygon.js @@ -140,10 +140,14 @@ const defaultProps = { }; class MapPolygon extends React.Component { + setNativeProps(props) { + this.polygon.setNativeProps(props); + } + render() { const AIRMapPolygon = this.getAirComponent(); return ( - + { this.polygon = ref; }} /> ); } } diff --git a/components/MapPolyline.js b/components/MapPolyline.js index 684e1d71d..35b4c6048 100644 --- a/components/MapPolyline.js +++ b/components/MapPolyline.js @@ -130,10 +130,14 @@ const defaultProps = { }; class MapPolyline extends React.Component { + setNativeProps(props) { + this.polyline.setNativeProps(props); + } + render() { const AIRMapPolyline = this.getAirComponent(); return ( - + { this.polyline = ref; }} /> ); } } diff --git a/example/App.js b/example/App.js index 696682ba0..0275f519e 100644 --- a/example/App.js +++ b/example/App.js @@ -33,6 +33,7 @@ import ZIndexMarkers from './examples/ZIndexMarkers'; import StaticMap from './examples/StaticMap'; import MapStyle from './examples/MapStyle'; import LegalLabel from './examples/LegalLabel'; +import SetNativePropsOverlays from './examples/SetNativePropsOverlays'; const IOS = Platform.OS === 'ios'; const ANDROID = Platform.OS === 'android'; @@ -144,6 +145,7 @@ class App extends React.Component { [ZIndexMarkers, 'Position Markers with Z-index', true], [MapStyle, 'Customize the style of the map', true], [LegalLabel, 'Reposition the legal label', true], + [SetNativePropsOverlays, 'Update native props', true], ] // Filter out examples that are not yet supported for Google Maps on iOS. .filter(example => ANDROID || (IOS && (example[2] || !this.state.useGoogleMaps))) diff --git a/example/examples/SetNativePropsOverlays.js b/example/examples/SetNativePropsOverlays.js new file mode 100644 index 000000000..2545c205b --- /dev/null +++ b/example/examples/SetNativePropsOverlays.js @@ -0,0 +1,162 @@ +import React from 'react'; +import { + StyleSheet, + View, + Text, + TouchableOpacity, + Dimensions, +} from 'react-native'; + +import MapView from 'react-native-maps'; + +const { width, height } = Dimensions.get('window'); + +const ASPECT_RATIO = width / height; +const LATITUDE = 37.78825; +const LONGITUDE = -122.4324; +const LATITUDE_DELTA = 0.0922; +const LONGITUDE_DELTA = LATITUDE_DELTA * ASPECT_RATIO; +const SPACE = 0.01; + +class SetNativePropsOverlays extends React.Component { + constructor(props) { + super(props); + + this.state = { + region: { + latitude: LATITUDE, + longitude: LONGITUDE, + latitudeDelta: LATITUDE_DELTA, + longitudeDelta: LONGITUDE_DELTA, + }, + circle: { + center: { + latitude: LATITUDE + SPACE, + longitude: LONGITUDE + SPACE, + }, + radius: 700, + }, + polygon: [ + { + latitude: LATITUDE + SPACE, + longitude: LONGITUDE + SPACE, + }, + { + latitude: LATITUDE - SPACE, + longitude: LONGITUDE - SPACE, + }, + { + latitude: LATITUDE - SPACE, + longitude: LONGITUDE + SPACE, + }, + ], + polyline: [ + { + latitude: LATITUDE + SPACE, + longitude: LONGITUDE - SPACE, + }, + { + latitude: LATITUDE - (2 * SPACE), + longitude: LONGITUDE + (2 * SPACE), + }, + { + latitude: LATITUDE - SPACE, + longitude: LONGITUDE - SPACE, + }, + { + latitude: LATITUDE - (2 * SPACE), + longitude: LONGITUDE - SPACE, + }, + ], + }; + } + + handleColorChange(color) { + const props = { strokeColor: color }; + this.circle.setNativeProps(props); + this.polygon.setNativeProps(props); + this.polyline.setNativeProps(props); + } + + render() { + const { region, circle, polygon, polyline } = this.state; + return ( + + + this.circle = ref} + center={circle.center} + radius={circle.radius} + fillColor="rgba(255, 255, 255, 0.6)" + strokeColor="green" + zIndex={3} + strokeWidth={3} + /> + this.polygon = ref} + coordinates={polygon} + fillColor="rgba(255, 255, 255, 0.6)" + strokeColor="green" + strokeWidth={2} + /> + this.polyline = ref} + coordinates={polyline} + strokeColor="green" + strokeWidth={3} + /> + + + this.handleColorChange('green')}> + + Green + + + this.handleColorChange('black')}> + + Black + + + this.handleColorChange('red')}> + + Red + + + + + ); + } +} + +SetNativePropsOverlays.propTypes = { + provider: MapView.ProviderPropType, +}; + +const styles = StyleSheet.create({ + container: { + ...StyleSheet.absoluteFillObject, + justifyContent: 'flex-end', + alignItems: 'center', + }, + map: { + ...StyleSheet.absoluteFillObject, + }, + bubble: { + flex: 1, + backgroundColor: 'rgba(255,255,255,0.7)', + paddingHorizontal: 18, + paddingVertical: 12, + borderRadius: 20, + }, + buttonContainer: { + flexDirection: 'row', + marginVertical: 20, + backgroundColor: 'transparent', + }, +}); + +module.exports = SetNativePropsOverlays; From fa4d9b05f4ceb2fb764451e70224b48095477e67 Mon Sep 17 00:00:00 2001 From: Nick Italiano Date: Sun, 1 Jan 2017 11:40:10 -0800 Subject: [PATCH 0191/1148] Added support to nest overlays in views and react components --- .../airbnb/android/react/maps/AirMapView.java | 5 +- example/App.js | 2 + example/examples/CustomOverlay.js | 116 ++++++++++++++++++ ios/AirGoogleMaps/AIRGoogleMap.m | 10 ++ ios/AirMaps/AIRMap.m | 10 ++ 5 files changed, 142 insertions(+), 1 deletion(-) create mode 100644 example/examples/CustomOverlay.js diff --git a/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java b/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java index 5d8de64af..d32942689 100644 --- a/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java +++ b/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java @@ -420,7 +420,10 @@ public void addFeature(View child, int index) { urlTileView.addToMap(map); features.add(index, urlTileView); } else { - // TODO(lmr): throw? User shouldn't be adding non-feature children. + ViewGroup children = (ViewGroup) child; + for (int i = 0; i < children.getChildCount(); i++) { + addFeature(children.getChildAt(i), index); + } } } diff --git a/example/App.js b/example/App.js index 0275f519e..43c39580a 100644 --- a/example/App.js +++ b/example/App.js @@ -34,6 +34,7 @@ import StaticMap from './examples/StaticMap'; import MapStyle from './examples/MapStyle'; import LegalLabel from './examples/LegalLabel'; import SetNativePropsOverlays from './examples/SetNativePropsOverlays'; +import CustomOverlay from './examples/CustomOverlay'; const IOS = Platform.OS === 'ios'; const ANDROID = Platform.OS === 'android'; @@ -146,6 +147,7 @@ class App extends React.Component { [MapStyle, 'Customize the style of the map', true], [LegalLabel, 'Reposition the legal label', true], [SetNativePropsOverlays, 'Update native props', true], + [CustomOverlay, 'Custom Overlay Component', true], ] // Filter out examples that are not yet supported for Google Maps on iOS. .filter(example => ANDROID || (IOS && (example[2] || !this.state.useGoogleMaps))) diff --git a/example/examples/CustomOverlay.js b/example/examples/CustomOverlay.js new file mode 100644 index 000000000..bebe1da25 --- /dev/null +++ b/example/examples/CustomOverlay.js @@ -0,0 +1,116 @@ +import React, { PropTypes } from 'react'; +import { + StyleSheet, + View, + Text, + TouchableOpacity, + Dimensions, +} from 'react-native'; + +import MapView from 'react-native-maps'; + +const { width, height } = Dimensions.get('window'); +const ASPECT_RATIO = width / height; +const LATITUDE = 37.78825; +const LONGITUDE = -122.4324; +const LATITUDE_DELTA = 0.0922; +const LONGITUDE_DELTA = LATITUDE_DELTA * ASPECT_RATIO; +const SPACE = 0.01; + +class XMarksTheSpot extends React.Component { + render() { + return ( + + + + + + + ); + } +} + +XMarksTheSpot.propTypes = { + coordinates: PropTypes.array, + center: PropTypes.object, + zIndex: PropTypes.number, +}; + +class CustomOverlay extends React.Component { + constructor(props) { + super(props); + + this.state = { + region: { + latitude: LATITUDE, + longitude: LONGITUDE, + latitudeDelta: LATITUDE_DELTA, + longitudeDelta: LONGITUDE_DELTA, + }, + coordinates: [ + { + longitude: -122.442753, + latitude: 37.798790, + }, + { + longitude: -122.424728, + latitude: 37.801232, + }, + { + longitude: -122.422497, + latitude: 37.790651, + }, + { + longitude: -122.440693, + latitude: 37.788209, + }, + ], + center: { + longitude: -122.4326648935676, + latitude: 37.79418561114521, + }, + }; + } + + render() { + const { coordinates, center, region } = this.state; + return ( + + + + + + ); + } +} + +CustomOverlay.propTypes = { + provider: MapView.ProviderPropType, +}; + +const styles = StyleSheet.create({ + container: { + ...StyleSheet.absoluteFillObject, + justifyContent: 'flex-end', + alignItems: 'center', + }, + map: { + ...StyleSheet.absoluteFillObject, + }, +}); + +module.exports = CustomOverlay; diff --git a/ios/AirGoogleMaps/AIRGoogleMap.m b/ios/AirGoogleMaps/AIRGoogleMap.m index 39c8bb3a6..e6d028c31 100644 --- a/ios/AirGoogleMaps/AIRGoogleMap.m +++ b/ios/AirGoogleMaps/AIRGoogleMap.m @@ -91,6 +91,11 @@ - (void)insertReactSubview:(id)subview atIndex:(NSInteger)atIndex AIRGoogleMapUrlTile *tile = (AIRGoogleMapUrlTile*)subview; tile.tileLayer.map = self; [self.tiles addObject:tile]; + } else { + NSArray> *childSubviews = [subview reactSubviews]; + for (int i = 0; i < childSubviews.count; i++) { + [self insertReactSubview:(UIView *)childSubviews[i] atIndex:atIndex]; + } } [_reactSubviews insertObject:(UIView *)subview atIndex:(NSUInteger) atIndex]; } @@ -122,6 +127,11 @@ - (void)removeReactSubview:(id)subview { AIRGoogleMapUrlTile *tile = (AIRGoogleMapUrlTile*)subview; tile.tileLayer.map = nil; [self.tiles removeObject:tile]; + } else { + NSArray> *childSubviews = [subview reactSubviews]; + for (int i = 0; i < childSubviews.count; i++) { + [self removeReactSubview:(UIView *)childSubviews[i]]; + } } [_reactSubviews removeObject:(UIView *)subview]; } diff --git a/ios/AirMaps/AIRMap.m b/ios/AirMaps/AIRMap.m index 1126c3825..e1b4d57ee 100644 --- a/ios/AirMaps/AIRMap.m +++ b/ios/AirMaps/AIRMap.m @@ -105,6 +105,11 @@ - (void)insertReactSubview:(id)subview atIndex:(NSInteger)atIndex [self addOverlay:(id)subview]; } else if ([subview isKindOfClass:[AIRMapUrlTile class]]) { [self addOverlay:(id)subview]; + } else { + NSArray> *childSubviews = [subview reactSubviews]; + for (int i = 0; i < childSubviews.count; i++) { + [self insertReactSubview:(UIView *)childSubviews[i] atIndex:atIndex]; + } } [_reactSubviews insertObject:(UIView *)subview atIndex:(NSUInteger) atIndex]; } @@ -125,6 +130,11 @@ - (void)removeReactSubview:(id)subview { [self removeOverlay:(id ) subview]; } else if ([subview isKindOfClass:[AIRMapUrlTile class]]) { [self removeOverlay:(id ) subview]; + } else { + NSArray> *childSubviews = [subview reactSubviews]; + for (int i = 0; i < childSubviews.count; i++) { + [self removeReactSubview:(UIView *)childSubviews[i]]; + } } [_reactSubviews removeObject:(UIView *)subview]; } From b03a27473a455809e7c195bbd005746d88243cd7 Mon Sep 17 00:00:00 2001 From: Nick Italiano Date: Mon, 2 Jan 2017 20:22:17 -0800 Subject: [PATCH 0192/1148] Added opacity prop to marker --- .../com/airbnb/android/react/maps/AirMapMarker.java | 10 ++++++++++ .../android/react/maps/AirMapMarkerManager.java | 7 +++++++ components/MapMarker.js | 5 +++++ example/examples/MarkerTypes.js | 11 +++++++++++ ios/AirGoogleMaps/AIRGoogleMapMarker.h | 1 + ios/AirGoogleMaps/AIRGoogleMapMarker.m | 5 +++++ ios/AirGoogleMaps/AIRGoogleMapMarkerManager.m | 1 + ios/AirMaps/AIRMapMarker.h | 1 + ios/AirMaps/AIRMapMarker.m | 5 +++++ ios/AirMaps/AIRMapMarkerManager.m | 1 + 10 files changed, 47 insertions(+) diff --git a/android/src/main/java/com/airbnb/android/react/maps/AirMapMarker.java b/android/src/main/java/com/airbnb/android/react/maps/AirMapMarker.java index de01d106e..4041d91ac 100644 --- a/android/src/main/java/com/airbnb/android/react/maps/AirMapMarker.java +++ b/android/src/main/java/com/airbnb/android/react/maps/AirMapMarker.java @@ -62,6 +62,7 @@ public class AirMapMarker extends AirMapFeature { private boolean flat = false; private boolean draggable = false; private int zIndex = 0; + private float opacity = 1.0f; private float calloutAnchorX; private float calloutAnchorY; @@ -182,6 +183,14 @@ public void setZIndex(int zIndex) { update(); } + public void setOpacity(float opacity) { + this.opacity = opacity; + if (marker != null) { + marker.setAlpha(opacity); + } + update(); + } + public void setMarkerHue(float markerHue) { this.markerHue = markerHue; update(); @@ -298,6 +307,7 @@ private MarkerOptions createMarkerOptions() { options.flat(flat); options.draggable(draggable); options.zIndex(zIndex); + options.alpha(opacity); options.icon(getIcon()); return options; } diff --git a/android/src/main/java/com/airbnb/android/react/maps/AirMapMarkerManager.java b/android/src/main/java/com/airbnb/android/react/maps/AirMapMarkerManager.java index f6da4c1cd..e035e1e14 100644 --- a/android/src/main/java/com/airbnb/android/react/maps/AirMapMarkerManager.java +++ b/android/src/main/java/com/airbnb/android/react/maps/AirMapMarkerManager.java @@ -124,6 +124,13 @@ public void setZIndex(AirMapMarker view, float zIndex) { view.setZIndex(integerZIndex); } + @Override + @ReactProp(name = "opacity", defaultFloat = 1.0f) + public void setOpacity(AirMapMarker view, float opacity) { + super.setOpacity(view, opacity); + view.setOpacity(opacity); + } + @Override public void addView(AirMapMarker parent, View child, int index) { // if an component is a child, then it is a callout view, NOT part of the diff --git a/components/MapMarker.js b/components/MapMarker.js index 72adbd767..be54e42db 100644 --- a/components/MapMarker.js +++ b/components/MapMarker.js @@ -48,6 +48,11 @@ const propTypes = { */ image: PropTypes.any, + /** + * Opacity level of view/image based markers + */ + opacity: PropTypes.number, + /** * If no custom marker view or custom image is provided, the platform default pin will be used, * which can be customized by this color. Ignored if a custom marker is being used. diff --git a/example/examples/MarkerTypes.js b/example/examples/MarkerTypes.js index 7bf3a6465..76685d782 100644 --- a/example/examples/MarkerTypes.js +++ b/example/examples/MarkerTypes.js @@ -62,6 +62,17 @@ class MarkerTypes extends React.Component { anchor={{ x: 0.84, y: 1 }} image={this.state.marker2 ? flagBlueImg : flagPinkImg} /> + this.setState({ marker2: !this.state.marker2 })} + coordinate={{ + latitude: LATITUDE + SPACE, + longitude: LONGITUDE - SPACE, + }} + centerOffset={{ x: -42, y: -60 }} + anchor={{ x: 0.84, y: 1 }} + opacity={0.6} + image={this.state.marker2 ? flagBlueImg : flagPinkImg} + />
); diff --git a/ios/AirGoogleMaps/AIRGoogleMapMarker.h b/ios/AirGoogleMaps/AIRGoogleMapMarker.h index ca6a5cc12..36190e7cb 100644 --- a/ios/AirGoogleMaps/AIRGoogleMapMarker.h +++ b/ios/AirGoogleMaps/AIRGoogleMapMarker.h @@ -28,6 +28,7 @@ @property (nonatomic, strong) UIColor *pinColor; @property (nonatomic, assign) CGPoint anchor; @property (nonatomic, assign) NSInteger zIndex; +@property (nonatomic, assign) double opacity; @property (nonatomic, assign) BOOL draggable; - (void)showCalloutView; diff --git a/ios/AirGoogleMaps/AIRGoogleMapMarker.m b/ios/AirGoogleMaps/AIRGoogleMapMarker.m index 4bb10dede..2c6080e9e 100644 --- a/ios/AirGoogleMaps/AIRGoogleMapMarker.m +++ b/ios/AirGoogleMaps/AIRGoogleMapMarker.m @@ -173,6 +173,11 @@ - (RCTBubblingEventBlock)onPress { return _realMarker.onPress; } +- (void)setOpacity:(double)opacity +{ + _realMarker.opacity = opacity; +} + - (void)setImageSrc:(NSString *)imageSrc { _imageSrc = imageSrc; diff --git a/ios/AirGoogleMaps/AIRGoogleMapMarkerManager.m b/ios/AirGoogleMaps/AIRGoogleMapMarkerManager.m index 0d29c3fac..fd16f58a6 100644 --- a/ios/AirGoogleMaps/AIRGoogleMapMarkerManager.m +++ b/ios/AirGoogleMaps/AIRGoogleMapMarkerManager.m @@ -36,6 +36,7 @@ - (UIView *)view RCT_EXPORT_VIEW_PROPERTY(anchor, CGPoint) RCT_EXPORT_VIEW_PROPERTY(zIndex, NSInteger) RCT_EXPORT_VIEW_PROPERTY(draggable, BOOL) +RCT_EXPORT_VIEW_PROPERTY(opacity, double) RCT_EXPORT_VIEW_PROPERTY(onDragStart, RCTDirectEventBlock) RCT_EXPORT_VIEW_PROPERTY(onDrag, RCTDirectEventBlock) RCT_EXPORT_VIEW_PROPERTY(onDragEnd, RCTDirectEventBlock) diff --git a/ios/AirMaps/AIRMapMarker.h b/ios/AirMaps/AIRMapMarker.h index 97440639f..f92a06789 100644 --- a/ios/AirMaps/AIRMapMarker.h +++ b/ios/AirMaps/AIRMapMarker.h @@ -33,6 +33,7 @@ @property (nonatomic, assign) CLLocationCoordinate2D coordinate; @property (nonatomic, strong) UIColor *pinColor; @property (nonatomic, assign) NSInteger zIndex; +@property (nonatomic, assign) double opacity; @property (nonatomic, copy) RCTBubblingEventBlock onPress; @property (nonatomic, copy) RCTDirectEventBlock onSelect; diff --git a/ios/AirMaps/AIRMapMarker.m b/ios/AirMaps/AIRMapMarker.m index 2d7d086d4..e26574706 100644 --- a/ios/AirMaps/AIRMapMarker.m +++ b/ios/AirMaps/AIRMapMarker.m @@ -203,6 +203,11 @@ - (BOOL)shouldUsePinView return self.reactSubviews.count == 0 && !self.imageSrc; } +- (void)setOpacity:(double)opacity +{ + [self setAlpha:opacity]; +} + - (void)setImageSrc:(NSString *)imageSrc { _imageSrc = imageSrc; diff --git a/ios/AirMaps/AIRMapMarkerManager.m b/ios/AirMaps/AIRMapMarkerManager.m index 493d6cc2e..3d8b16627 100644 --- a/ios/AirMaps/AIRMapMarkerManager.m +++ b/ios/AirMaps/AIRMapMarkerManager.m @@ -44,6 +44,7 @@ - (UIView *)view RCT_EXPORT_VIEW_PROPERTY(pinColor, UIColor) RCT_EXPORT_VIEW_PROPERTY(draggable, BOOL) RCT_EXPORT_VIEW_PROPERTY(zIndex, NSInteger) +RCT_EXPORT_VIEW_PROPERTY(opacity, double) RCT_EXPORT_VIEW_PROPERTY(onPress, RCTBubblingEventBlock) RCT_EXPORT_VIEW_PROPERTY(onSelect, RCTDirectEventBlock) From 106cc02b1bfdb60ba36735f759205beb7fd3d546 Mon Sep 17 00:00:00 2001 From: Nick Italiano Date: Sun, 15 Jan 2017 14:11:30 -0800 Subject: [PATCH 0193/1148] Lint --- example/examples/CustomOverlay.js | 37 ++----------------- .../examples/CustomOverlayXMarksTheSpot.js | 34 +++++++++++++++++ example/examples/SetNativePropsOverlays.js | 12 +++--- 3 files changed, 43 insertions(+), 40 deletions(-) create mode 100644 example/examples/CustomOverlayXMarksTheSpot.js diff --git a/example/examples/CustomOverlay.js b/example/examples/CustomOverlay.js index bebe1da25..c57f83ff7 100644 --- a/example/examples/CustomOverlay.js +++ b/example/examples/CustomOverlay.js @@ -1,13 +1,12 @@ -import React, { PropTypes } from 'react'; +import React from 'react'; import { StyleSheet, View, - Text, - TouchableOpacity, Dimensions, } from 'react-native'; import MapView from 'react-native-maps'; +import XMarksTheSpot from './CustomOverlayXMarksTheSpot'; const { width, height } = Dimensions.get('window'); const ASPECT_RATIO = width / height; @@ -15,36 +14,6 @@ const LATITUDE = 37.78825; const LONGITUDE = -122.4324; const LATITUDE_DELTA = 0.0922; const LONGITUDE_DELTA = LATITUDE_DELTA * ASPECT_RATIO; -const SPACE = 0.01; - -class XMarksTheSpot extends React.Component { - render() { - return ( - - - - - - - ); - } -} - -XMarksTheSpot.propTypes = { - coordinates: PropTypes.array, - center: PropTypes.object, - zIndex: PropTypes.number, -}; class CustomOverlay extends React.Component { constructor(props) { @@ -91,7 +60,7 @@ class CustomOverlay extends React.Component { style={styles.map} initialRegion={region} > - +
); diff --git a/example/examples/CustomOverlayXMarksTheSpot.js b/example/examples/CustomOverlayXMarksTheSpot.js new file mode 100644 index 000000000..ada19da9c --- /dev/null +++ b/example/examples/CustomOverlayXMarksTheSpot.js @@ -0,0 +1,34 @@ +import React, { PropTypes } from 'react'; +import { View } from 'react-native'; +import MapView from 'react-native-maps'; + +class XMarksTheSpot extends React.Component { + render() { + return ( + + + + + + + ); + } +} + +XMarksTheSpot.propTypes = { + coordinates: PropTypes.array, + center: PropTypes.object, + zIndex: PropTypes.number, +}; + +export default XMarksTheSpot; diff --git a/example/examples/SetNativePropsOverlays.js b/example/examples/SetNativePropsOverlays.js index 2545c205b..b0dac9a80 100644 --- a/example/examples/SetNativePropsOverlays.js +++ b/example/examples/SetNativePropsOverlays.js @@ -88,7 +88,7 @@ class SetNativePropsOverlays extends React.Component { initialRegion={region} > this.circle = ref} + ref={ref => { this.circle = ref; }} center={circle.center} radius={circle.radius} fillColor="rgba(255, 255, 255, 0.6)" @@ -97,31 +97,31 @@ class SetNativePropsOverlays extends React.Component { strokeWidth={3} /> this.polygon = ref} + ref={ref => { this.polygon = ref; }} coordinates={polygon} fillColor="rgba(255, 255, 255, 0.6)" strokeColor="green" strokeWidth={2} /> this.polyline = ref} + ref={ref => { this.polyline = ref; }} coordinates={polyline} strokeColor="green" strokeWidth={3} /> - this.handleColorChange('green')}> + { this.handleColorChange('green'); }}> Green - this.handleColorChange('black')}> + { this.handleColorChange('black'); }}> Black - this.handleColorChange('red')}> + { this.handleColorChange('red'); }}> Red From db7178667843241bc8768f9fe51a4667e9ddc8c1 Mon Sep 17 00:00:00 2001 From: Osman Hernandez Date: Wed, 18 Jan 2017 10:54:07 -0600 Subject: [PATCH 0194/1148] Update circle.md (#973) --- docs/circle.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/circle.md b/docs/circle.md index 78a850283..706237c18 100644 --- a/docs/circle.md +++ b/docs/circle.md @@ -9,6 +9,7 @@ | `strokeWidth` | `Number` | `1` | The stroke width to use for the path. | `strokeColor` | `String` | `#000` | The stroke color to use for the path. | `fillColor` | `String` | | The fill color to use for the path. +| `zIndex` | `Number` | 0 | The order in which this tile overlay is drawn with respect to other overlays. An overlay with a larger z-index is drawn over overlays with smaller z-indices. The order of overlays with the same z-index is arbitrary. The default zIndex is 0. (Android Only) | `lineCap` | `String` | `round` | The line cap style to apply to the open ends of the path. | `lineJoin` | `Array` | | The line join style to apply to corners of the path. | `miterLimit` | `Number` | | The limiting value that helps avoid spikes at junctions between connected line segments. The miter limit helps you avoid spikes in paths that use the `miter` `lineJoin` style. If the ratio of the miter length—that is, the diagonal length of the miter join—to the line thickness exceeds the miter limit, the joint is converted to a bevel join. The default miter limit is 10, which results in the conversion of miters whose angle at the joint is less than 11 degrees. From aafec80185a1b0ea5eb6cede99cdf39ea4c89c7f Mon Sep 17 00:00:00 2001 From: Paulo Cesar Date: Wed, 18 Jan 2017 13:56:35 -0300 Subject: [PATCH 0195/1148] Update mapview.md (#961) add non-optional `animated` parameter to the docs --- docs/mapview.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/mapview.md b/docs/mapview.md index f05867bd2..bfab08e7d 100644 --- a/docs/mapview.md +++ b/docs/mapview.md @@ -57,7 +57,7 @@ | `animateToRegion` | `region: Region`, `duration: Number` | | `animateToCoordinate` | `region: Coordinate`, `duration: Number` | | `fitToElements` | `animated: Boolean` | -| `fitToSuppliedMarkers` | `markerIDs: String[]` | If you need to use this in `ComponentDidMount`, make sure you put it in a timeout or it will cause performance problems. +| `fitToSuppliedMarkers` | `markerIDs: String[]`, `animated: Boolean` | If you need to use this in `ComponentDidMount`, make sure you put it in a timeout or it will cause performance problems. | `fitToCoordinates` | `coordinates: Array, options: { edgePadding: EdgePadding, animated: Boolean }` | @@ -112,4 +112,4 @@ type EdgeInsets { bottom: Number, right: Number } -``` \ No newline at end of file +``` From b42cca90b04d8660d0a94e9444d7e4df9b7a2b91 Mon Sep 17 00:00:00 2001 From: Vince Yuan Date: Thu, 19 Jan 2017 00:58:55 +0800 Subject: [PATCH 0196/1148] Update doc to show how to add GoogleMaps support for iOS. (#950) --- docs/installation.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/installation.md b/docs/installation.md index a236fbda1..5f85b14db 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -22,10 +22,10 @@ react-native link 1. Setup your `Podfile` like the included [example/ios/Podfile](../example/ios/Podfile), replace all references to `AirMapExplorer` with your project name, and then run `pod install`. (If you do not need `GoogleMaps` support for iOS, then you can probably completely skip this step.) 1. Open your project in Xcode workspace -1. Drag the following folder into your project: - - `node_modules/react-native-maps/ios/AirMaps/` -1. If you need `GoogleMaps` support also drag this folder into your project: - - `node_modules/react-native-maps/ios/AirGoogleMaps/` +1. If you need `GoogleMaps` support also + - Drag this folder `node_modules/react-native-maps/ios/AirGoogleMaps/` into your project, and choose `Create groups` in the popup window. + - In `AppDelegate.m`, add `@import GoogleMaps;` before `@implementation AppDelegate`. In `- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions`, add `[GMSServices provideAPIKey:@"YOUR_GOOGLE_MAP_API_KEY"];` + - In your project's `Build Settings` > `Header Search Paths`, double click the value field. In the popup, add `$(SRCROOT)/../node_modules/react-native-maps/ios/AirMaps` and change `non-recursive` to `recursive`. (Dragging the folder `node_modules/react-native-maps/ios/AirMaps/` into your project introduces duplicate symbols. We should not do it.) ### Option 2: CocoaPods This is now considered the **old way** because it will only work if you **don't** have From 98440253977a12075f914720b2d756ac2c04974b Mon Sep 17 00:00:00 2001 From: Marton Bodonyi Date: Thu, 19 Jan 2017 03:59:17 +1100 Subject: [PATCH 0197/1148] Add Android SDK Build tools 23.03 to troubleshooting (#945) This adds Android SDK Build-tools 23.0.3 to the troubleshooting section for Android. This is required because react-native documentation (https://facebook.github.io/react-native/docs/getting-started.html) only specifies a requirement of Build-tools 23.0.1. The build error if you don't have 23.0.3 installed is ``` A problem occurred configuring project ':app'. > A problem occurred configuring project ':react-native-maps'. > Failed to notify project evaluation listener. > failed to find Build Tools revision 23.0.3 > failed to find Build Tools revision 23.0.3 ``` --- docs/installation.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/installation.md b/docs/installation.md index 5f85b14db..10a3dfa20 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -189,6 +189,7 @@ You have to link dependencies with rnpm and re-run the build: - Extras / Google Play services - Extras / Google Repository - Android 6.0 (API 23) / Google APIs Intel x86 Atom System Image Rev. 19 + - Android SDK Build-tools 23.0.3 1. Check manual installation steps if you didn't run "react-native link" 1. Go to [Google API Console](https://console.developers.google.com/flows/enableapi?apiid=maps_android_backend) and select your project, or create one. Then, once enabled, select `Go to credentials`. From c55092808aa0d159a44119299cdbb792a7517518 Mon Sep 17 00:00:00 2001 From: Marton Bodonyi Date: Thu, 19 Jan 2017 04:01:18 +1100 Subject: [PATCH 0198/1148] Update installation.md (#947) Added troubleshooting step for enabling Use Host GPU checkbox in AVD settings. It appears that Google Maps requires Open GL to be enabled and working on devices for it to draw the map. See https://github.com/airbnb/react-native-maps/issues/942 --- docs/installation.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/installation.md b/docs/installation.md index 10a3dfa20..d73c4011e 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -212,3 +212,5 @@ Enter the name of the API key and create it. gradlew clean cd .. ``` + +1. If you are using Android Virtual Devices (AVD), ensure that `Use Host GPU` is checked in the settings for your virtual device. From de43e5d0a5733188a2ea908ba8dadabd9410e71a Mon Sep 17 00:00:00 2001 From: jschloer Date: Mon, 23 Jan 2017 13:41:58 -0500 Subject: [PATCH 0199/1148] Sets the map value for the AirMapUrlTile so that it can be updated properly. --- ios/AirMaps/AIRMap.m | 1 + 1 file changed, 1 insertion(+) diff --git a/ios/AirMaps/AIRMap.m b/ios/AirMaps/AIRMap.m index 1126c3825..286be275a 100644 --- a/ios/AirMaps/AIRMap.m +++ b/ios/AirMaps/AIRMap.m @@ -104,6 +104,7 @@ - (void)insertReactSubview:(id)subview atIndex:(NSInteger)atIndex } else if ([subview isKindOfClass:[AIRMapCircle class]]) { [self addOverlay:(id)subview]; } else if ([subview isKindOfClass:[AIRMapUrlTile class]]) { + ((AIRMapUrlTile *)subview).map = self; [self addOverlay:(id)subview]; } [_reactSubviews insertObject:(UIView *)subview atIndex:(NSUInteger) atIndex]; From 9d52855f84f016bff16dc5e014de8697dcedc84d Mon Sep 17 00:00:00 2001 From: Lucas Bento Date: Tue, 31 Jan 2017 22:26:09 -0200 Subject: [PATCH 0200/1148] Fix typo on Android installation (#1004) --- docs/installation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/installation.md b/docs/installation.md index d73c4011e..195124e02 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -73,7 +73,7 @@ After your `Podfile` is setup properly, run `pod install`. } ``` - If you have a different play serivces than the one included in this library, use the following instead (switch 10.0.1 for the desired version): + If you have a different play services than the one included in this library, use the following instead (switch 10.0.1 for the desired version): ```groovy ... From eccf876d8717613692ef8ea55cbc713dcbe4aa3d Mon Sep 17 00:00:00 2001 From: alexbelyeu Date: Tue, 31 Jan 2017 19:26:24 -0500 Subject: [PATCH 0201/1148] Update installation.md (#989) The link to the instructions for having Google Play Services installed in your sim is now outdated and Genymotion recently provided easy steps to follow. --- docs/installation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/installation.md b/docs/installation.md index 195124e02..5a394322f 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -114,7 +114,7 @@ After your `Podfile` is setup properly, run `pod install`. Source: https://developers.google.com/maps/documentation/android-api/signup 1. Ensure that you have Google Play Services installed: - * For Genymotion you can follow [these instructions](http://stackoverflow.com/a/20137324/1424349). + * For Genymotion you can follow [these instructions](https://www.genymotion.com/help/desktop/faq/#google-play-services). * For a physical device you need to search on Google for 'Google Play Services'. There will be a link that takes you to the Play Store and from there you will see a button to update it (do not search within the Play Store). ## Troubleshooting From 571fbb53cc6d22f3ff946246d08382ce572990ed Mon Sep 17 00:00:00 2001 From: gilbox Date: Mon, 21 Nov 2016 14:55:36 -0800 Subject: [PATCH 0202/1148] [android] Create example for marker not updating bug --- example/App.js | 2 + example/examples/BugMarkerWontUpdate.js | 134 ++++++++++++++++++ example/examples/MyLocationMapMarker.js | 179 ++++++++++++++++++++++++ example/package.json | 1 + 4 files changed, 316 insertions(+) create mode 100644 example/examples/BugMarkerWontUpdate.js create mode 100644 example/examples/MyLocationMapMarker.js diff --git a/example/App.js b/example/App.js index 43c39580a..dadbea056 100644 --- a/example/App.js +++ b/example/App.js @@ -35,6 +35,7 @@ import MapStyle from './examples/MapStyle'; import LegalLabel from './examples/LegalLabel'; import SetNativePropsOverlays from './examples/SetNativePropsOverlays'; import CustomOverlay from './examples/CustomOverlay'; +import BugMarkerWontUpdate from './examples/BugMarkerWontUpdate'; const IOS = Platform.OS === 'ios'; const ANDROID = Platform.OS === 'android'; @@ -148,6 +149,7 @@ class App extends React.Component { [LegalLabel, 'Reposition the legal label', true], [SetNativePropsOverlays, 'Update native props', true], [CustomOverlay, 'Custom Overlay Component', true], + [BugMarkerWontUpdate, 'BUG: Marker Won\'t Update (Android)', true], ] // Filter out examples that are not yet supported for Google Maps on iOS. .filter(example => ANDROID || (IOS && (example[2] || !this.state.useGoogleMaps))) diff --git a/example/examples/BugMarkerWontUpdate.js b/example/examples/BugMarkerWontUpdate.js new file mode 100644 index 000000000..8bf62ffca --- /dev/null +++ b/example/examples/BugMarkerWontUpdate.js @@ -0,0 +1,134 @@ +import React from 'react'; +import { + StyleSheet, + View, + Text, + Dimensions, + TouchableOpacity, +} from 'react-native'; +import MapView from 'react-native-maps'; +import MyLocationMapMarker from './MyLocationMapMarker'; + +const { width, height } = Dimensions.get('window'); + +const ASPECT_RATIO = width / height; +const LATITUDE = 37.78825; +const LONGITUDE = -122.4324; +const LATITUDE_DELTA = 0.0922; +const LONGITUDE_DELTA = LATITUDE_DELTA * ASPECT_RATIO; + +class BugMarkerWontUpdate extends React.Component { + constructor(props) { + super(props); + + this.state = { + region: { + latitude: LATITUDE, + longitude: LONGITUDE, + latitudeDelta: LATITUDE_DELTA, + longitudeDelta: LONGITUDE_DELTA, + }, + coordinate: { + latitude: LATITUDE, + longitude: LONGITUDE, + }, + amount: 0, + enableHack: false, + }; + } + + increment() { + this.setState({ amount: this.state.amount + 10 }); + } + + decrement() { + this.setState({ amount: this.state.amount - 10 }); + } + + toggleHack() { + this.setState({ enableHack: !this.state.enableHack }); + } + + render() { + return ( + + + + + + this.toggleHack()} + style={[styles.bubble, styles.button, styles.hackButton]} + > + + {this.state.enableHack ? 'Disable Hack' : 'Enable Hack'} + + + + + this.decrement()} + style={[styles.bubble, styles.button]} + > + - + + this.increment()} + style={[styles.bubble, styles.button]} + > + + + + + + ); + } +} + +BugMarkerWontUpdate.propTypes = { + provider: MapView.ProviderPropType, +}; + +const styles = StyleSheet.create({ + container: { + ...StyleSheet.absoluteFillObject, + justifyContent: 'flex-end', + alignItems: 'center', + }, + map: { + ...StyleSheet.absoluteFillObject, + }, + bubble: { + backgroundColor: 'rgba(255,255,255,0.7)', + paddingHorizontal: 18, + paddingVertical: 12, + borderRadius: 20, + }, + latlng: { + width: 200, + alignItems: 'stretch', + }, + button: { + width: 80, + paddingHorizontal: 12, + alignItems: 'center', + marginHorizontal: 10, + }, + hackButton: { + width: 200, + }, + buttonContainer: { + flexDirection: 'row', + marginVertical: 20, + backgroundColor: 'transparent', + }, +}); + +module.exports = BugMarkerWontUpdate; diff --git a/example/examples/MyLocationMapMarker.js b/example/examples/MyLocationMapMarker.js new file mode 100644 index 000000000..fff3f2b37 --- /dev/null +++ b/example/examples/MyLocationMapMarker.js @@ -0,0 +1,179 @@ +import React, { PropTypes } from 'react'; +import { + StyleSheet, + Text, + View, + PermissionsAndroid, + Platform, +} from 'react-native'; +import MapView from 'react-native-maps'; +import isEqual from 'lodash/isEqual'; + +const GEOLOCATION_OPTIONS = { enableHighAccuracy: true, timeout: 20000, maximumAge: 1000 }; +const ANCHOR = { x: 0.5, y: 0.5 }; + +const colorOfmyLocationMapMarker = 'blue'; + +const propTypes = { + ...MapView.Marker.propTypes, + // override this prop to make it optional + coordinate: PropTypes.shape({ + latitude: PropTypes.number.isRequired, + longitude: PropTypes.number.isRequired, + }), + children: PropTypes.node, + geolocationOptions: PropTypes.shape({ + enableHighAccuracy: PropTypes.bool, + timeout: PropTypes.number, + maximumAge: PropTypes.number, + }), + heading: PropTypes.number, + enableHack: PropTypes.bool, +}; + +const defaultProps = { + enableHack: false, + geolocationOptions: GEOLOCATION_OPTIONS, +}; + +export default class MyLocationMapMarker extends React.PureComponent { + constructor(props) { + super(props); + this.mounted = false; + this.state = { + myPosition: null, + }; + } + componentDidMount() { + this.mounted = true; + // If you supply a coordinate prop, we won't try to track location automatically + if (this.props.coordinate) return; + + if (Platform.OS === 'android') { + PermissionsAndroid.requestPermission(PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION) + .then(granted => { + if (granted && this.mounted) this.watchLocation(); + }); + } else { + this.watchLocation(); + } + } + watchLocation() { + // eslint-disable-next-line no-undef + this.watchID = navigator.geolocation.watchPosition((position) => { + const myLastPosition = this.state.myPosition; + const myPosition = position.coords; + if (!isEqual(myPosition, myLastPosition)) { + this.setState({ myPosition }); + } + }, null, this.props.geolocationOptions); + } + componentWillUnmount() { + this.mounted = false; + // eslint-disable-next-line no-undef + if (this.watchID) navigator.geolocation.clearWatch(this.watchID); + } + render() { + let { heading, coordinate } = this.props; + if (!coordinate) { + const { myPosition } = this.state; + if (!myPosition) return null; + coordinate = myPosition; + heading = myPosition.heading; + } + + const rotate = (typeof heading === 'number' && heading >= 0) ? `${heading}deg` : null; + + return ( + + + + {rotate && + + + + } + + + {this.props.enableHack && rotate} + + + + {this.props.children} + + ); + } +} + +const SIZE = 35; +const HALO_RADIUS = 6; +const ARROW_SIZE = 7; +const ARROW_DISTANCE = 6; +const HALO_SIZE = SIZE + HALO_RADIUS; +const HEADING_BOX_SIZE = HALO_SIZE + ARROW_SIZE + ARROW_DISTANCE; + +const styles = StyleSheet.create({ + mapMarker: { + zIndex: 1000, + }, + // The container is necessary to protect the markerHalo shadow from clipping + container: { + width: HEADING_BOX_SIZE, + height: HEADING_BOX_SIZE, + }, + heading: { + position: 'absolute', + top: 0, + left: 0, + width: HEADING_BOX_SIZE, + height: HEADING_BOX_SIZE, + alignItems: 'center', + }, + headingPointer: { + width: 0, + height: 0, + backgroundColor: 'transparent', + borderStyle: 'solid', + borderTopWidth: 0, + borderRightWidth: ARROW_SIZE * 0.75, + borderBottomWidth: ARROW_SIZE, + borderLeftWidth: ARROW_SIZE * 0.75, + borderTopColor: 'transparent', + borderRightColor: 'transparent', + borderBottomColor: colorOfmyLocationMapMarker, + borderLeftColor: 'transparent', + }, + markerHalo: { + position: 'absolute', + backgroundColor: 'white', + top: 0, + left: 0, + width: HALO_SIZE, + height: HALO_SIZE, + borderRadius: Math.ceil(HALO_SIZE / 2), + margin: (HEADING_BOX_SIZE - HALO_SIZE) / 2, + shadowColor: 'black', + shadowOpacity: 0.25, + shadowRadius: 2, + shadowOffset: { + height: 0, + width: 0, + }, + }, + marker: { + justifyContent: 'center', + backgroundColor: colorOfmyLocationMapMarker, + width: SIZE, + height: SIZE, + borderRadius: Math.ceil(SIZE / 2), + margin: (HEADING_BOX_SIZE - SIZE) / 2, + }, +}); + +MyLocationMapMarker.propTypes = propTypes; +MyLocationMapMarker.defaultProps = defaultProps; diff --git a/example/package.json b/example/package.json index eca9884a4..378bd5578 100644 --- a/example/package.json +++ b/example/package.json @@ -9,6 +9,7 @@ "dev": "concurrently 'npm run watch' 'npm run packager'" }, "dependencies": { + "lodash": "^4.17.2", "react": "~15.4.1", "react-native": "^0.40.0", "react-native-maps": "file:../" From 2ff4f8c9fbdc1f65fff318896f02f24178e7e748 Mon Sep 17 00:00:00 2001 From: Spike Brehm Date: Wed, 1 Feb 2017 16:14:57 -0800 Subject: [PATCH 0203/1148] Fix copyright in README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 05ed75170..8322d0fcf 100644 --- a/README.md +++ b/README.md @@ -476,7 +476,7 @@ Good: License -------- - Copyright (c) 2015 Leland Richardson + Copyright (c) 2015 Airbnb Licensed under the The MIT License (MIT) (the "License"); you may not use this file except in compliance with the License. From b5e49c5dd5516a07bff1e8ad10bf8aabeb7f1514 Mon Sep 17 00:00:00 2001 From: Spike Brehm Date: Wed, 1 Feb 2017 16:28:19 -0800 Subject: [PATCH 0204/1148] Clean up MapView#_onLayout a bit. DRY it up and simplify. --- components/MapView.js | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/components/MapView.js b/components/MapView.js index 0195e694c..16755d68c 100644 --- a/components/MapView.js +++ b/components/MapView.js @@ -424,19 +424,15 @@ class MapView extends React.Component { } _onLayout(e) { - const { region, initialRegion, onLayout } = this.props; - const { isReady } = this.state; - const { layout } = e.nativeEvent; - if (!layout.width || !layout.height) return; - if (region && isReady && !this.__layoutCalled) { - this.__layoutCalled = true; - this.map.setNativeProps({ region }); - } else if (initialRegion && isReady && !this.__layoutCalled) { - this.__layoutCalled = true; - this.map.setNativeProps({ region: initialRegion }); + if (this.state.isReady && !this.__layoutCalled) { + const region = this.props.region || this.props.initialRegion; + if (region) { + this.__layoutCalled = true; + this.map.setNativeProps({ region }); + } } - if (onLayout) { - onLayout(e); + if (this.props.onLayout) { + this.props.onLayout(e); } } From 91bd30e32f7c882b5b24c331694e318eaebbf082 Mon Sep 17 00:00:00 2001 From: Spike Brehm Date: Wed, 1 Feb 2017 16:32:05 -0800 Subject: [PATCH 0205/1148] Add on layout.width/height check --- components/MapView.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/components/MapView.js b/components/MapView.js index 16755d68c..a4d316a72 100644 --- a/components/MapView.js +++ b/components/MapView.js @@ -424,6 +424,8 @@ class MapView extends React.Component { } _onLayout(e) { + const { layout } = e.nativeEvent; + if (!layout.width || !layout.height) return; if (this.state.isReady && !this.__layoutCalled) { const region = this.props.region || this.props.initialRegion; if (region) { From 80e8b77551224f1c8b17479a56f5a063bde79cbe Mon Sep 17 00:00:00 2001 From: Spike Brehm Date: Wed, 1 Feb 2017 17:58:08 -0800 Subject: [PATCH 0206/1148] Create `update-version` script to more easily update version Similar to `npm version`, but updates the version number in all the files we need to. Usage: ./scripts/update-version.js [major|minor|patch] It will: * Get current npm version. * Determine what type of version bump: major, minor, patch * Update the files: * package.json * android/gradle.properties * react-native-maps.podspec * react-native-google-maps.podspec * Make Git commit. * Create Git tag. --- package.json | 5 +- scripts/update-version.js | 105 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 109 insertions(+), 1 deletion(-) create mode 100755 scripts/update-version.js diff --git a/package.json b/package.json index 016a69c97..77f519ffd 100644 --- a/package.json +++ b/package.json @@ -27,12 +27,15 @@ }, "devDependencies": { "babel-eslint": "^6.1.2", + "commander": "^2.9.0", + "dedent": "^0.7.0", "eslint": "^3.3.1", "eslint-config-airbnb": "^10.0.1", "eslint-plugin-import": "^1.14.0", "eslint-plugin-jsx-a11y": "^2.1.0", "eslint-plugin-prefer-object-spread": "^1.1.0", - "eslint-plugin-react": "^6.1.2" + "eslint-plugin-react": "^6.1.2", + "semver": "^5.3.0" }, "rnpm": { "android": { diff --git a/scripts/update-version.js b/scripts/update-version.js new file mode 100755 index 000000000..8e949b08f --- /dev/null +++ b/scripts/update-version.js @@ -0,0 +1,105 @@ +#!/usr/bin/env node + +/* + +* Get current npm version. +* Determine what type of version bump: major, minor, patch +* Update the files: + * package.json + * android/gradle.properties + * react-native-maps.podspec + * react-native-google-maps.podspec +* Make Git commit. +* Create Git tag. + +*/ + +// TODO: update eslint-plugin-import so we can configure +// `import/no-extraneous-dependencies` to allow devDependencies in `scripts/`. + +const { exec } = require('child_process'); +// eslint-disable-next-line import/no-extraneous-dependencies +const commander = require('commander'); +// eslint-disable-next-line import/no-extraneous-dependencies +const dedent = require('dedent'); +// eslint-disable-next-line import/no-extraneous-dependencies +const semver = require('semver'); +const pkg = require('../package.json'); + +const versionTypes = ['major', 'minor', 'patch']; +const filesToUpdate = [ + 'package.json', + 'android/gradle.properties', + 'react-native-maps.podspec', + 'react-native-google-maps.podspec', +]; + +commander + .version(pkg.version) + .arguments('') + .action(versionType => { + if (!versionTypes.includes(versionType)) { + die(dedent`Version type "${versionType}" not recognized. + Supported values: ${versionTypes.map(v => `"${v}"`).join(', ')}.`); + } + bumpVersion(pkg.version, versionType).catch(err => { + process.stderr.write(`${err.stack}\n`); + }); + }); + +commander.parse(process.argv); + +function die(message) { + process.stderr.write(message); + process.exit(1); +} + +function doExec(cmdString) { + return new Promise((resolve, reject) => { + exec(cmdString, (err, stdout) => { + if (err) { + reject(err); + return; + } + resolve(stdout); + }); + }); +} + +function bumpVersion(currentVersion, versionType) { + const nextVersion = semver.inc(currentVersion, versionType); + process.stdout.write(`Updating version from ${currentVersion} to ${nextVersion}...\n`); + + return Promise.resolve() + .then(() => updateFiles(currentVersion, nextVersion)) + .then(() => createCommit(nextVersion)) + .then(() => createTag(nextVersion)) + ; +} + +function updateFiles(currentVersion, nextVersion) { + return Promise.all(filesToUpdate.map(relativePath => + updateVersionInFile(currentVersion, nextVersion, relativePath) + )); +} + +function createCommit(nextVersion) { + return doExec(`git commit -am ${nextVersion}`); +} + +function createTag(nextVersion) { + return doExec(`git tag v${nextVersion}`); +} + +function updateVersionInFile(currentVersion, nextVersion, relativePath) { + process.stdout.write(`-> ${relativePath}\n`); + return doExec(`sed -i '' 's/${ + escapeDots(currentVersion) + }/${ + escapeDots(nextVersion) + }/g' ./${relativePath}`); +} + +function escapeDots(version) { + return version.replace(/\./g, '\\.'); +} From bec405d55bdc1ae7bbf10e56c769e089d1a8f3e5 Mon Sep 17 00:00:00 2001 From: Martin Ledgard Date: Thu, 2 Feb 2017 20:43:51 +0000 Subject: [PATCH 0207/1148] update animateToCoordinate arguments (#1018) --- docs/mapview.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/mapview.md b/docs/mapview.md index bfab08e7d..ed8ecb71d 100644 --- a/docs/mapview.md +++ b/docs/mapview.md @@ -55,7 +55,7 @@ | Method Name | Arguments | Notes |---|---|---| | `animateToRegion` | `region: Region`, `duration: Number` | -| `animateToCoordinate` | `region: Coordinate`, `duration: Number` | +| `animateToCoordinate` | `coordinate: LatLng`, `duration: Number` | | `fitToElements` | `animated: Boolean` | | `fitToSuppliedMarkers` | `markerIDs: String[]`, `animated: Boolean` | If you need to use this in `ComponentDidMount`, make sure you put it in a timeout or it will cause performance problems. | `fitToCoordinates` | `coordinates: Array, options: { edgePadding: EdgePadding, animated: Boolean }` | From 88a7e0320862e076e81a73e96c73f44f6b529493 Mon Sep 17 00:00:00 2001 From: Cesar alonso Date: Thu, 2 Feb 2017 16:52:42 -0600 Subject: [PATCH 0208/1148] Add showsIndoorLevelPicker options for MapView --- .../java/com/airbnb/android/react/maps/AirMapManager.java | 7 ++++++- components/MapView.js | 8 ++++++++ docs/mapview.md | 1 + 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java b/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java index 75ed5777f..2f11319a5 100644 --- a/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java +++ b/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java @@ -93,7 +93,7 @@ public void setMapType(AirMapView view, @Nullable String mapType) { int typeId = MAP_TYPES.get(mapType); view.map.setMapType(typeId); } - + @ReactProp(name = "customMapStyleString") public void setMapStyle(AirMapView view, @Nullable String customMapStyleString) { view.map.setMapStyle(new MapStyleOptions(customMapStyleString)); @@ -135,6 +135,11 @@ public void setShowIndoors(AirMapView view, boolean showIndoors) { view.map.setIndoorEnabled(showIndoors); } + @ReactProp(name = "showsIndoorLevelPicker", defaultBoolean = false) + public void setShowsIndoorLevelPicker(AirMapView view, boolean showsIndoorLevelPicker) { + view.map.getUiSettings().setIndoorLevelPickerEnabled(showsIndoorLevelPicker); + } + @ReactProp(name = "showsCompass", defaultBoolean = false) public void setShowsCompass(AirMapView view, boolean showsCompass) { view.map.getUiSettings().setCompassEnabled(showsCompass); diff --git a/components/MapView.js b/components/MapView.js index 0195e694c..b857fcb1b 100644 --- a/components/MapView.js +++ b/components/MapView.js @@ -217,6 +217,14 @@ const propTypes = { */ showsIndoors: PropTypes.bool, + /** + * A Boolean indicating whether indoor level picker should be enabled. + * Default value is `false` + * + * @platform android + */ + showsIndoorLevelPicker: PropTypes.bool, + /** * The map type to be displayed. * diff --git a/docs/mapview.md b/docs/mapview.md index bfab08e7d..caa89403e 100644 --- a/docs/mapview.md +++ b/docs/mapview.md @@ -18,6 +18,7 @@ | `showsBuildings` | `Boolean` | `true` | A Boolean indicating whether the map displays extruded building information. | `showsTraffic` | `Boolean` | `true` | A Boolean value indicating whether the map displays traffic information. | `showsIndoors` | `Boolean` | `true` | A Boolean indicating whether indoor maps should be enabled. +| `showsIndoorLevelPicker` | `Boolean` | `false` | A Boolean indicating whether indoor level picker should be enabled. | `zoomEnabled` | `Boolean` | `true` | If `false` the user won't be able to pinch/zoom the map. | `rotateEnabled` | `Boolean` | `true` | If `false` the user won't be able to pinch/rotate the map. | `scrollEnabled` | `Boolean` | `true` | If `false` the user won't be able to change the map region being displayed. From 5c80a5c3998087e6d91535cae3268c597cf24f59 Mon Sep 17 00:00:00 2001 From: Gerardo Pacheco Date: Sun, 5 Feb 2017 20:08:54 +0100 Subject: [PATCH 0209/1148] [iOS] Added onPress support for Polygons on Google Maps --- components/MapPolygon.js | 6 ++++++ example/examples/EventListener.js | 1 + .../AirMapsExplorer.xcodeproj/project.pbxproj | 6 ++++++ ios/AirGoogleMaps/AIRGMSPolygon.h | 16 ++++++++++++++++ ios/AirGoogleMaps/AIRGMSPolygon.m | 12 ++++++++++++ ios/AirGoogleMaps/AIRGoogleMap.h | 1 + ios/AirGoogleMaps/AIRGoogleMap.m | 10 ++++++++++ ios/AirGoogleMaps/AIRGoogleMapManager.m | 5 +++++ ios/AirGoogleMaps/AIRGoogleMapPolygon.h | 8 +++++++- ios/AirGoogleMaps/AIRGoogleMapPolygon.m | 13 ++++++++++++- ios/AirGoogleMaps/AIRGoogleMapPolygonManager.m | 3 +++ 11 files changed, 79 insertions(+), 2 deletions(-) create mode 100644 ios/AirGoogleMaps/AIRGMSPolygon.h create mode 100644 ios/AirGoogleMaps/AIRGMSPolygon.m diff --git a/components/MapPolygon.js b/components/MapPolygon.js index 7baea77db..6901979db 100644 --- a/components/MapPolygon.js +++ b/components/MapPolygon.js @@ -37,6 +37,12 @@ const propTypes = { */ onPress: PropTypes.func, + /** + * Boolean to allow a polygon to be tappable and use the + * onPress function + */ + tappable: PropTypes.bool, + /** * The stroke width to use for the path. */ diff --git a/example/examples/EventListener.js b/example/examples/EventListener.js index 0876c621d..005894a0d 100644 --- a/example/examples/EventListener.js +++ b/example/examples/EventListener.js @@ -130,6 +130,7 @@ class EventListener extends React.Component { +#import "UIView+React.h" + +@class AIRGoogleMapPolygon; + +@interface AIRGMSPolygon : GMSPolygon +@property (nonatomic, strong) NSString *identifier; +@property (nonatomic, copy) RCTBubblingEventBlock onPress; +@end diff --git a/ios/AirGoogleMaps/AIRGMSPolygon.m b/ios/AirGoogleMaps/AIRGMSPolygon.m new file mode 100644 index 000000000..05de0b029 --- /dev/null +++ b/ios/AirGoogleMaps/AIRGMSPolygon.m @@ -0,0 +1,12 @@ +// +// AIRGMSPolygon.m +// AirMaps +// +// Created by Gerardo Pacheco 02/05/2017. +// + +#import "AIRGMSPolygon.h" + +@implementation AIRGMSPolygon + +@end diff --git a/ios/AirGoogleMaps/AIRGoogleMap.h b/ios/AirGoogleMaps/AIRGoogleMap.h index 925aa4746..1dcc830ec 100644 --- a/ios/AirGoogleMaps/AIRGoogleMap.h +++ b/ios/AirGoogleMaps/AIRGoogleMap.h @@ -40,6 +40,7 @@ @property (nonatomic, assign) BOOL showsUserLocation; - (BOOL)didTapMarker:(GMSMarker *)marker; +- (void)didTapPolygon:(GMSPolygon *)polygon; - (void)didTapAtCoordinate:(CLLocationCoordinate2D)coordinate; - (void)didLongPressAtCoordinate:(CLLocationCoordinate2D)coordinate; - (void)didChangeCameraPosition:(GMSCameraPosition *)position; diff --git a/ios/AirGoogleMaps/AIRGoogleMap.m b/ios/AirGoogleMaps/AIRGoogleMap.m index e6d028c31..1d0ecd252 100644 --- a/ios/AirGoogleMaps/AIRGoogleMap.m +++ b/ios/AirGoogleMaps/AIRGoogleMap.m @@ -170,6 +170,16 @@ - (BOOL)didTapMarker:(GMSMarker *)marker { return NO; } +- (void)didTapPolygon:(GMSOverlay *)polygon { + AIRGMSPolygon *airPolygon = (AIRGMSPolygon *)polygon; + + id event = @{@"action": @"polygon-press", + @"id": airPolygon.identifier ?: @"unknown", + }; + + if (airPolygon.onPress) airPolygon.onPress(event); +} + - (void)didTapAtCoordinate:(CLLocationCoordinate2D)coordinate { if (!self.onPress) return; self.onPress([self eventFromCoordinate:coordinate]); diff --git a/ios/AirGoogleMaps/AIRGoogleMapManager.m b/ios/AirGoogleMaps/AIRGoogleMapManager.m index e306de1d8..b903d6b3a 100644 --- a/ios/AirGoogleMaps/AIRGoogleMapManager.m +++ b/ios/AirGoogleMaps/AIRGoogleMapManager.m @@ -202,6 +202,11 @@ - (BOOL)mapView:(GMSMapView *)mapView didTapMarker:(GMSMarker *)marker { return [googleMapView didTapMarker:marker]; } +- (void)mapView:(GMSMapView *)mapView didTapOverlay:(GMSPolygon *)polygon { + AIRGoogleMap *googleMapView = (AIRGoogleMap *)mapView; + [googleMapView didTapPolygon:polygon]; +} + - (void)mapView:(GMSMapView *)mapView didTapAtCoordinate:(CLLocationCoordinate2D)coordinate { AIRGoogleMap *googleMapView = (AIRGoogleMap *)mapView; [googleMapView didTapAtCoordinate:coordinate]; diff --git a/ios/AirGoogleMaps/AIRGoogleMapPolygon.h b/ios/AirGoogleMaps/AIRGoogleMapPolygon.h index 12a207128..e7719ebee 100644 --- a/ios/AirGoogleMaps/AIRGoogleMapPolygon.h +++ b/ios/AirGoogleMaps/AIRGoogleMapPolygon.h @@ -5,18 +5,24 @@ // #import +#import +#import "AIRGMSPolygon.h" #import "AIRMapCoordinate.h" @interface AIRGoogleMapPolygon : UIView -@property (nonatomic, strong) GMSPolygon *polygon; +@property (nonatomic, weak) RCTBridge *bridge; +@property (nonatomic, strong) NSString *identifier; +@property (nonatomic, strong) AIRGMSPolygon *polygon; @property (nonatomic, strong) NSArray *coordinates; @property (nonatomic, strong) NSArray *> *holes; +@property (nonatomic, copy) RCTBubblingEventBlock onPress; @property (nonatomic, assign) UIColor *fillColor; @property (nonatomic, assign) double strokeWidth; @property (nonatomic, assign) UIColor *strokeColor; @property (nonatomic, assign) BOOL geodesic; @property (nonatomic, assign) int zIndex; +@property (nonatomic, assign) BOOL tappable; @end diff --git a/ios/AirGoogleMaps/AIRGoogleMapPolygon.m b/ios/AirGoogleMaps/AIRGoogleMapPolygon.m index ea31b5008..bbd5d99c9 100644 --- a/ios/AirGoogleMaps/AIRGoogleMapPolygon.m +++ b/ios/AirGoogleMaps/AIRGoogleMapPolygon.m @@ -5,6 +5,7 @@ // #import "AIRGoogleMapPolygon.h" +#import "AIRGMSPolygon.h" #import @implementation AIRGoogleMapPolygon @@ -12,7 +13,7 @@ @implementation AIRGoogleMapPolygon - (instancetype)init { if (self = [super init]) { - _polygon = [[GMSPolygon alloc] init]; + _polygon = [[AIRGMSPolygon alloc] init]; } return self; @@ -82,4 +83,14 @@ -(void)setZIndex:(int)zIndex _polygon.zIndex = zIndex; } +-(void)setTappable:(BOOL)tappable +{ + _tappable = tappable; + _polygon.tappable = tappable; +} + +- (void)setOnPress:(RCTBubblingEventBlock)onPress { + _polygon.onPress = onPress; +} + @end diff --git a/ios/AirGoogleMaps/AIRGoogleMapPolygonManager.m b/ios/AirGoogleMaps/AIRGoogleMapPolygonManager.m index 5c7ce2a66..a946d3b7a 100644 --- a/ios/AirGoogleMaps/AIRGoogleMapPolygonManager.m +++ b/ios/AirGoogleMaps/AIRGoogleMapPolygonManager.m @@ -25,6 +25,7 @@ @implementation AIRGoogleMapPolygonManager - (UIView *)view { AIRGoogleMapPolygon *polygon = [AIRGoogleMapPolygon new]; + polygon.bridge = self.bridge; return polygon; } @@ -35,5 +36,7 @@ - (UIView *)view RCT_EXPORT_VIEW_PROPERTY(strokeColor, UIColor) RCT_EXPORT_VIEW_PROPERTY(geodesic, BOOL) RCT_EXPORT_VIEW_PROPERTY(zIndex, int) +RCT_EXPORT_VIEW_PROPERTY(tappable, BOOL) +RCT_EXPORT_VIEW_PROPERTY(onPress, RCTBubblingEventBlock) @end From ada2961f2b5af89d9255200cbb88233f80db34e3 Mon Sep 17 00:00:00 2001 From: Spike Brehm Date: Mon, 6 Feb 2017 17:25:11 -0800 Subject: [PATCH 0210/1148] Integrate better with `npm version` --- package.json | 3 +- scripts/update-version.js | 101 +++++++++++++------------------------- 2 files changed, 36 insertions(+), 68 deletions(-) diff --git a/package.json b/package.json index 77f519ffd..0e788ec48 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,8 @@ "version": "0.13.0", "scripts": { "start": "react-native start", - "lint": "eslint ." + "lint": "eslint .", + "preversion": "./scripts/update-version.js" }, "repository": { "type": "git", diff --git a/scripts/update-version.js b/scripts/update-version.js index 8e949b08f..f8f840ea7 100755 --- a/scripts/update-version.js +++ b/scripts/update-version.js @@ -1,59 +1,25 @@ #!/usr/bin/env node -/* - -* Get current npm version. -* Determine what type of version bump: major, minor, patch -* Update the files: - * package.json - * android/gradle.properties - * react-native-maps.podspec - * react-native-google-maps.podspec -* Make Git commit. -* Create Git tag. - +/** + * Script that runs as part of `npm version`. It updates any files that have a + * reference to the current package version: + * + * - android/gradle.properties + * - react-native-maps.podspec + * - react-native-google-maps.podspec + * + * And `git add`s them. */ -// TODO: update eslint-plugin-import so we can configure -// `import/no-extraneous-dependencies` to allow devDependencies in `scripts/`. - const { exec } = require('child_process'); -// eslint-disable-next-line import/no-extraneous-dependencies -const commander = require('commander'); -// eslint-disable-next-line import/no-extraneous-dependencies -const dedent = require('dedent'); -// eslint-disable-next-line import/no-extraneous-dependencies -const semver = require('semver'); const pkg = require('../package.json'); -const versionTypes = ['major', 'minor', 'patch']; const filesToUpdate = [ - 'package.json', 'android/gradle.properties', 'react-native-maps.podspec', 'react-native-google-maps.podspec', ]; -commander - .version(pkg.version) - .arguments('') - .action(versionType => { - if (!versionTypes.includes(versionType)) { - die(dedent`Version type "${versionType}" not recognized. - Supported values: ${versionTypes.map(v => `"${v}"`).join(', ')}.`); - } - bumpVersion(pkg.version, versionType).catch(err => { - process.stderr.write(`${err.stack}\n`); - }); - }); - -commander.parse(process.argv); - -function die(message) { - process.stderr.write(message); - process.exit(1); -} - function doExec(cmdString) { return new Promise((resolve, reject) => { exec(cmdString, (err, stdout) => { @@ -66,40 +32,41 @@ function doExec(cmdString) { }); } -function bumpVersion(currentVersion, versionType) { - const nextVersion = semver.inc(currentVersion, versionType); - process.stdout.write(`Updating version from ${currentVersion} to ${nextVersion}...\n`); +function updateVersionInFile(currentVersion, nextVersion, relativePath) { + process.stdout.write(`• ${relativePath}\n`); + return doExec(`sed -i '' 's/${ + escapeDots(currentVersion) + }/${ + escapeDots(nextVersion) + }/g' ./${relativePath}`); +} + +function escapeDots(version) { + return version.replace(/\./g, '\\.'); +} - return Promise.resolve() +function run() { + const currentVersion = pkg.version; + const nextVersion = process.env.npm_package_version; + + Promise.resolve() .then(() => updateFiles(currentVersion, nextVersion)) - .then(() => createCommit(nextVersion)) - .then(() => createTag(nextVersion)) - ; + .then(() => gitAdd()); } +// Tasks + function updateFiles(currentVersion, nextVersion) { + process.stdout.write(`Updating ${currentVersion} ➞ ${nextVersion}:\n`); return Promise.all(filesToUpdate.map(relativePath => updateVersionInFile(currentVersion, nextVersion, relativePath) )); } -function createCommit(nextVersion) { - return doExec(`git commit -am ${nextVersion}`); +function gitAdd() { + return doExec(`git add ${filesToUpdate.join(' ')}`); } -function createTag(nextVersion) { - return doExec(`git tag v${nextVersion}`); -} +// Do it. -function updateVersionInFile(currentVersion, nextVersion, relativePath) { - process.stdout.write(`-> ${relativePath}\n`); - return doExec(`sed -i '' 's/${ - escapeDots(currentVersion) - }/${ - escapeDots(nextVersion) - }/g' ./${relativePath}`); -} - -function escapeDots(version) { - return version.replace(/\./g, '\\.'); -} +run(); From fce2e66ad8b31edae3fbb0a726d5e4886012699d Mon Sep 17 00:00:00 2001 From: Spike Brehm Date: Mon, 6 Feb 2017 18:24:22 -0800 Subject: [PATCH 0211/1148] Remove unused dependencies --- package.json | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/package.json b/package.json index 0e788ec48..5741fe8bd 100644 --- a/package.json +++ b/package.json @@ -28,15 +28,12 @@ }, "devDependencies": { "babel-eslint": "^6.1.2", - "commander": "^2.9.0", - "dedent": "^0.7.0", "eslint": "^3.3.1", "eslint-config-airbnb": "^10.0.1", "eslint-plugin-import": "^1.14.0", "eslint-plugin-jsx-a11y": "^2.1.0", "eslint-plugin-prefer-object-spread": "^1.1.0", - "eslint-plugin-react": "^6.1.2", - "semver": "^5.3.0" + "eslint-plugin-react": "^6.1.2" }, "rnpm": { "android": { From 1c50e7fceadb9863979b9ec90b4d93d50814a428 Mon Sep 17 00:00:00 2001 From: "Rachel P.Y. Liao" Date: Mon, 20 Feb 2017 17:59:54 +0800 Subject: [PATCH 0212/1148] add customized user location annotation title --- components/MapView.js | 9 +++++++++ ios/AirMaps/AIRMap.h | 1 + ios/AirMaps/AIRMapManager.m | 8 ++++++++ 3 files changed, 18 insertions(+) diff --git a/components/MapView.js b/components/MapView.js index a4d316a72..4f93db019 100644 --- a/components/MapView.js +++ b/components/MapView.js @@ -86,6 +86,15 @@ const propTypes = { */ showsUserLocation: PropTypes.bool, + /** + * The title of the annotation for current user location. This only works if + * `showsUserLocation` is true. + * There is a default value `My Location` set by MapView. + * + * @platform ios + */ + userLocationAnnotationTitle: PropTypes.string, + /** * If `false` hide the button to move map to the current user's location. * Default value is `true`. diff --git a/ios/AirMaps/AIRMap.h b/ios/AirMaps/AIRMap.h index fd4ed0f25..5c9695466 100644 --- a/ios/AirMaps/AIRMap.h +++ b/ios/AirMaps/AIRMap.h @@ -24,6 +24,7 @@ extern const CGFloat AIRMapZoomBoundBuffer; @property (nonatomic, strong) UIImageView *cacheImageView; @property (nonatomic, strong) UIView *loadingView; +@property (nonatomic, copy) NSString *userLocationAnnotationTitle; @property (nonatomic, assign) BOOL followUserLocation; @property (nonatomic, assign) BOOL hasStartedRendering; @property (nonatomic, assign) BOOL cacheEnabled; diff --git a/ios/AirMaps/AIRMapManager.m b/ios/AirMaps/AIRMapManager.m index 91a7f3ef9..3a1e6e947 100644 --- a/ios/AirMaps/AIRMapManager.m +++ b/ios/AirMaps/AIRMapManager.m @@ -65,6 +65,7 @@ - (UIView *)view } RCT_EXPORT_VIEW_PROPERTY(showsUserLocation, BOOL) +RCT_EXPORT_VIEW_PROPERTY(userLocationAnnotationTitle, NSString) RCT_EXPORT_VIEW_PROPERTY(followsUserLocation, BOOL) RCT_EXPORT_VIEW_PROPERTY(showsPointsOfInterest, BOOL) RCT_EXPORT_VIEW_PROPERTY(showsBuildings, BOOL) @@ -491,7 +492,10 @@ - (void)mapView:(AIRMap *)mapView didSelectAnnotationView:(MKAnnotationView *)vi { if ([view.annotation isKindOfClass:[AIRMapMarker class]]) { [(AIRMapMarker *)view.annotation showCalloutView]; + } else if ([view.annotation isKindOfClass:[MKUserLocation class]] && mapView.userLocationAnnotationTitle != nil && view.annotation.title != mapView.userLocationAnnotationTitle) { + [(MKUserLocation*)view.annotation setTitle: mapView.userLocationAnnotationTitle]; } + } - (void)mapView:(AIRMap *)mapView didDeselectAnnotationView:(MKAnnotationView *)view { @@ -503,6 +507,10 @@ - (void)mapView:(AIRMap *)mapView didDeselectAnnotationView:(MKAnnotationView *) - (MKAnnotationView *)mapView:(__unused AIRMap *)mapView viewForAnnotation:(AIRMapMarker *)marker { if (![marker isKindOfClass:[AIRMapMarker class]]) { + if ([marker isKindOfClass:[MKUserLocation class]] && mapView.userLocationAnnotationTitle != nil) { + [(MKUserLocation*)marker setTitle: mapView.userLocationAnnotationTitle]; + return nil; + } return nil; } From 01564bd051bcebb86464c3afba7df012b7f2e687 Mon Sep 17 00:00:00 2001 From: "Rachel P.Y. Liao" Date: Mon, 20 Feb 2017 18:19:00 +0800 Subject: [PATCH 0213/1148] Update MapView doc --- docs/mapview.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/mapview.md b/docs/mapview.md index ed8ecb71d..53a5dcaae 100644 --- a/docs/mapview.md +++ b/docs/mapview.md @@ -10,6 +10,7 @@ | `liteMode` | `Boolean` | `false` | Enable lite mode. **Note**: Android only. | `mapType` | `String` | `"standard"` | The map type to be displayed.

- standard: standard road map (default)
- satellite: satellite view
- hybrid: satellite view with roads and points of interest overlayed
- terrain: (Android only) topographic view | `showsUserLocation` | `Boolean` | `false` | If `true` the app will ask for the user's location. **NOTE**: You need to add `NSLocationWhenInUseUsageDescription` key in Info.plist to enable geolocation, otherwise it is going to *fail silently*! +| `userLocationAnnotationTitle` | `String` | | The title of the annotation for current user location. This only works if `showsUserLocation` is true. There is a default value `My Location` set by MapView. **Note**: iOS only. | `followsUserLocation` | `Boolean` | `false` | If `true` the map will focus on the user's location. This only works if `showsUserLocation` is true and the user has shared their location. **Note**: iOS only. | `showsMyLocationButton` | `Boolean` | `true` | `Android only` If `false` hide the button to move map to the current user's location. | `showsPointsOfInterest` | `Boolean` | `true` | If `false` points of interest won't be displayed on the map. From bc85512af7f3424cf028b3279f2dc03f93c729a6 Mon Sep 17 00:00:00 2001 From: Yonah Forst Date: Fri, 3 Mar 2017 17:31:10 +0100 Subject: [PATCH 0214/1148] addresses #436 --- ios/AirMaps/AIRMapMarker.m | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ios/AirMaps/AIRMapMarker.m b/ios/AirMaps/AIRMapMarker.m index 608198c50..8be20784e 100644 --- a/ios/AirMaps/AIRMapMarker.m +++ b/ios/AirMaps/AIRMapMarker.m @@ -216,6 +216,8 @@ - (void)_handleTap:(UITapGestureRecognizer *)recognizer { if (marker.onPress) marker.onPress(event); if (marker.map.onMarkerPress) marker.map.onMarkerPress(event); + + [marker.map selectAnnotation:marker animated:NO]; } - (void)hideCalloutView From d53d93eb9eb44d38a8f7757274edda4293085873 Mon Sep 17 00:00:00 2001 From: Grey Vugrin Date: Sat, 4 Mar 2017 10:48:15 -0800 Subject: [PATCH 0215/1148] Improve documentation of customMapStyle (#1085) * Improve documentation of customMapStyle Readme addition described in https://github.com/airbnb/react-native-maps/issues/881. * Add customMapStyle prop to MapView doc --- README.md | 18 ++++++++++++++++++ docs/mapview.md | 1 + 2 files changed, 19 insertions(+) diff --git a/README.md b/README.md index 8322d0fcf..41139a4a0 100644 --- a/README.md +++ b/README.md @@ -190,6 +190,24 @@ render() { ); } ``` +For iOS, in addition to providing the `mapStyle` you will need to do the following + +```jsx +import MapView, { PROVIDER_GOOGLE } from 'react-native-maps' + +// ... + + +``` + +Then add the AirGoogleMaps directory: + +https://github.com/airbnb/react-native-maps/blob/1e71a21f39e7b88554852951f773c731c94680c9/docs/installation.md#ios + +An unoffical step-by-step guide is also available at https://gist.github.com/heron2014/e60fa003e9b117ce80d56bb1d5bfe9e0 ## Examples diff --git a/docs/mapview.md b/docs/mapview.md index ed8ecb71d..3c6dd08c4 100644 --- a/docs/mapview.md +++ b/docs/mapview.md @@ -9,6 +9,7 @@ | `initialRegion` | `Region` | | The initial region to be displayed by the map. Use this prop instead of `region` only if you don't want to control the viewport of the map besides the initial region.

Changing this prop after the component has mounted will not result in a region change.

This is similar to the `initialValue` prop of a text input. | `liteMode` | `Boolean` | `false` | Enable lite mode. **Note**: Android only. | `mapType` | `String` | `"standard"` | The map type to be displayed.

- standard: standard road map (default)
- satellite: satellite view
- hybrid: satellite view with roads and points of interest overlayed
- terrain: (Android only) topographic view +| `customMapStyle` | `Array` | | Adds custom styling to the map component. See [README](https://github.com/airbnb/react-native-maps#customizing-the-map-style) for more information. | `showsUserLocation` | `Boolean` | `false` | If `true` the app will ask for the user's location. **NOTE**: You need to add `NSLocationWhenInUseUsageDescription` key in Info.plist to enable geolocation, otherwise it is going to *fail silently*! | `followsUserLocation` | `Boolean` | `false` | If `true` the map will focus on the user's location. This only works if `showsUserLocation` is true and the user has shared their location. **Note**: iOS only. | `showsMyLocationButton` | `Boolean` | `true` | `Android only` If `false` hide the button to move map to the current user's location. From 536d11f8dd778900a9c5b53eea543a3b9d3907ba Mon Sep 17 00:00:00 2001 From: Guillaume DROULEZ Date: Tue, 7 Mar 2017 10:52:32 +0100 Subject: [PATCH 0216/1148] Crash in our App fix java.lang.NullPointerException: Attempt to invoke virtual method 'com.google.android.gms.maps.Projection com.google.android.gms.maps.GoogleMap.getProjection()' on a null object reference at com.airbnb.android.react.maps.AirMapView$13.run(AirMapView.java:643) at android.os.Handler.handleCallback(Handler.java:739) at android.os.Handler.dispatchMessage(Handler.java:95) at android.os.Looper.loop(Looper.java:135) at android.app.ActivityThread.main(ActivityThread.java:5289) at java.lang.reflect.Method.invoke(Native Method) at java.lang.reflect.Method.invoke(Method.java:372) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.ja va:899) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694) --- .../java/com/airbnb/android/react/maps/AirMapView.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java b/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java index 632e568bc..646b318be 100644 --- a/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java +++ b/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java @@ -41,6 +41,7 @@ import com.google.android.gms.maps.model.Marker; import com.google.android.gms.maps.model.Polygon; import com.google.android.gms.maps.model.Polyline; +import com.google.android.gms.maps.model.VisibleRegion; import java.util.ArrayList; import java.util.Arrays; @@ -646,9 +647,12 @@ public void stopMonitoringRegion() { @Override public void run() { - LatLngBounds bounds = map.getProjection().getVisibleRegion().latLngBounds; - if (lastBoundsEmitted == null || - LatLngBoundsUtils.BoundsAreDifferent(bounds, lastBoundsEmitted)) { + Projection projection = map.getProjection(); + VisibleRegion region = (projection != null) ? projection.getVisibleRegion() : null; + LatLngBounds bounds = (region != null) ? region.latLngBounds : null; + + if ((bounds != null) && + (lastBoundsEmitted == null || LatLngBoundsUtils.BoundsAreDifferent(bounds, lastBoundsEmitted))) { LatLng center = map.getCameraPosition().target; lastBoundsEmitted = bounds; eventDispatcher.dispatchEvent(new RegionChangeEvent(getId(), bounds, center, true)); From cbbea86127350ccbe58e780668ec4c7f56bdd940 Mon Sep 17 00:00:00 2001 From: Christian Mitchell Date: Wed, 8 Mar 2017 11:30:26 +1300 Subject: [PATCH 0217/1148] Updated Google play services and gradle build plugin (#1023) * Updated Gradle build version * Updated Google Play Services --- android/build.gradle | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/android/build.gradle b/android/build.gradle index d6e86e557..740017fad 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -18,7 +18,7 @@ buildscript { } } dependencies { - classpath 'com.android.tools.build:gradle:2.1.0' + classpath 'com.android.tools.build:gradle:2.2.3' } } @@ -39,12 +39,12 @@ allprojects { } android { - compileSdkVersion 23 + compileSdkVersion 25 buildToolsVersion "23.0.3" defaultConfig { minSdkVersion 16 - targetSdkVersion 23 + targetSdkVersion 25 } lintOptions { @@ -54,6 +54,6 @@ android { dependencies { compile "com.facebook.react:react-native:+" - compile "com.google.android.gms:play-services-base:9.8.0" - compile "com.google.android.gms:play-services-maps:9.8.0" + compile "com.google.android.gms:play-services-base:10.0.1" + compile "com.google.android.gms:play-services-maps:10.0.1" } From a2dfedfb36c164da9e15862a9f6ba75ee988008b Mon Sep 17 00:00:00 2001 From: allthetime Date: Tue, 7 Mar 2017 15:12:11 -0800 Subject: [PATCH 0218/1148] specify `react-native link` command (#1086) `react-native link react-native-maps` should be used instead of simply `react-native link` because it may break, or double, manual linkings, especially for libraries that that do not work with `react-native link` (gl-react-native for example) --- docs/installation.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/installation.md b/docs/installation.md index 5a394322f..49f37fd85 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -10,7 +10,7 @@ Second, install the native dependencies: You can use `rnpm` (now part of `react- add native dependencies automatically then continue the directions below depending on your target OS. ``` -react-native link +react-native link react-native-maps ``` >This installation should work in physical devices. For Genymotion, be sure to check Android installation about Google Play Services @@ -63,7 +63,7 @@ After your `Podfile` is setup properly, run `pod install`. ## Android 1. In your `android/app/build.gradle` add: - >This step is not necessary if you ran "react-native link" + >This step is not necessary if you ran "react-native link react-native-maps" ```groovy ... @@ -125,13 +125,13 @@ If you have a blank map issue, ([#118](https://github.com/airbnb/react-native-ma You have to link dependencies with rnpm and re-run the build: -1. `react-native link` +1. `react-native link react-native-maps` 1. `react-native run-ios` ### On Android: 1. Be sure to have `new MapsPackage()` in your `MainApplication.java` : - >This step is not necessary if you ran "react-native link" + >This step is not necessary if you ran "react-native link react-native-maps" ``` import com.airbnb.android.react.maps.MapsPackage; @@ -190,7 +190,7 @@ You have to link dependencies with rnpm and re-run the build: - Extras / Google Repository - Android 6.0 (API 23) / Google APIs Intel x86 Atom System Image Rev. 19 - Android SDK Build-tools 23.0.3 -1. Check manual installation steps if you didn't run "react-native link" +1. Check manual installation steps if you didn't run "react-native link react-native-maps" 1. Go to [Google API Console](https://console.developers.google.com/flows/enableapi?apiid=maps_android_backend) and select your project, or create one. Then, once enabled, select `Go to credentials`. Select `Google Maps Android API` and create a new key. From dfa01ccae99c56fef50b6f2746e4ff7c72d6424d Mon Sep 17 00:00:00 2001 From: Grey Vugrin Date: Tue, 7 Mar 2017 15:12:40 -0800 Subject: [PATCH 0219/1148] Mention rgba option for polygons in docs (#1084) * Mention rgba option for polygon colors Courtesy of https://github.com/airbnb/react-native-maps/issues/183 * Added rgba mention to circle doc --- docs/circle.md | 4 ++-- docs/polygon.md | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/circle.md b/docs/circle.md index 706237c18..70a5e078e 100644 --- a/docs/circle.md +++ b/docs/circle.md @@ -7,8 +7,8 @@ | `center` | `LatLng` | (Required) | The coordinate of the center of the circle | `radius` | `Number` | (Required) | The radius of the circle to be drawn (in meters) | `strokeWidth` | `Number` | `1` | The stroke width to use for the path. -| `strokeColor` | `String` | `#000` | The stroke color to use for the path. -| `fillColor` | `String` | | The fill color to use for the path. +| `strokeColor` | `String` | `#000`, `rgba(r,g,b,0.5)` | The stroke color to use for the path. +| `fillColor` | `String` | `#000`, `rgba(r,g,b,0.5)` | The fill color to use for the path. | `zIndex` | `Number` | 0 | The order in which this tile overlay is drawn with respect to other overlays. An overlay with a larger z-index is drawn over overlays with smaller z-indices. The order of overlays with the same z-index is arbitrary. The default zIndex is 0. (Android Only) | `lineCap` | `String` | `round` | The line cap style to apply to the open ends of the path. | `lineJoin` | `Array` | | The line join style to apply to corners of the path. diff --git a/docs/polygon.md b/docs/polygon.md index 875327a81..085b31a18 100644 --- a/docs/polygon.md +++ b/docs/polygon.md @@ -6,8 +6,8 @@ |---|---|---|---| | `coordinates` | `Array` | (Required) | An array of coordinates to describe the polygon | `strokeWidth` | `Number` | `1` | The stroke width to use for the path. -| `strokeColor` | `String` | `#000` | The stroke color to use for the path. -| `fillColor` | `String` | | The fill color to use for the path. +| `strokeColor` | `String` | `#000`, `rgba(r,g,b,0.5)` | The stroke color to use for the path. +| `fillColor` | `String` | `#000`, `rgba(r,g,b,0.5)` | The fill color to use for the path. | `lineCap` | `String` | `round` | The line cap style to apply to the open ends of the path. | `lineJoin` | `Array` | | The line join style to apply to corners of the path. | `miterLimit` | `Number` | | The limiting value that helps avoid spikes at junctions between connected line segments. The miter limit helps you avoid spikes in paths that use the `miter` `lineJoin` style. If the ratio of the miter length—that is, the diagonal length of the miter join—to the line thickness exceeds the miter limit, the joint is converted to a bevel join. The default miter limit is 10, which results in the conversion of miters whose angle at the joint is less than 11 degrees. From 4b712670a72be5dde157202bb141e5379fd005bf Mon Sep 17 00:00:00 2001 From: Evan Siroky Date: Tue, 7 Mar 2017 15:14:38 -0800 Subject: [PATCH 0220/1148] Add one more tip to Android installation troubleshooting (#1060) * Add one more tip to Android installation troubleshooting Add note about dealing with correcting the system image to use with the emulator. * reword a tip in the troubleshooting section --- docs/installation.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/docs/installation.md b/docs/installation.md index 49f37fd85..aefa6c5b6 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -22,7 +22,7 @@ react-native link react-native-maps 1. Setup your `Podfile` like the included [example/ios/Podfile](../example/ios/Podfile), replace all references to `AirMapExplorer` with your project name, and then run `pod install`. (If you do not need `GoogleMaps` support for iOS, then you can probably completely skip this step.) 1. Open your project in Xcode workspace -1. If you need `GoogleMaps` support also +1. If you need `GoogleMaps` support also - Drag this folder `node_modules/react-native-maps/ios/AirGoogleMaps/` into your project, and choose `Create groups` in the popup window. - In `AppDelegate.m`, add `@import GoogleMaps;` before `@implementation AppDelegate`. In `- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions`, add `[GMSServices provideAPIKey:@"YOUR_GOOGLE_MAP_API_KEY"];` - In your project's `Build Settings` > `Header Search Paths`, double click the value field. In the popup, add `$(SRCROOT)/../node_modules/react-native-maps/ios/AirMaps` and change `non-recursive` to `recursive`. (Dragging the folder `node_modules/react-native-maps/ios/AirMaps/` into your project introduces duplicate symbols. We should not do it.) @@ -72,9 +72,9 @@ After your `Podfile` is setup properly, run `pod install`. compile project(':react-native-maps') } ``` - + If you have a different play services than the one included in this library, use the following instead (switch 10.0.1 for the desired version): - + ```groovy ... dependencies { @@ -212,5 +212,7 @@ Enter the name of the API key and create it. gradlew clean cd .. ``` - + 1. If you are using Android Virtual Devices (AVD), ensure that `Use Host GPU` is checked in the settings for your virtual device. + +1. If using an emulator and the only thing that shows up on the screen is the message: `[APPNAME] won't run without Google Play services which are not supported by your device.`, you need to change the emulator CPU/ABI setting to a system image that includes Google APIs. These may need to be downloaded from the Android SDK Manager first. From 88e9aea7bfbecd72fdc6d3df86a74618d86b661e Mon Sep 17 00:00:00 2001 From: Alvaro Date: Wed, 8 Mar 2017 00:15:15 +0100 Subject: [PATCH 0221/1148] Improve documentation for fitToCoordinates (#1037) * added notes for fitToCoordinates call * Notes for fitToCoordinates set in correct box --- docs/mapview.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/mapview.md b/docs/mapview.md index 3c6dd08c4..5c80b87f9 100644 --- a/docs/mapview.md +++ b/docs/mapview.md @@ -57,9 +57,9 @@ |---|---|---| | `animateToRegion` | `region: Region`, `duration: Number` | | `animateToCoordinate` | `coordinate: LatLng`, `duration: Number` | -| `fitToElements` | `animated: Boolean` | +| `fitToElements` | `animated: Boolean` | | `fitToSuppliedMarkers` | `markerIDs: String[]`, `animated: Boolean` | If you need to use this in `ComponentDidMount`, make sure you put it in a timeout or it will cause performance problems. -| `fitToCoordinates` | `coordinates: Array, options: { edgePadding: EdgePadding, animated: Boolean }` | +| `fitToCoordinates` | `coordinates: Array, options: { edgePadding: EdgePadding, animated: Boolean }` | If called in `ComponentDidMount` in android, it will cause an exception. It is recommended to call it from the MapView `onLayout` event. From b7f33d0093970c4c6a6ca44a7b2b021713acdc39 Mon Sep 17 00:00:00 2001 From: David DiPanfilo Date: Mon, 13 Mar 2017 11:04:25 -0400 Subject: [PATCH 0222/1148] Update for dependency issues (#1092) * Update for dependency issues https://github.com/airbnb/react-native-maps/issues/1067 this is a common issue people are experiencing right now * Distinguish dependencies for React versions --- docs/installation.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/installation.md b/docs/installation.md index aefa6c5b6..9783b46a5 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -26,6 +26,8 @@ react-native link react-native-maps - Drag this folder `node_modules/react-native-maps/ios/AirGoogleMaps/` into your project, and choose `Create groups` in the popup window. - In `AppDelegate.m`, add `@import GoogleMaps;` before `@implementation AppDelegate`. In `- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions`, add `[GMSServices provideAPIKey:@"YOUR_GOOGLE_MAP_API_KEY"];` - In your project's `Build Settings` > `Header Search Paths`, double click the value field. In the popup, add `$(SRCROOT)/../node_modules/react-native-maps/ios/AirMaps` and change `non-recursive` to `recursive`. (Dragging the folder `node_modules/react-native-maps/ios/AirMaps/` into your project introduces duplicate symbols. We should not do it.) + +Note: We recommend using a version of React Native >= .40. Newer versions (>= .40) require `package.json` to be set to `"react-native-maps": "^0.13.0"`, while older versions require `"react-native-maps": "^0.12.4"`. ### Option 2: CocoaPods This is now considered the **old way** because it will only work if you **don't** have From a1f4762a4608021045f2a3a0f45cec4b7b554831 Mon Sep 17 00:00:00 2001 From: Matt Shen Date: Wed, 15 Mar 2017 21:37:45 +1100 Subject: [PATCH 0223/1148] issue#939, fix multiple-instance memory leak --- .../android/react/maps/AirMapManager.java | 8 +++++ .../airbnb/android/react/maps/AirMapView.java | 29 +++++++++++++++++-- 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java b/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java index 75ed5777f..0ecf26a41 100644 --- a/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java +++ b/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java @@ -302,4 +302,12 @@ void pushEvent(View view, String name, WritableMap data) { .receiveEvent(view.getId(), name, data); } + + + @Override + public void onDropViewInstance(AirMapView view) { + view.doDestroy(); + super.onDropViewInstance(view); + } + } diff --git a/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java b/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java index 632e568bc..ac78d9f6a 100644 --- a/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java +++ b/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java @@ -21,6 +21,7 @@ import android.widget.RelativeLayout; import com.facebook.react.bridge.LifecycleEventListener; +import com.facebook.react.bridge.ReactContext; import com.facebook.react.bridge.ReadableArray; import com.facebook.react.bridge.ReadableMap; import com.facebook.react.bridge.WritableMap; @@ -79,7 +80,9 @@ public class AirMapView extends MapView implements GoogleMap.InfoWindowAdapter, private final ScaleGestureDetector scaleDetector; private final GestureDetectorCompat gestureDetector; private final AirMapManager manager; + private LifecycleEventListener lifecycleListener; private boolean paused = false; + private boolean destroyed = false; private final ThemedReactContext context; private final EventDispatcher eventDispatcher; @@ -254,7 +257,7 @@ public void onCameraChange(CameraPosition position) { // updating location constantly, killing the battery, even though some other location-mgmt // module may // desire to shut-down location-services. - LifecycleEventListener lifecycleListener = new LifecycleEventListener() { + lifecycleListener = new LifecycleEventListener() { @Override public void onHostResume() { if (hasPermissions()) { @@ -273,11 +276,15 @@ public void onHostPause() { //noinspection MissingPermission map.setMyLocationEnabled(false); } - paused = true; + synchronized (AirMapView.this) { + AirMapView.this.onPause(); + paused = true; + } } @Override public void onHostDestroy() { + AirMapView.this.doDestroy(); } }; @@ -289,6 +296,24 @@ private boolean hasPermissions() { checkSelfPermission(getContext(), PERMISSIONS[1]) == PackageManager.PERMISSION_GRANTED; } + /* + onDestroy is final method so I can't override it. + */ + public synchronized void doDestroy() { + if (lifecycleListener != null && context != null) { + context.removeLifecycleEventListener(lifecycleListener); + lifecycleListener = null; + } + if(!paused) { + onPause(); + } + if (!destroyed) { + onDestroy(); + destroyed = true; + } + + } + public void setRegion(ReadableMap region) { if (region == null) return; From e326d323a91c09badcb6af7d48a50a21403b5556 Mon Sep 17 00:00:00 2001 From: Evan Siroky Date: Wed, 15 Mar 2017 17:32:14 -0700 Subject: [PATCH 0224/1148] Add iOS tip Add clarification to iOS options section that the advanced options may not be necessary. --- docs/installation.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/installation.md b/docs/installation.md index 9783b46a5..d3b6c331c 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -17,6 +17,8 @@ react-native link react-native-maps ## iOS +> These options may not be necessary if you ran "react-native link" + ### Option 1: CocoaPods - Same as the included AirMapsExplorer example 1. Setup your `Podfile` like the included [example/ios/Podfile](../example/ios/Podfile), replace all references to `AirMapExplorer` with your project name, and then run `pod install`. From 3c38a4067d1f73c6601e960e8a4470df9ce9e1f6 Mon Sep 17 00:00:00 2001 From: Janic Duplessis Date: Fri, 17 Mar 2017 18:40:45 -0400 Subject: [PATCH 0225/1148] Use local RCTConvert+Mapkit instead of the one in React Native --- .../AirMapsExplorer.xcodeproj/project.pbxproj | 12 ++++----- ios/AirGoogleMaps/AIRGoogleMap.h | 2 +- ios/AirGoogleMaps/AIRGoogleMap.m | 2 +- ios/AirGoogleMaps/AIRGoogleMapManager.m | 2 +- ios/AirGoogleMaps/AIRGoogleMapMarkerManager.m | 2 +- .../AIRGoogleMapPolygonManager.m | 2 +- .../AIRGoogleMapPolylineManager.m | 2 +- ios/AirMaps.xcodeproj/project.pbxproj | 13 +++++---- ios/AirMaps/AIRMap.h | 2 +- ios/AirMaps/AIRMapCircle.h | 2 +- ios/AirMaps/AIRMapManager.m | 2 +- ios/AirMaps/AIRMapMarker.h | 2 +- ios/AirMaps/AIRMapPolygon.h | 2 +- ios/AirMaps/AIRMapPolygonManager.m | 2 +- ios/AirMaps/AIRMapPolyline.h | 2 +- ios/AirMaps/AIRMapPolylineManager.m | 2 +- ios/AirMaps/AIRMapUrlTile.h | 2 +- ...nvert+MoreMapKit.h => RCTConvert+MapKit.h} | 8 ++++-- ...nvert+MoreMapKit.m => RCTConvert+MapKit.m} | 27 +++++++++++++++++-- 19 files changed, 58 insertions(+), 32 deletions(-) rename ios/AirMaps/{RCTConvert+MoreMapKit.h => RCTConvert+MapKit.h} (54%) rename ios/AirMaps/{RCTConvert+MoreMapKit.m => RCTConvert+MapKit.m} (57%) diff --git a/example/ios/AirMapsExplorer.xcodeproj/project.pbxproj b/example/ios/AirMapsExplorer.xcodeproj/project.pbxproj index df5a3a05b..01f6ca481 100644 --- a/example/ios/AirMapsExplorer.xcodeproj/project.pbxproj +++ b/example/ios/AirMapsExplorer.xcodeproj/project.pbxproj @@ -25,7 +25,7 @@ 2166AB341D82EC56007538D7 /* AIRMapPolyline.m in Sources */ = {isa = PBXBuildFile; fileRef = 2166AB121D82EC56007538D7 /* AIRMapPolyline.m */; }; 2166AB351D82EC56007538D7 /* AIRMapPolylineManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 2166AB141D82EC56007538D7 /* AIRMapPolylineManager.m */; }; 2166AB361D82EC56007538D7 /* SMCalloutView.m in Sources */ = {isa = PBXBuildFile; fileRef = 2166AB171D82EC56007538D7 /* SMCalloutView.m */; }; - 2166AB3E1D82EC56007538D7 /* RCTConvert+MoreMapKit.m in Sources */ = {isa = PBXBuildFile; fileRef = 2166AB281D82EC56007538D7 /* RCTConvert+MoreMapKit.m */; }; + 2166AB3E1D82EC56007538D7 /* RCTConvert+MapKit.m in Sources */ = {isa = PBXBuildFile; fileRef = 2166AB281D82EC56007538D7 /* RCTConvert+MapKit.m */; }; 21D346651D933B8C002BAD8A /* AIRMapUrlTile.m in Sources */ = {isa = PBXBuildFile; fileRef = 21D346621D933B8C002BAD8A /* AIRMapUrlTile.m */; }; 21D346661D933B8C002BAD8A /* AIRMapUrlTileManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 21D346641D933B8C002BAD8A /* AIRMapUrlTileManager.m */; }; 21E6570A1D77591400B75EE5 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 21E657091D77591400B75EE5 /* SystemConfiguration.framework */; }; @@ -106,8 +106,8 @@ 2166AB141D82EC56007538D7 /* AIRMapPolylineManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRMapPolylineManager.m; sourceTree = ""; }; 2166AB161D82EC56007538D7 /* SMCalloutView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SMCalloutView.h; sourceTree = ""; }; 2166AB171D82EC56007538D7 /* SMCalloutView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SMCalloutView.m; sourceTree = ""; }; - 2166AB271D82EC56007538D7 /* RCTConvert+MoreMapKit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "RCTConvert+MoreMapKit.h"; sourceTree = ""; }; - 2166AB281D82EC56007538D7 /* RCTConvert+MoreMapKit.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "RCTConvert+MoreMapKit.m"; sourceTree = ""; }; + 2166AB271D82EC56007538D7 /* RCTConvert+MapKit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "RCTConvert+MapKit.h"; sourceTree = ""; }; + 2166AB281D82EC56007538D7 /* RCTConvert+MapKit.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "RCTConvert+MapKit.m"; sourceTree = ""; }; 21D346611D933B8C002BAD8A /* AIRMapUrlTile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRMapUrlTile.h; sourceTree = ""; }; 21D346621D933B8C002BAD8A /* AIRMapUrlTile.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRMapUrlTile.m; sourceTree = ""; }; 21D346631D933B8C002BAD8A /* AIRMapUrlTileManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRMapUrlTileManager.h; sourceTree = ""; }; @@ -242,8 +242,8 @@ 21D346631D933B8C002BAD8A /* AIRMapUrlTileManager.h */, 21D346641D933B8C002BAD8A /* AIRMapUrlTileManager.m */, 2166AB151D82EC56007538D7 /* Callout */, - 2166AB271D82EC56007538D7 /* RCTConvert+MoreMapKit.h */, - 2166AB281D82EC56007538D7 /* RCTConvert+MoreMapKit.m */, + 2166AB271D82EC56007538D7 /* RCTConvert+MapKit.h */, + 2166AB281D82EC56007538D7 /* RCTConvert+MapKit.m */, ); name = AirMaps; path = ../../ios/AirMaps; @@ -528,7 +528,7 @@ 8697D6221DBEDE6100DB7D0F /* AIRGoogleMapCircle.m in Sources */, 2166AB321D82EC56007538D7 /* AIRMapPolygon.m in Sources */, 13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */, - 2166AB3E1D82EC56007538D7 /* RCTConvert+MoreMapKit.m in Sources */, + 2166AB3E1D82EC56007538D7 /* RCTConvert+MapKit.m in Sources */, 8697D6251DBEE22B00DB7D0F /* AIRGoogleMapCircleManager.m in Sources */, 13B07FC11A68108700A75B9A /* main.m in Sources */, 86DE6F8B1DCE8543002A5053 /* AIRGoogleMapURLTileManager.m in Sources */, diff --git a/ios/AirGoogleMaps/AIRGoogleMap.h b/ios/AirGoogleMaps/AIRGoogleMap.h index 925aa4746..bf74e4047 100644 --- a/ios/AirGoogleMaps/AIRGoogleMap.h +++ b/ios/AirGoogleMaps/AIRGoogleMap.h @@ -7,10 +7,10 @@ #import #import -#import #import #import #import "AIRGMSMarker.h" +#import "RCTConvert+MapKit.h" @interface AIRGoogleMap : GMSMapView diff --git a/ios/AirGoogleMaps/AIRGoogleMap.m b/ios/AirGoogleMaps/AIRGoogleMap.m index e6d028c31..46c323b65 100644 --- a/ios/AirGoogleMaps/AIRGoogleMap.m +++ b/ios/AirGoogleMaps/AIRGoogleMap.m @@ -13,8 +13,8 @@ #import "AIRGoogleMapUrlTile.h" #import #import -#import #import +#import "RCTConvert+MapKit.h" id regionAsJSON(MKCoordinateRegion region) { return @{ diff --git a/ios/AirGoogleMaps/AIRGoogleMapManager.m b/ios/AirGoogleMaps/AIRGoogleMapManager.m index e306de1d8..092f4ef62 100644 --- a/ios/AirGoogleMaps/AIRGoogleMapManager.m +++ b/ios/AirGoogleMaps/AIRGoogleMapManager.m @@ -11,7 +11,6 @@ #import #import #import -#import #import #import #import @@ -24,6 +23,7 @@ #import "AIRMapCircle.h" #import "SMCalloutView.h" #import "AIRGoogleMapMarker.h" +#import "RCTConvert+MapKit.h" #import diff --git a/ios/AirGoogleMaps/AIRGoogleMapMarkerManager.m b/ios/AirGoogleMaps/AIRGoogleMapMarkerManager.m index fd16f58a6..ac2e44347 100644 --- a/ios/AirGoogleMaps/AIRGoogleMapMarkerManager.m +++ b/ios/AirGoogleMaps/AIRGoogleMapMarkerManager.m @@ -8,8 +8,8 @@ #import "AIRGoogleMapMarkerManager.h" #import "AIRGoogleMapMarker.h" #import -#import #import +#import "RCTConvert+MapKit.h" @implementation AIRGoogleMapMarkerManager diff --git a/ios/AirGoogleMaps/AIRGoogleMapPolygonManager.m b/ios/AirGoogleMaps/AIRGoogleMapPolygonManager.m index 5c7ce2a66..08c1125a0 100644 --- a/ios/AirGoogleMaps/AIRGoogleMapPolygonManager.m +++ b/ios/AirGoogleMaps/AIRGoogleMapPolygonManager.m @@ -11,7 +11,7 @@ #import #import #import -#import "RCTConvert+MoreMapKit.h" +#import "RCTConvert+MapKit.h" #import "AIRGoogleMapPolygon.h" @interface AIRGoogleMapPolygonManager() diff --git a/ios/AirGoogleMaps/AIRGoogleMapPolylineManager.m b/ios/AirGoogleMaps/AIRGoogleMapPolylineManager.m index 8ccaa7080..5fca4e902 100644 --- a/ios/AirGoogleMaps/AIRGoogleMapPolylineManager.m +++ b/ios/AirGoogleMaps/AIRGoogleMapPolylineManager.m @@ -12,7 +12,7 @@ #import #import #import -#import "RCTConvert+MoreMapKit.h" +#import "RCTConvert+MapKit.h" #import "AIRGoogleMapPolyline.h" @interface AIRGoogleMapPolylineManager() diff --git a/ios/AirMaps.xcodeproj/project.pbxproj b/ios/AirMaps.xcodeproj/project.pbxproj index 4be12b6bc..39b1256e2 100644 --- a/ios/AirMaps.xcodeproj/project.pbxproj +++ b/ios/AirMaps.xcodeproj/project.pbxproj @@ -20,8 +20,8 @@ 1125B2E41C4AD3DA007D0023 /* AIRMapPolygonManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 1125B2D21C4AD3DA007D0023 /* AIRMapPolygonManager.m */; }; 1125B2E51C4AD3DA007D0023 /* AIRMapPolyline.m in Sources */ = {isa = PBXBuildFile; fileRef = 1125B2D41C4AD3DA007D0023 /* AIRMapPolyline.m */; }; 1125B2E61C4AD3DA007D0023 /* AIRMapPolylineManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 1125B2D61C4AD3DA007D0023 /* AIRMapPolylineManager.m */; }; - 1125B2E71C4AD3DA007D0023 /* RCTConvert+MoreMapKit.m in Sources */ = {isa = PBXBuildFile; fileRef = 1125B2D91C4AD3DA007D0023 /* RCTConvert+MoreMapKit.m */; }; 1125B2F21C4AD445007D0023 /* SMCalloutView.m in Sources */ = {isa = PBXBuildFile; fileRef = 1125B2F11C4AD445007D0023 /* SMCalloutView.m */; }; + 19DABC7F1E7C9D3C00F41150 /* RCTConvert+MapKit.m in Sources */ = {isa = PBXBuildFile; fileRef = 19DABC7E1E7C9D3C00F41150 /* RCTConvert+MapKit.m */; }; DA6C26381C9E2AFE0035349F /* AIRMapUrlTile.m in Sources */ = {isa = PBXBuildFile; fileRef = DA6C26371C9E2AFE0035349F /* AIRMapUrlTile.m */; }; DA6C263E1C9E324A0035349F /* AIRMapUrlTileManager.m in Sources */ = {isa = PBXBuildFile; fileRef = DA6C263D1C9E324A0035349F /* AIRMapUrlTileManager.m */; }; /* End PBXBuildFile section */ @@ -65,11 +65,11 @@ 1125B2D41C4AD3DA007D0023 /* AIRMapPolyline.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AIRMapPolyline.m; path = AirMaps/AIRMapPolyline.m; sourceTree = SOURCE_ROOT; }; 1125B2D51C4AD3DA007D0023 /* AIRMapPolylineManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AIRMapPolylineManager.h; path = AirMaps/AIRMapPolylineManager.h; sourceTree = SOURCE_ROOT; }; 1125B2D61C4AD3DA007D0023 /* AIRMapPolylineManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AIRMapPolylineManager.m; path = AirMaps/AIRMapPolylineManager.m; sourceTree = SOURCE_ROOT; }; - 1125B2D81C4AD3DA007D0023 /* RCTConvert+MoreMapKit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "RCTConvert+MoreMapKit.h"; path = "AirMaps/RCTConvert+MoreMapKit.h"; sourceTree = SOURCE_ROOT; }; - 1125B2D91C4AD3DA007D0023 /* RCTConvert+MoreMapKit.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "RCTConvert+MoreMapKit.m"; path = "AirMaps/RCTConvert+MoreMapKit.m"; sourceTree = SOURCE_ROOT; }; 1125B2F01C4AD445007D0023 /* SMCalloutView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SMCalloutView.h; path = AirMaps/Callout/SMCalloutView.h; sourceTree = SOURCE_ROOT; }; 1125B2F11C4AD445007D0023 /* SMCalloutView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SMCalloutView.m; path = AirMaps/Callout/SMCalloutView.m; sourceTree = SOURCE_ROOT; }; 11FA5C511C4A1296003AC2EE /* libAirMaps.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libAirMaps.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 19DABC7D1E7C9D3C00F41150 /* RCTConvert+MapKit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "RCTConvert+MapKit.h"; sourceTree = ""; }; + 19DABC7E1E7C9D3C00F41150 /* RCTConvert+MapKit.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "RCTConvert+MapKit.m"; sourceTree = ""; }; DA6C26361C9E2AFE0035349F /* AIRMapUrlTile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRMapUrlTile.h; sourceTree = ""; }; DA6C26371C9E2AFE0035349F /* AIRMapUrlTile.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRMapUrlTile.m; sourceTree = ""; }; DA6C263C1C9E324A0035349F /* AIRMapUrlTileManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRMapUrlTileManager.h; sourceTree = ""; }; @@ -132,11 +132,10 @@ 1125B2D31C4AD3DA007D0023 /* AIRMapPolyline.h */, 1125B2D51C4AD3DA007D0023 /* AIRMapPolylineManager.h */, 1125B2D61C4AD3DA007D0023 /* AIRMapPolylineManager.m */, - 21B6E2D21D99B886007E664F /* AIRMapSnapshot.h */, 1125B2F01C4AD445007D0023 /* SMCalloutView.h */, 1125B2F11C4AD445007D0023 /* SMCalloutView.m */, - 1125B2D81C4AD3DA007D0023 /* RCTConvert+MoreMapKit.h */, - 1125B2D91C4AD3DA007D0023 /* RCTConvert+MoreMapKit.m */, + 19DABC7D1E7C9D3C00F41150 /* RCTConvert+MapKit.h */, + 19DABC7E1E7C9D3C00F41150 /* RCTConvert+MapKit.m */, DA6C26361C9E2AFE0035349F /* AIRMapUrlTile.h */, DA6C26371C9E2AFE0035349F /* AIRMapUrlTile.m */, DA6C263C1C9E324A0035349F /* AIRMapUrlTileManager.h */, @@ -207,10 +206,10 @@ 1125B2E01C4AD3DA007D0023 /* AIRMapManager.m in Sources */, 1125B2E61C4AD3DA007D0023 /* AIRMapPolylineManager.m in Sources */, 1125B2DD1C4AD3DA007D0023 /* AIRMapCircle.m in Sources */, + 19DABC7F1E7C9D3C00F41150 /* RCTConvert+MapKit.m in Sources */, 1125B2E51C4AD3DA007D0023 /* AIRMapPolyline.m in Sources */, DA6C263E1C9E324A0035349F /* AIRMapUrlTileManager.m in Sources */, 1125B2DA1C4AD3DA007D0023 /* AIRMap.m in Sources */, - 1125B2E71C4AD3DA007D0023 /* RCTConvert+MoreMapKit.m in Sources */, 1125B2DF1C4AD3DA007D0023 /* AIRMapCoordinate.m in Sources */, 1125B2F21C4AD445007D0023 /* SMCalloutView.m in Sources */, 1125B2E11C4AD3DA007D0023 /* AIRMapMarker.m in Sources */, diff --git a/ios/AirMaps/AIRMap.h b/ios/AirMaps/AIRMap.h index fd4ed0f25..9edf403a1 100644 --- a/ios/AirMaps/AIRMap.h +++ b/ios/AirMaps/AIRMap.h @@ -10,9 +10,9 @@ #import #import -#import #import #import "SMCalloutView.h" +#import "RCTConvert+MapKit.h" extern const CLLocationDegrees AIRMapDefaultSpan; extern const NSTimeInterval AIRMapRegionChangeObserveInterval; diff --git a/ios/AirMaps/AIRMapCircle.h b/ios/AirMaps/AIRMapCircle.h index 44755a9ee..7d7160e85 100644 --- a/ios/AirMaps/AIRMapCircle.h +++ b/ios/AirMaps/AIRMapCircle.h @@ -8,12 +8,12 @@ #import #import -#import #import #import #import "AIRMapCoordinate.h" #import "AIRMap.h" +#import "RCTConvert+MapKit.h" @interface AIRMapCircle: MKAnnotationView diff --git a/ios/AirMaps/AIRMapManager.m b/ios/AirMaps/AIRMapManager.m index 91a7f3ef9..0585ecf1b 100644 --- a/ios/AirMaps/AIRMapManager.m +++ b/ios/AirMaps/AIRMapManager.m @@ -13,7 +13,6 @@ #import #import #import -#import #import #import #import @@ -25,6 +24,7 @@ #import "SMCalloutView.h" #import "AIRMapUrlTile.h" #import "AIRMapSnapshot.h" +#import "RCTConvert+MapKit.h" #import diff --git a/ios/AirMaps/AIRMapMarker.h b/ios/AirMaps/AIRMapMarker.h index 6d6274a4a..bbcabf506 100644 --- a/ios/AirMaps/AIRMapMarker.h +++ b/ios/AirMaps/AIRMapMarker.h @@ -13,10 +13,10 @@ #import #import -#import #import #import "AIRMap.h" #import "SMCalloutView.h" +#import "RCTConvert+MapKit.h" @class RCTBridge; diff --git a/ios/AirMaps/AIRMapPolygon.h b/ios/AirMaps/AIRMapPolygon.h index 33e752cf0..15def9100 100644 --- a/ios/AirMaps/AIRMapPolygon.h +++ b/ios/AirMaps/AIRMapPolygon.h @@ -9,10 +9,10 @@ #import #import -#import #import #import "AIRMapCoordinate.h" #import "AIRMap.h" +#import "RCTConvert+MapKit.h" diff --git a/ios/AirMaps/AIRMapPolygonManager.m b/ios/AirMaps/AIRMapPolygonManager.m index a8177c180..e9be4936a 100644 --- a/ios/AirMaps/AIRMapPolygonManager.m +++ b/ios/AirMaps/AIRMapPolygonManager.m @@ -15,7 +15,7 @@ #import #import #import -#import "RCTConvert+MoreMapKit.h" +#import "RCTConvert+MapKit.h" #import "AIRMapMarker.h" #import "AIRMapPolygon.h" diff --git a/ios/AirMaps/AIRMapPolyline.h b/ios/AirMaps/AIRMapPolyline.h index 5629b1fd4..6fb5feadc 100644 --- a/ios/AirMaps/AIRMapPolyline.h +++ b/ios/AirMaps/AIRMapPolyline.h @@ -8,11 +8,11 @@ #import #import -#import #import #import #import "AIRMapCoordinate.h" #import "AIRMap.h" +#import "RCTConvert+MapKit.h" @interface AIRMapPolyline: MKAnnotationView diff --git a/ios/AirMaps/AIRMapPolylineManager.m b/ios/AirMaps/AIRMapPolylineManager.m index 70ba3eb1f..d00a9efac 100644 --- a/ios/AirMaps/AIRMapPolylineManager.m +++ b/ios/AirMaps/AIRMapPolylineManager.m @@ -15,7 +15,7 @@ #import #import #import -#import "RCTConvert+MoreMapKit.h" +#import "RCTConvert+MapKit.h" #import "AIRMapMarker.h" #import "AIRMapPolyline.h" diff --git a/ios/AirMaps/AIRMapUrlTile.h b/ios/AirMaps/AIRMapUrlTile.h index 509331414..a33be61d1 100644 --- a/ios/AirMaps/AIRMapUrlTile.h +++ b/ios/AirMaps/AIRMapUrlTile.h @@ -10,11 +10,11 @@ #import #import -#import #import #import #import "AIRMapCoordinate.h" #import "AIRMap.h" +#import "RCTConvert+MapKit.h" @interface AIRMapUrlTile : MKAnnotationView diff --git a/ios/AirMaps/RCTConvert+MoreMapKit.h b/ios/AirMaps/RCTConvert+MapKit.h similarity index 54% rename from ios/AirMaps/RCTConvert+MoreMapKit.h rename to ios/AirMaps/RCTConvert+MapKit.h index 2d2475890..28f60bf96 100644 --- a/ios/AirMaps/RCTConvert+MoreMapKit.h +++ b/ios/AirMaps/RCTConvert+MapKit.h @@ -7,6 +7,10 @@ #import #import -@interface RCTConvert (MoreMapKit) +@interface RCTConvert (MapKit) -@end \ No newline at end of file ++ (MKCoordinateSpan)MKCoordinateSpan:(id)json; ++ (MKCoordinateRegion)MKCoordinateRegion:(id)json; ++ (MKMapType)MKMapType:(id)json; + +@end diff --git a/ios/AirMaps/RCTConvert+MoreMapKit.m b/ios/AirMaps/RCTConvert+MapKit.m similarity index 57% rename from ios/AirMaps/RCTConvert+MoreMapKit.m rename to ios/AirMaps/RCTConvert+MapKit.m index 11f19a4a8..2e3b11602 100644 --- a/ios/AirMaps/RCTConvert+MoreMapKit.m +++ b/ios/AirMaps/RCTConvert+MapKit.m @@ -3,12 +3,35 @@ // Copyright (c) 2015 Facebook. All rights reserved. // -#import "RCTConvert+MoreMapKit.h" +#import "RCTConvert+MapKit.h" #import #import "AIRMapCoordinate.h" -@implementation RCTConvert (MoreMapKit) +@implementation RCTConvert (MapKit) + ++ (MKCoordinateSpan)MKCoordinateSpan:(id)json +{ + json = [self NSDictionary:json]; + return (MKCoordinateSpan){ + [self CLLocationDegrees:json[@"latitudeDelta"]], + [self CLLocationDegrees:json[@"longitudeDelta"]] + }; +} + ++ (MKCoordinateRegion)MKCoordinateRegion:(id)json +{ + return (MKCoordinateRegion){ + [self CLLocationCoordinate2D:json], + [self MKCoordinateSpan:json] + }; +} + +RCT_ENUM_CONVERTER(MKMapType, (@{ + @"standard": @(MKMapTypeStandard), + @"satellite": @(MKMapTypeSatellite), + @"hybrid": @(MKMapTypeHybrid), +}), MKMapTypeStandard, integerValue) // NOTE(lmr): // This is a bit of a hack, but I'm using this class to simply wrap From bb5acfd533f593077c1d2828432491f2b026bfcd Mon Sep 17 00:00:00 2001 From: Leland Richardson Date: Mon, 20 Mar 2017 14:57:24 -0700 Subject: [PATCH 0226/1148] Fix null activity crash --- .../android/react/maps/AirMapManager.java | 23 +++-------- .../airbnb/android/react/maps/AirMapView.java | 39 ++++++++++--------- 2 files changed, 26 insertions(+), 36 deletions(-) diff --git a/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java b/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java index 75ed5777f..086aead67 100644 --- a/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java +++ b/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java @@ -43,8 +43,6 @@ public class AirMapManager extends ViewGroupManager { "none", GoogleMap.MAP_TYPE_NONE ); - private ReactContext reactContext; - private final ReactApplicationContext appContext; protected GoogleMapOptions googleMapOptions; @@ -61,24 +59,15 @@ public String getName() { @Override protected AirMapView createViewInstance(ThemedReactContext context) { - reactContext = context; - - try { - MapsInitializer.initialize(this.appContext); - } catch (RuntimeException e) { - e.printStackTrace(); - emitMapError("Map initialize error", "map_init_error"); - } - - return new AirMapView(context, this.appContext.getCurrentActivity(), this, this.googleMapOptions); + return new AirMapView(context, this, googleMapOptions); } - private void emitMapError(String message, String type) { + private void emitMapError(ThemedReactContext context, String message, String type) { WritableMap error = Arguments.createMap(); error.putString("message", message); error.putString("type", type); - reactContext + context .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class) .emit("onError", error); } @@ -297,9 +286,9 @@ public void updateExtraData(AirMapView view, Object extraData) { view.updateExtraData(extraData); } - void pushEvent(View view, String name, WritableMap data) { - reactContext.getJSModule(RCTEventEmitter.class) - .receiveEvent(view.getId(), name, data); + void pushEvent(ThemedReactContext context, View view, String name, WritableMap data) { + context.getJSModule(RCTEventEmitter.class) + .receiveEvent(view.getId(), name, data); } } diff --git a/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java b/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java index 632e568bc..65ba78fd9 100644 --- a/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java +++ b/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java @@ -83,14 +83,15 @@ public class AirMapView extends MapView implements GoogleMap.InfoWindowAdapter, private final ThemedReactContext context; private final EventDispatcher eventDispatcher; - public AirMapView(ThemedReactContext reactContext, Context appContext, AirMapManager manager, + public AirMapView(ThemedReactContext reactContext, AirMapManager manager, GoogleMapOptions googleMapOptions) { - super(appContext, googleMapOptions); + super(reactContext, googleMapOptions); this.manager = manager; this.context = reactContext; super.onCreate(null); + // TODO(lmr): what about onStart???? super.onResume(); super.getMapAsync(this); @@ -141,7 +142,7 @@ public void onMapReady(final GoogleMap map) { this.map.setInfoWindowAdapter(this); this.map.setOnMarkerDragListener(this); - manager.pushEvent(this, "onMapReady", new WritableNativeMap()); + manager.pushEvent(context, this, "onMapReady", new WritableNativeMap()); final AirMapView view = this; @@ -154,12 +155,12 @@ public boolean onMarkerClick(Marker marker) { event = makeClickEventData(marker.getPosition()); event.putString("action", "marker-press"); event.putString("id", airMapMarker.getIdentifier()); - manager.pushEvent(view, "onMarkerPress", event); + manager.pushEvent(context, view, "onMarkerPress", event); event = makeClickEventData(marker.getPosition()); event.putString("action", "marker-press"); event.putString("id", airMapMarker.getIdentifier()); - manager.pushEvent(markerMap.get(marker), "onPress", event); + manager.pushEvent(context, markerMap.get(marker), "onPress", event); // Return false to open the callout info window and center on the marker // https://developers.google.com/android/reference/com/google/android/gms/maps/GoogleMap.OnMarkerClickListener @@ -177,7 +178,7 @@ public boolean onMarkerClick(Marker marker) { public void onPolygonClick(Polygon polygon) { WritableMap event = makeClickEventData(polygon.getPoints().get(0)); event.putString("action", "polygon-press"); - manager.pushEvent(polygonMap.get(polygon), "onPress", event); + manager.pushEvent(context, polygonMap.get(polygon), "onPress", event); } }); @@ -186,7 +187,7 @@ public void onPolygonClick(Polygon polygon) { public void onPolylineClick(Polyline polyline) { WritableMap event = makeClickEventData(polyline.getPoints().get(0)); event.putString("action", "polyline-press"); - manager.pushEvent(polylineMap.get(polyline), "onPress", event); + manager.pushEvent(context, polylineMap.get(polyline), "onPress", event); } }); @@ -197,17 +198,17 @@ public void onInfoWindowClick(Marker marker) { event = makeClickEventData(marker.getPosition()); event.putString("action", "callout-press"); - manager.pushEvent(view, "onCalloutPress", event); + manager.pushEvent(context, view, "onCalloutPress", event); event = makeClickEventData(marker.getPosition()); event.putString("action", "callout-press"); AirMapMarker markerView = markerMap.get(marker); - manager.pushEvent(markerView, "onCalloutPress", event); + manager.pushEvent(context, markerView, "onCalloutPress", event); event = makeClickEventData(marker.getPosition()); event.putString("action", "callout-press"); AirMapCallout infoWindow = markerView.getCalloutView(); - if (infoWindow != null) manager.pushEvent(infoWindow, "onPress", event); + if (infoWindow != null) manager.pushEvent(context, infoWindow, "onPress", event); } }); @@ -216,7 +217,7 @@ public void onInfoWindowClick(Marker marker) { public void onMapClick(LatLng point) { WritableMap event = makeClickEventData(point); event.putString("action", "press"); - manager.pushEvent(view, "onPress", event); + manager.pushEvent(context, view, "onPress", event); } }); @@ -225,7 +226,7 @@ public void onMapClick(LatLng point) { public void onMapLongClick(LatLng point) { WritableMap event = makeClickEventData(point); event.putString("action", "long-press"); - manager.pushEvent(view, "onLongPress", makeClickEventData(point)); + manager.pushEvent(context, view, "onLongPress", makeClickEventData(point)); } }); @@ -661,31 +662,31 @@ public void run() { @Override public void onMarkerDragStart(Marker marker) { WritableMap event = makeClickEventData(marker.getPosition()); - manager.pushEvent(this, "onMarkerDragStart", event); + manager.pushEvent(context, this, "onMarkerDragStart", event); AirMapMarker markerView = markerMap.get(marker); event = makeClickEventData(marker.getPosition()); - manager.pushEvent(markerView, "onDragStart", event); + manager.pushEvent(context, markerView, "onDragStart", event); } @Override public void onMarkerDrag(Marker marker) { WritableMap event = makeClickEventData(marker.getPosition()); - manager.pushEvent(this, "onMarkerDrag", event); + manager.pushEvent(context, this, "onMarkerDrag", event); AirMapMarker markerView = markerMap.get(marker); event = makeClickEventData(marker.getPosition()); - manager.pushEvent(markerView, "onDrag", event); + manager.pushEvent(context, markerView, "onDrag", event); } @Override public void onMarkerDragEnd(Marker marker) { WritableMap event = makeClickEventData(marker.getPosition()); - manager.pushEvent(this, "onMarkerDragEnd", event); + manager.pushEvent(context, this, "onMarkerDragEnd", event); AirMapMarker markerView = markerMap.get(marker); event = makeClickEventData(marker.getPosition()); - manager.pushEvent(markerView, "onDragEnd", event); + manager.pushEvent(context, markerView, "onDragEnd", event); } private ProgressBar getMapLoadingProgressBar() { @@ -778,6 +779,6 @@ public void onPanDrag(MotionEvent ev) { Point point = new Point((int) ev.getX(), (int) ev.getY()); LatLng coords = this.map.getProjection().fromScreenLocation(point); WritableMap event = makeClickEventData(coords); - manager.pushEvent(this, "onPanDrag", event); + manager.pushEvent(context, this, "onPanDrag", event); } } From 4247d9be4b4ff291737e2f512be3bf8ed16e42da Mon Sep 17 00:00:00 2001 From: Leland Richardson Date: Tue, 21 Mar 2017 11:34:40 -0700 Subject: [PATCH 0227/1148] Fix abi splits on example app --- example/android/app/build.gradle | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/example/android/app/build.gradle b/example/android/app/build.gradle index c0fcb022f..f46e51f10 100644 --- a/example/android/app/build.gradle +++ b/example/android/app/build.gradle @@ -61,6 +61,8 @@ import com.android.build.OutputFile apply from: "react.gradle" +def enableSeparateBuildPerCPUArchitecture = false + /** * Run Proguard to shrink the Java bytecode in release builds. */ @@ -76,6 +78,17 @@ android { targetSdkVersion 23 versionCode 1 versionName "1.0" + ndk { + abiFilters "armeabi-v7a", "x86" + } + } + splits { + abi { + reset() + enable enableSeparateBuildPerCPUArchitecture + universalApk false // If true, also generate a universal APK + include "armeabi-v7a", "x86" + } } buildTypes { release { From 1e6dda7775ae2aaa84bfe4aae37bb1ace6147871 Mon Sep 17 00:00:00 2001 From: Gabriel Peal Date: Mon, 20 Mar 2017 17:19:36 -0700 Subject: [PATCH 0228/1148] Use provided as the gradle dependency This allows the library to compile but will use whichever RN the app is using and also allows it to pass POM verification on sonatype which doesn't allow non-explicit dependencies. --- android/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android/build.gradle b/android/build.gradle index 740017fad..18f2808c4 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -53,7 +53,7 @@ android { } dependencies { - compile "com.facebook.react:react-native:+" + provided "com.facebook.react:react-native:+" compile "com.google.android.gms:play-services-base:10.0.1" compile "com.google.android.gms:play-services-maps:10.0.1" } From dad1d3403d7d40faa0b03f899232e88da61df6f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20G=C3=BCnther?= Date: Tue, 21 Mar 2017 21:57:17 +0100 Subject: [PATCH 0229/1148] Update the android buildToolsVersion to 25.0.0 When using the current android studio with the current SDKs you have the problem that your app is on version 25 and you can not create a APK without adjusting the buildToolsVersion in the build.gradle --- android/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android/build.gradle b/android/build.gradle index 740017fad..48b3656d1 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -40,7 +40,7 @@ allprojects { android { compileSdkVersion 25 - buildToolsVersion "23.0.3" + buildToolsVersion "25.0.0" defaultConfig { minSdkVersion 16 From cc24997fc9b14ea8f87dc721ce43d9a7fe3420ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20G=C3=BCnther?= Date: Tue, 21 Mar 2017 22:11:13 +0100 Subject: [PATCH 0230/1148] Update the android SDK version to 25 in example --- example/android/app/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/example/android/app/build.gradle b/example/android/app/build.gradle index f46e51f10..5e58e57b5 100644 --- a/example/android/app/build.gradle +++ b/example/android/app/build.gradle @@ -69,8 +69,8 @@ def enableSeparateBuildPerCPUArchitecture = false def enableProguardInReleaseBuilds = false android { - compileSdkVersion 23 - buildToolsVersion "23.0.3" + compileSdkVersion 25 + buildToolsVersion "25.0.0" defaultConfig { applicationId "com.airbnb.android.react.maps.example" From e8bc08fd8e7e614174e2395a597d3b1727d65308 Mon Sep 17 00:00:00 2001 From: Leland Richardson Date: Tue, 21 Mar 2017 16:26:29 -0700 Subject: [PATCH 0231/1148] v0.13.1 --- CHANGELOG.md | 42 +++++++++++++++++++++++++++++++++++++++ android/gradle.properties | 4 ++-- package.json | 2 +- 3 files changed, 45 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0fc969558..adbe8bf60 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,47 @@ # Change Log +## 0.13.1 (March 21, 2017) + + +## Enhancements + +* Add id identifier to marker-press event on Android +[#1008](https://github.com/airbnb/react-native-maps/pull/1008) + (@stan229) + +* setNativeProps, marker opacity, nested components +[#940](https://github.com/airbnb/react-native-maps/pull/940) + (@unboundfire) + + +## Patches + +* Update the android buildToolsVersion to 25.0.0 +[#1152](https://github.com/airbnb/react-native-maps/pull/1152) + (@markusguenther) + +* use `provided` for RN gradle dependency +[#1151](https://github.com/airbnb/react-native-maps/pull/1151) + (@gpeal) + +* fix null activity crash +[#1150](https://github.com/airbnb/react-native-maps/pull/1150) + (@lelandrichardson) + +* Updated Google play services and gradle build plugin +[#1023](https://github.com/airbnb/react-native-maps/pull/1023) + (@chris-at-translate) + +* Sets the map value for the AirMapUrlTile so that it can be updated properly +[#992](https://github.com/airbnb/react-native-maps/pull/992) + (@jschloer) + +* onPress and onCalloutPress doesn't trigger on markers in iOS +[#954](https://github.com/airbnb/react-native-maps/pull/954) + (@RajkumarPunchh) + + + ## 0.13.0 (January 6, 2017) ### Breaking Changes diff --git a/android/gradle.properties b/android/gradle.properties index 81ab2a1bd..cfe4fd7d4 100644 --- a/android/gradle.properties +++ b/android/gradle.properties @@ -1,5 +1,5 @@ -VERSION_CODE=2 -VERSION_NAME=0.13.0 +VERSION_CODE=4 +VERSION_NAME=0.13.1 GROUP=com.airbnb.android POM_DESCRIPTION=React Native Map view component for Android diff --git a/package.json b/package.json index 5741fe8bd..42a006cea 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "description": "React Native Mapview component for iOS + Android", "main": "index.js", "author": "Leland Richardson ", - "version": "0.13.0", + "version": "0.13.1", "scripts": { "start": "react-native start", "lint": "eslint .", From a2ef978f29abf7812a7ccf9bee8a52970117e3d1 Mon Sep 17 00:00:00 2001 From: David Stoker Date: Wed, 22 Mar 2017 19:03:03 -0400 Subject: [PATCH 0232/1148] Add `showsMyLocationButton` support for Google Maps on iOS --- docs/mapview.md | 2 +- ios/AirGoogleMaps/AIRGoogleMap.h | 1 + ios/AirGoogleMaps/AIRGoogleMap.m | 9 +++++++++ ios/AirGoogleMaps/AIRGoogleMapManager.m | 1 + 4 files changed, 12 insertions(+), 1 deletion(-) diff --git a/docs/mapview.md b/docs/mapview.md index 5c80b87f9..9a64583a4 100644 --- a/docs/mapview.md +++ b/docs/mapview.md @@ -12,7 +12,7 @@ | `customMapStyle` | `Array` | | Adds custom styling to the map component. See [README](https://github.com/airbnb/react-native-maps#customizing-the-map-style) for more information. | `showsUserLocation` | `Boolean` | `false` | If `true` the app will ask for the user's location. **NOTE**: You need to add `NSLocationWhenInUseUsageDescription` key in Info.plist to enable geolocation, otherwise it is going to *fail silently*! | `followsUserLocation` | `Boolean` | `false` | If `true` the map will focus on the user's location. This only works if `showsUserLocation` is true and the user has shared their location. **Note**: iOS only. -| `showsMyLocationButton` | `Boolean` | `true` | `Android only` If `false` hide the button to move map to the current user's location. +| `showsMyLocationButton` | `Boolean` | `true` | If `false` hide the button to move map to the current user's location. | `showsPointsOfInterest` | `Boolean` | `true` | If `false` points of interest won't be displayed on the map. | `showsCompass` | `Boolean` | `true` | If `false` compass won't be displayed on the map. | `showsScale` | `Boolean` | `true` | A Boolean indicating whether the map shows scale information. diff --git a/ios/AirGoogleMaps/AIRGoogleMap.h b/ios/AirGoogleMaps/AIRGoogleMap.h index 925aa4746..b9fde5a67 100644 --- a/ios/AirGoogleMaps/AIRGoogleMap.h +++ b/ios/AirGoogleMaps/AIRGoogleMap.h @@ -38,6 +38,7 @@ @property (nonatomic, assign) BOOL rotateEnabled; @property (nonatomic, assign) BOOL pitchEnabled; @property (nonatomic, assign) BOOL showsUserLocation; +@property (nonatomic, assign) BOOL showsMyLocationButton; - (BOOL)didTapMarker:(GMSMarker *)marker; - (void)didTapAtCoordinate:(CLLocationCoordinate2D)coordinate; diff --git a/ios/AirGoogleMaps/AIRGoogleMap.m b/ios/AirGoogleMaps/AIRGoogleMap.m index e6d028c31..21e2de132 100644 --- a/ios/AirGoogleMaps/AIRGoogleMap.m +++ b/ios/AirGoogleMaps/AIRGoogleMap.m @@ -272,6 +272,15 @@ - (BOOL)showsUserLocation { return self.myLocationEnabled; } +- (void)setShowsMyLocationButton:(BOOL)showsMyLocationButton { + self.settings.myLocationButton = showsMyLocationButton; +} + +- (BOOL)showsMyLocationButton { + return self.settings.myLocationButton; +} + + + (MKCoordinateRegion) makeGMSCameraPositionFromMap:(GMSMapView *)map andGMSCameraPosition:(GMSCameraPosition *)position { // solution from here: http://stackoverflow.com/a/16587735/1102215 GMSVisibleRegion visibleRegion = map.projection.visibleRegion; diff --git a/ios/AirGoogleMaps/AIRGoogleMapManager.m b/ios/AirGoogleMaps/AIRGoogleMapManager.m index e306de1d8..bde7883cf 100644 --- a/ios/AirGoogleMaps/AIRGoogleMapManager.m +++ b/ios/AirGoogleMaps/AIRGoogleMapManager.m @@ -56,6 +56,7 @@ - (UIView *)view RCT_EXPORT_VIEW_PROPERTY(scrollEnabled, BOOL) RCT_EXPORT_VIEW_PROPERTY(pitchEnabled, BOOL) RCT_EXPORT_VIEW_PROPERTY(showsUserLocation, BOOL) +RCT_EXPORT_VIEW_PROPERTY(showsMyLocationButton, BOOL) RCT_EXPORT_VIEW_PROPERTY(customMapStyleString, NSString) RCT_EXPORT_VIEW_PROPERTY(onPress, RCTBubblingEventBlock) RCT_EXPORT_VIEW_PROPERTY(onLongPress, RCTBubblingEventBlock) From edde484725993e365b6dbef7cc8bfdb627e3a90e Mon Sep 17 00:00:00 2001 From: Leland Richardson Date: Sun, 26 Mar 2017 13:05:56 -0700 Subject: [PATCH 0233/1148] Fix typos --- CHANGELOG.md | 2 +- .../main/java/com/airbnb/android/react/maps/MapsPackage.java | 2 +- docs/mapview.md | 2 +- ios/AirMaps/AIRMapManager.m | 2 +- ios/AirMaps/Callout/SMCalloutView.h | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index adbe8bf60..a6e3ab5c3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -322,7 +322,7 @@ Failed to build DependencyGraph: @providesModule naming collision: Duplicate module name: String.prototype.es6 Paths: /Users//node_modules/react-native-maps/example2/node_modules/react-native/packager/react-packager/src/Resolver/polyfills/String.prototype.es6.js collides with /Users//node_modules/react-native/packager/react-packager/src/Resolver/polyfills/String.prototype.es6.js -This error is caused by a @providesModule declaration with the same name accross two different files. +This error is caused by a @providesModule declaration with the same name across two different files. ``` 0.8.2 is identical to 0.8.1, except with the offending code removed from the NPM package. diff --git a/android/src/main/java/com/airbnb/android/react/maps/MapsPackage.java b/android/src/main/java/com/airbnb/android/react/maps/MapsPackage.java index bc80cbcba..e76f63aa2 100644 --- a/android/src/main/java/com/airbnb/android/react/maps/MapsPackage.java +++ b/android/src/main/java/com/airbnb/android/react/maps/MapsPackage.java @@ -14,7 +14,7 @@ public class MapsPackage implements ReactPackage { public MapsPackage(Activity activity) { - } // backwards compatability + } // backwards compatibility public MapsPackage() { } diff --git a/docs/mapview.md b/docs/mapview.md index f83bf1834..f242f636b 100644 --- a/docs/mapview.md +++ b/docs/mapview.md @@ -26,7 +26,7 @@ | `scrollEnabled` | `Boolean` | `true` | If `false` the user won't be able to change the map region being displayed. | `pitchEnabled` | `Boolean` | `true` | If `false` the user won't be able to adjust the camera’s pitch angle. | `toolbarEnabled` | `Boolean` | `true` | `Android only` If `false` will hide 'Navigate' and 'Open in Maps' buttons on marker press -| `cacheEnabled` | `Boolean` | `false` | If `true` map will be cached and displayed as a image instead of being interactable, for performance usage. +| `cacheEnabled` | `Boolean` | `false` | If `true` map will be cached and displayed as an image instead of being interactable, for performance usage. | `loadingEnabled` | `Boolean` | `false` | If `true` a loading indicator will show while the map is loading. | `loadingIndicatorColor` | `Color` | `#606060` | Sets loading indicator color, default to `#606060`. | `loadingBackgroundColor` | `Color` | `#FFFFFF` | Sets loading background color, default to `#FFFFFF`. diff --git a/ios/AirMaps/AIRMapManager.m b/ios/AirMaps/AIRMapManager.m index 8dcaaacb4..1e2c3f5ac 100644 --- a/ios/AirMaps/AIRMapManager.m +++ b/ios/AirMaps/AIRMapManager.m @@ -685,7 +685,7 @@ - (void)_regionChanged:(AIRMap *)mapView mapView.region = region; } - // Continously observe region changes + // Continuously observe region changes [self _emitRegionChangeEvent:mapView continuous:YES]; } diff --git a/ios/AirMaps/Callout/SMCalloutView.h b/ios/AirMaps/Callout/SMCalloutView.h index f0a41a49c..1281c3030 100644 --- a/ios/AirMaps/Callout/SMCalloutView.h +++ b/ios/AirMaps/Callout/SMCalloutView.h @@ -183,7 +183,7 @@ extern NSTimeInterval const kSMCalloutViewRepositionDelayForUIScrollView; Typically you would return @c kSMCalloutViewRepositionDelayForUIScrollView if you're repositioning by calling @c [UIScrollView @c setContentOffset:animated:]. @param calloutView the @c SMCalloutView to reposition - @param offset caluclated offset necessary to make everything visible + @param offset calculated offset necessary to make everything visible @returns @c NSTimeInterval to delay the repositioning */ - (NSTimeInterval)calloutView:(SMCalloutView *)calloutView delayForRepositionWithSize:(CGSize)offset; From 6cd30add6b95ae69f0fbdc2a14adfbc394ed2a1e Mon Sep 17 00:00:00 2001 From: Leland Richardson Date: Sun, 26 Mar 2017 15:53:40 -0700 Subject: [PATCH 0234/1148] Restructure project --- .babelrc | 14 + .bundle/config | 2 + .eslintrc | 3 +- .gitignore | 2 + .travis.yml | 3 +- Gemfile | 3 + example/ios/Gemfile.lock => Gemfile.lock | 51 ++-- android/build.gradle | 59 ---- build.gradle | 25 ++ example/android/app/build.gradle | 24 +- example/android/app/react.gradle | 97 ------- .../maps/example/ExampleApplication.java | 16 +- example/android/build.gradle | 24 -- example/android/gradle.properties | 19 -- example/android/settings.gradle | 2 - example/index.android.js | 11 - example/index.ios.js | 11 - example/index.js | 4 + .../AirMapsExplorer.xcodeproj/project.pbxproj | 258 ++---------------- example/ios/AirMapsExplorer/AppDelegate.m | 2 +- .../AppIcon.appiconset/Contents.json | 10 + example/ios/Gemfile | 2 - example/ios/Podfile | 9 +- example/ios/Podfile.lock | 79 ++++-- example/ios/bundler | 17 ++ example/ios/fuzzy_match | 17 ++ example/ios/pod | 17 ++ example/package.json | 24 -- example/scripts/.eslintrc | 6 - example/scripts/watch-and-copy-src.js | 51 ---- gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 54208 bytes gradle/wrapper/gradle-wrapper.properties | 6 + example/android/gradlew => gradlew | 74 ++--- example/android/gradlew.bat => gradlew.bat | 14 +- index.js | 2 +- lib/android/build.gradle | 40 +++ .../android}/gradle-maven-push.gradle | 0 {android => lib/android}/gradle.properties | 0 .../gradle/wrapper/gradle-wrapper.jar | Bin .../gradle/wrapper/gradle-wrapper.properties | 0 {android => lib/android}/gradlew | 0 {android => lib/android}/gradlew.bat | 0 .../android}/src/main/AndroidManifest.xml | 0 .../android/react/maps/AirMapCallout.java | 0 .../react/maps/AirMapCalloutManager.java | 0 .../android/react/maps/AirMapCircle.java | 0 .../react/maps/AirMapCircleManager.java | 0 .../android/react/maps/AirMapFeature.java | 0 .../android/react/maps/AirMapLiteManager.java | 0 .../android/react/maps/AirMapManager.java | 0 .../android/react/maps/AirMapMarker.java | 0 .../react/maps/AirMapMarkerManager.java | 0 .../android/react/maps/AirMapModule.java | 0 .../android/react/maps/AirMapPolygon.java | 0 .../react/maps/AirMapPolygonManager.java | 0 .../android/react/maps/AirMapPolyline.java | 0 .../react/maps/AirMapPolylineManager.java | 0 .../android/react/maps/AirMapUrlTile.java | 0 .../react/maps/AirMapUrlTileManager.java | 0 .../airbnb/android/react/maps/AirMapView.java | 0 .../android/react/maps/LatLngBoundsUtils.java | 0 .../android/react/maps/MapsPackage.java | 0 .../android/react/maps/RegionChangeEvent.java | 0 .../react/maps/SizeReportingShadowNode.java | 0 .../components}/AnimatedRegion.js | 0 {components => lib/components}/MapCallout.js | 0 {components => lib/components}/MapCircle.js | 0 {components => lib/components}/MapMarker.js | 0 {components => lib/components}/MapPolygon.js | 0 {components => lib/components}/MapPolyline.js | 0 {components => lib/components}/MapUrlTile.js | 0 {components => lib/components}/MapView.js | 0 .../components}/ProviderConstants.js | 0 .../components}/decorateMapComponent.js | 0 {ios => lib/ios}/AirGoogleMaps/AIRGMSMarker.h | 0 {ios => lib/ios}/AirGoogleMaps/AIRGMSMarker.m | 0 .../ios}/AirGoogleMaps/AIRGMSPolygon.h | 0 .../ios}/AirGoogleMaps/AIRGMSPolygon.m | 0 {ios => lib/ios}/AirGoogleMaps/AIRGoogleMap.h | 0 {ios => lib/ios}/AirGoogleMaps/AIRGoogleMap.m | 0 .../ios}/AirGoogleMaps/AIRGoogleMapCallout.h | 0 .../ios}/AirGoogleMaps/AIRGoogleMapCallout.m | 0 .../AIRGoogleMapCalloutManager.h | 0 .../AIRGoogleMapCalloutManager.m | 0 .../ios}/AirGoogleMaps/AIRGoogleMapCircle.h | 0 .../ios}/AirGoogleMaps/AIRGoogleMapCircle.m | 0 .../AirGoogleMaps/AIRGoogleMapCircleManager.h | 0 .../AirGoogleMaps/AIRGoogleMapCircleManager.m | 0 .../ios}/AirGoogleMaps/AIRGoogleMapManager.h | 0 .../ios}/AirGoogleMaps/AIRGoogleMapManager.m | 0 .../ios}/AirGoogleMaps/AIRGoogleMapMarker.h | 0 .../ios}/AirGoogleMaps/AIRGoogleMapMarker.m | 0 .../AirGoogleMaps/AIRGoogleMapMarkerManager.h | 0 .../AirGoogleMaps/AIRGoogleMapMarkerManager.m | 0 .../ios}/AirGoogleMaps/AIRGoogleMapPolygon.h | 0 .../ios}/AirGoogleMaps/AIRGoogleMapPolygon.m | 0 .../AIRGoogleMapPolygonManager.h | 0 .../AIRGoogleMapPolygonManager.m | 0 .../ios}/AirGoogleMaps/AIRGoogleMapPolyline.h | 0 .../ios}/AirGoogleMaps/AIRGoogleMapPolyline.m | 0 .../AIRGoogleMapPolylineManager.h | 0 .../AIRGoogleMapPolylineManager.m | 0 .../AIRGoogleMapURLTileManager.m | 0 .../ios}/AirGoogleMaps/AIRGoogleMapUrlTile.h | 0 .../ios}/AirGoogleMaps/AIRGoogleMapUrlTile.m | 0 .../AIRGoogleMapUrlTileManager.h | 0 {ios => lib/ios}/AirGoogleMaps/DummyView.h | 0 {ios => lib/ios}/AirGoogleMaps/DummyView.m | 0 .../AirGoogleMaps/RCTConvert+GMSMapViewType.h | 0 .../AirGoogleMaps/RCTConvert+GMSMapViewType.m | 0 .../ios}/AirMaps.xcodeproj/project.pbxproj | 0 {ios => lib/ios}/AirMaps/AIRMap.h | 0 {ios => lib/ios}/AirMaps/AIRMap.m | 0 {ios => lib/ios}/AirMaps/AIRMapCallout.h | 0 {ios => lib/ios}/AirMaps/AIRMapCallout.m | 0 .../ios}/AirMaps/AIRMapCalloutManager.h | 0 .../ios}/AirMaps/AIRMapCalloutManager.m | 0 {ios => lib/ios}/AirMaps/AIRMapCircle.h | 0 {ios => lib/ios}/AirMaps/AIRMapCircle.m | 0 .../ios}/AirMaps/AIRMapCircleManager.h | 0 .../ios}/AirMaps/AIRMapCircleManager.m | 0 {ios => lib/ios}/AirMaps/AIRMapCoordinate.h | 0 {ios => lib/ios}/AirMaps/AIRMapCoordinate.m | 0 {ios => lib/ios}/AirMaps/AIRMapManager.h | 0 {ios => lib/ios}/AirMaps/AIRMapManager.m | 0 {ios => lib/ios}/AirMaps/AIRMapMarker.h | 0 {ios => lib/ios}/AirMaps/AIRMapMarker.m | 0 .../ios}/AirMaps/AIRMapMarkerManager.h | 0 .../ios}/AirMaps/AIRMapMarkerManager.m | 0 {ios => lib/ios}/AirMaps/AIRMapPolygon.h | 0 {ios => lib/ios}/AirMaps/AIRMapPolygon.m | 0 .../ios}/AirMaps/AIRMapPolygonManager.h | 0 .../ios}/AirMaps/AIRMapPolygonManager.m | 0 {ios => lib/ios}/AirMaps/AIRMapPolyline.h | 0 {ios => lib/ios}/AirMaps/AIRMapPolyline.m | 0 .../ios}/AirMaps/AIRMapPolylineManager.h | 0 .../ios}/AirMaps/AIRMapPolylineManager.m | 0 {ios => lib/ios}/AirMaps/AIRMapSnapshot.h | 0 {ios => lib/ios}/AirMaps/AIRMapUrlTile.h | 0 {ios => lib/ios}/AirMaps/AIRMapUrlTile.m | 0 .../ios}/AirMaps/AIRMapUrlTileManager.h | 0 .../ios}/AirMaps/AIRMapUrlTileManager.m | 0 .../ios}/AirMaps/Callout/SMCalloutView.h | 0 .../ios}/AirMaps/Callout/SMCalloutView.m | 0 {ios => lib/ios}/AirMaps/RCTConvert+MapKit.h | 0 {ios => lib/ios}/AirMaps/RCTConvert+MapKit.m | 0 package.json | 22 +- react-native-google-maps.podspec | 8 +- react-native-maps.podspec | 8 +- rn-cli.config.js | 11 + scripts/update-version.js | 6 +- settings.gradle | 7 + 152 files changed, 391 insertions(+), 669 deletions(-) create mode 100644 .babelrc create mode 100644 .bundle/config create mode 100644 Gemfile rename example/ios/Gemfile.lock => Gemfile.lock (64%) delete mode 100644 android/build.gradle create mode 100644 build.gradle delete mode 100644 example/android/app/react.gradle delete mode 100644 example/android/build.gradle delete mode 100644 example/android/gradle.properties delete mode 100644 example/android/settings.gradle delete mode 100644 example/index.android.js delete mode 100644 example/index.ios.js create mode 100644 example/index.js delete mode 100644 example/ios/Gemfile create mode 100755 example/ios/bundler create mode 100755 example/ios/fuzzy_match create mode 100755 example/ios/pod delete mode 100644 example/package.json delete mode 100644 example/scripts/.eslintrc delete mode 100644 example/scripts/watch-and-copy-src.js create mode 100644 gradle/wrapper/gradle-wrapper.jar create mode 100644 gradle/wrapper/gradle-wrapper.properties rename example/android/gradlew => gradlew (83%) rename example/android/gradlew.bat => gradlew.bat (88%) create mode 100644 lib/android/build.gradle rename {android => lib/android}/gradle-maven-push.gradle (100%) rename {android => lib/android}/gradle.properties (100%) rename {android => lib/android}/gradle/wrapper/gradle-wrapper.jar (100%) rename {android => lib/android}/gradle/wrapper/gradle-wrapper.properties (100%) rename {android => lib/android}/gradlew (100%) rename {android => lib/android}/gradlew.bat (100%) rename {android => lib/android}/src/main/AndroidManifest.xml (100%) rename {android => lib/android}/src/main/java/com/airbnb/android/react/maps/AirMapCallout.java (100%) rename {android => lib/android}/src/main/java/com/airbnb/android/react/maps/AirMapCalloutManager.java (100%) rename {android => lib/android}/src/main/java/com/airbnb/android/react/maps/AirMapCircle.java (100%) rename {android => lib/android}/src/main/java/com/airbnb/android/react/maps/AirMapCircleManager.java (100%) rename {android => lib/android}/src/main/java/com/airbnb/android/react/maps/AirMapFeature.java (100%) rename {android => lib/android}/src/main/java/com/airbnb/android/react/maps/AirMapLiteManager.java (100%) rename {android => lib/android}/src/main/java/com/airbnb/android/react/maps/AirMapManager.java (100%) rename {android => lib/android}/src/main/java/com/airbnb/android/react/maps/AirMapMarker.java (100%) rename {android => lib/android}/src/main/java/com/airbnb/android/react/maps/AirMapMarkerManager.java (100%) rename {android => lib/android}/src/main/java/com/airbnb/android/react/maps/AirMapModule.java (100%) rename {android => lib/android}/src/main/java/com/airbnb/android/react/maps/AirMapPolygon.java (100%) rename {android => lib/android}/src/main/java/com/airbnb/android/react/maps/AirMapPolygonManager.java (100%) rename {android => lib/android}/src/main/java/com/airbnb/android/react/maps/AirMapPolyline.java (100%) rename {android => lib/android}/src/main/java/com/airbnb/android/react/maps/AirMapPolylineManager.java (100%) rename {android => lib/android}/src/main/java/com/airbnb/android/react/maps/AirMapUrlTile.java (100%) rename {android => lib/android}/src/main/java/com/airbnb/android/react/maps/AirMapUrlTileManager.java (100%) rename {android => lib/android}/src/main/java/com/airbnb/android/react/maps/AirMapView.java (100%) rename {android => lib/android}/src/main/java/com/airbnb/android/react/maps/LatLngBoundsUtils.java (100%) rename {android => lib/android}/src/main/java/com/airbnb/android/react/maps/MapsPackage.java (100%) rename {android => lib/android}/src/main/java/com/airbnb/android/react/maps/RegionChangeEvent.java (100%) rename {android => lib/android}/src/main/java/com/airbnb/android/react/maps/SizeReportingShadowNode.java (100%) rename {components => lib/components}/AnimatedRegion.js (100%) rename {components => lib/components}/MapCallout.js (100%) rename {components => lib/components}/MapCircle.js (100%) rename {components => lib/components}/MapMarker.js (100%) rename {components => lib/components}/MapPolygon.js (100%) rename {components => lib/components}/MapPolyline.js (100%) rename {components => lib/components}/MapUrlTile.js (100%) rename {components => lib/components}/MapView.js (100%) rename {components => lib/components}/ProviderConstants.js (100%) rename {components => lib/components}/decorateMapComponent.js (100%) rename {ios => lib/ios}/AirGoogleMaps/AIRGMSMarker.h (100%) rename {ios => lib/ios}/AirGoogleMaps/AIRGMSMarker.m (100%) rename {ios => lib/ios}/AirGoogleMaps/AIRGMSPolygon.h (100%) rename {ios => lib/ios}/AirGoogleMaps/AIRGMSPolygon.m (100%) rename {ios => lib/ios}/AirGoogleMaps/AIRGoogleMap.h (100%) rename {ios => lib/ios}/AirGoogleMaps/AIRGoogleMap.m (100%) rename {ios => lib/ios}/AirGoogleMaps/AIRGoogleMapCallout.h (100%) rename {ios => lib/ios}/AirGoogleMaps/AIRGoogleMapCallout.m (100%) rename {ios => lib/ios}/AirGoogleMaps/AIRGoogleMapCalloutManager.h (100%) rename {ios => lib/ios}/AirGoogleMaps/AIRGoogleMapCalloutManager.m (100%) rename {ios => lib/ios}/AirGoogleMaps/AIRGoogleMapCircle.h (100%) rename {ios => lib/ios}/AirGoogleMaps/AIRGoogleMapCircle.m (100%) rename {ios => lib/ios}/AirGoogleMaps/AIRGoogleMapCircleManager.h (100%) rename {ios => lib/ios}/AirGoogleMaps/AIRGoogleMapCircleManager.m (100%) rename {ios => lib/ios}/AirGoogleMaps/AIRGoogleMapManager.h (100%) rename {ios => lib/ios}/AirGoogleMaps/AIRGoogleMapManager.m (100%) rename {ios => lib/ios}/AirGoogleMaps/AIRGoogleMapMarker.h (100%) rename {ios => lib/ios}/AirGoogleMaps/AIRGoogleMapMarker.m (100%) rename {ios => lib/ios}/AirGoogleMaps/AIRGoogleMapMarkerManager.h (100%) rename {ios => lib/ios}/AirGoogleMaps/AIRGoogleMapMarkerManager.m (100%) rename {ios => lib/ios}/AirGoogleMaps/AIRGoogleMapPolygon.h (100%) rename {ios => lib/ios}/AirGoogleMaps/AIRGoogleMapPolygon.m (100%) rename {ios => lib/ios}/AirGoogleMaps/AIRGoogleMapPolygonManager.h (100%) rename {ios => lib/ios}/AirGoogleMaps/AIRGoogleMapPolygonManager.m (100%) rename {ios => lib/ios}/AirGoogleMaps/AIRGoogleMapPolyline.h (100%) rename {ios => lib/ios}/AirGoogleMaps/AIRGoogleMapPolyline.m (100%) rename {ios => lib/ios}/AirGoogleMaps/AIRGoogleMapPolylineManager.h (100%) rename {ios => lib/ios}/AirGoogleMaps/AIRGoogleMapPolylineManager.m (100%) rename {ios => lib/ios}/AirGoogleMaps/AIRGoogleMapURLTileManager.m (100%) rename {ios => lib/ios}/AirGoogleMaps/AIRGoogleMapUrlTile.h (100%) rename {ios => lib/ios}/AirGoogleMaps/AIRGoogleMapUrlTile.m (100%) rename {ios => lib/ios}/AirGoogleMaps/AIRGoogleMapUrlTileManager.h (100%) rename {ios => lib/ios}/AirGoogleMaps/DummyView.h (100%) rename {ios => lib/ios}/AirGoogleMaps/DummyView.m (100%) rename {ios => lib/ios}/AirGoogleMaps/RCTConvert+GMSMapViewType.h (100%) rename {ios => lib/ios}/AirGoogleMaps/RCTConvert+GMSMapViewType.m (100%) rename {ios => lib/ios}/AirMaps.xcodeproj/project.pbxproj (100%) rename {ios => lib/ios}/AirMaps/AIRMap.h (100%) rename {ios => lib/ios}/AirMaps/AIRMap.m (100%) rename {ios => lib/ios}/AirMaps/AIRMapCallout.h (100%) rename {ios => lib/ios}/AirMaps/AIRMapCallout.m (100%) rename {ios => lib/ios}/AirMaps/AIRMapCalloutManager.h (100%) rename {ios => lib/ios}/AirMaps/AIRMapCalloutManager.m (100%) rename {ios => lib/ios}/AirMaps/AIRMapCircle.h (100%) rename {ios => lib/ios}/AirMaps/AIRMapCircle.m (100%) rename {ios => lib/ios}/AirMaps/AIRMapCircleManager.h (100%) rename {ios => lib/ios}/AirMaps/AIRMapCircleManager.m (100%) rename {ios => lib/ios}/AirMaps/AIRMapCoordinate.h (100%) rename {ios => lib/ios}/AirMaps/AIRMapCoordinate.m (100%) rename {ios => lib/ios}/AirMaps/AIRMapManager.h (100%) rename {ios => lib/ios}/AirMaps/AIRMapManager.m (100%) rename {ios => lib/ios}/AirMaps/AIRMapMarker.h (100%) rename {ios => lib/ios}/AirMaps/AIRMapMarker.m (100%) rename {ios => lib/ios}/AirMaps/AIRMapMarkerManager.h (100%) rename {ios => lib/ios}/AirMaps/AIRMapMarkerManager.m (100%) rename {ios => lib/ios}/AirMaps/AIRMapPolygon.h (100%) rename {ios => lib/ios}/AirMaps/AIRMapPolygon.m (100%) rename {ios => lib/ios}/AirMaps/AIRMapPolygonManager.h (100%) rename {ios => lib/ios}/AirMaps/AIRMapPolygonManager.m (100%) rename {ios => lib/ios}/AirMaps/AIRMapPolyline.h (100%) rename {ios => lib/ios}/AirMaps/AIRMapPolyline.m (100%) rename {ios => lib/ios}/AirMaps/AIRMapPolylineManager.h (100%) rename {ios => lib/ios}/AirMaps/AIRMapPolylineManager.m (100%) rename {ios => lib/ios}/AirMaps/AIRMapSnapshot.h (100%) rename {ios => lib/ios}/AirMaps/AIRMapUrlTile.h (100%) rename {ios => lib/ios}/AirMaps/AIRMapUrlTile.m (100%) rename {ios => lib/ios}/AirMaps/AIRMapUrlTileManager.h (100%) rename {ios => lib/ios}/AirMaps/AIRMapUrlTileManager.m (100%) rename {ios => lib/ios}/AirMaps/Callout/SMCalloutView.h (100%) rename {ios => lib/ios}/AirMaps/Callout/SMCalloutView.m (100%) rename {ios => lib/ios}/AirMaps/RCTConvert+MapKit.h (100%) rename {ios => lib/ios}/AirMaps/RCTConvert+MapKit.m (100%) create mode 100644 rn-cli.config.js create mode 100644 settings.gradle diff --git a/.babelrc b/.babelrc new file mode 100644 index 000000000..e4e14594b --- /dev/null +++ b/.babelrc @@ -0,0 +1,14 @@ +{ + "presets": ["react-native"], + "plugins": [ + [ + "module-resolver", + { + "alias": { + "react-native-maps": "./" + }, + "cwd": "babelrc" + } + ] + ] +} diff --git a/.bundle/config b/.bundle/config new file mode 100644 index 000000000..671243892 --- /dev/null +++ b/.bundle/config @@ -0,0 +1,2 @@ +--- +BUNDLE_BIN: "./examples/ios" diff --git a/.eslintrc b/.eslintrc index 5cfda8e5d..7b768ff92 100644 --- a/.eslintrc +++ b/.eslintrc @@ -11,6 +11,7 @@ "react/sort-comp": 0, "no-use-before-define": 0, "no-underscore-dangle": 0, - "import/no-unresolved": [2, { "ignore": ["react"] }] + "import/no-extraneous-dependencies": 0, + "import/no-unresolved": [2, { "ignore": ["^react-native-maps"] }] } } diff --git a/.gitignore b/.gitignore index a2f0b339f..dc4d6bb16 100644 --- a/.gitignore +++ b/.gitignore @@ -35,3 +35,5 @@ node_modules/ npm-debug.log Pods/ AirMapsExplorer.xcworkspace/ +lib/android/src/main/gen +example/android/app/src/main/gen diff --git a/.travis.yml b/.travis.yml index 5e075585c..34c6353e8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,6 +6,5 @@ node_js: cache: directories: - node_modules - - example/node_modules -script: npm run lint +script: npm run ci diff --git a/Gemfile b/Gemfile new file mode 100644 index 000000000..e696ba58e --- /dev/null +++ b/Gemfile @@ -0,0 +1,3 @@ +source 'https://rubygems.org' +ruby '2.2.4' +gem 'cocoapods', '1.2.0' diff --git a/example/ios/Gemfile.lock b/Gemfile.lock similarity index 64% rename from example/ios/Gemfile.lock rename to Gemfile.lock index b8c6feba0..9265653cd 100644 --- a/example/ios/Gemfile.lock +++ b/Gemfile.lock @@ -1,43 +1,43 @@ GEM remote: https://rubygems.org/ specs: - CFPropertyList (2.3.3) - activesupport (4.2.7.1) + CFPropertyList (2.3.5) + activesupport (4.2.8) i18n (~> 0.7) - json (~> 1.7, >= 1.7.7) minitest (~> 5.1) thread_safe (~> 0.3, >= 0.3.4) tzinfo (~> 1.1) claide (1.0.1) - cocoapods (1.1.1) + cocoapods (1.2.0) activesupport (>= 4.0.2, < 5) claide (>= 1.0.1, < 2.0) - cocoapods-core (= 1.1.1) + cocoapods-core (= 1.2.0) cocoapods-deintegrate (>= 1.0.1, < 2.0) - cocoapods-downloader (>= 1.1.2, < 2.0) + cocoapods-downloader (>= 1.1.3, < 2.0) cocoapods-plugins (>= 1.0.0, < 2.0) cocoapods-search (>= 1.0.0, < 2.0) cocoapods-stats (>= 1.0.0, < 2.0) - cocoapods-trunk (>= 1.1.1, < 2.0) + cocoapods-trunk (>= 1.1.2, < 2.0) cocoapods-try (>= 1.1.0, < 2.0) colored (~> 1.2) escape (~> 0.0.4) fourflusher (~> 2.0.1) gh_inspector (~> 1.0) - molinillo (~> 0.5.1) + molinillo (~> 0.5.5) nap (~> 1.0) - xcodeproj (>= 1.3.3, < 2.0) - cocoapods-core (1.1.1) + ruby-macho (~> 0.2.5) + xcodeproj (>= 1.4.1, < 2.0) + cocoapods-core (1.2.0) activesupport (>= 4.0.2, < 5) fuzzy_match (~> 2.0.4) nap (~> 1.0) cocoapods-deintegrate (1.0.1) - cocoapods-downloader (1.1.2) + cocoapods-downloader (1.1.3) cocoapods-plugins (1.0.0) nap cocoapods-search (1.0.0) cocoapods-stats (1.0.0) - cocoapods-trunk (1.1.1) + cocoapods-trunk (1.1.2) nap (>= 0.8, < 2.0) netrc (= 0.7.8) cocoapods-try (1.1.0) @@ -45,29 +45,32 @@ GEM escape (0.0.4) fourflusher (2.0.1) fuzzy_match (2.0.4) - gh_inspector (1.0.2) - i18n (0.7.0) - json (1.8.3) - minitest (5.9.1) - molinillo (0.5.3) - nanaimo (0.2.2) + gh_inspector (1.0.3) + i18n (0.8.1) + minitest (5.10.1) + molinillo (0.5.7) + nanaimo (0.2.3) nap (1.1.0) netrc (0.7.8) - thread_safe (0.3.5) - tzinfo (1.2.2) + ruby-macho (0.2.6) + thread_safe (0.3.6) + tzinfo (1.2.3) thread_safe (~> 0.1) - xcodeproj (1.4.1) + xcodeproj (1.4.2) CFPropertyList (~> 2.3.3) activesupport (>= 3) claide (>= 1.0.1, < 2.0) colored (~> 1.2) - nanaimo (~> 0.2.0) + nanaimo (~> 0.2.3) PLATFORMS ruby DEPENDENCIES - cocoapods (~> 1.1.1) + cocoapods (= 1.2.0) + +RUBY VERSION + ruby 2.2.4p230 BUNDLED WITH - 1.10.6 + 1.14.6 diff --git a/android/build.gradle b/android/build.gradle deleted file mode 100644 index 806c85d48..000000000 --- a/android/build.gradle +++ /dev/null @@ -1,59 +0,0 @@ -// Top-level build file where you can add configuration options common to all sub-projects/modules. - -apply plugin: 'com.android.library' -apply from: 'gradle-maven-push.gradle' - -buildscript { - repositories { - mavenLocal() - jcenter() - maven { - // For developing the library outside the context of the example app, expect `react-native` - // to be installed at `./node_modules`. - url "$projectDir/../node_modules/react-native/android" - } - maven { - // For developing the example app. - url "$projectDir/../../react-native/android" - } - } - dependencies { - classpath 'com.android.tools.build:gradle:2.2.3' - } -} - -allprojects { - repositories { - mavenLocal() - jcenter() - maven { - // For developing the library outside the context of the example app, expect `react-native` - // to be installed at `./node_modules`. - url "$projectDir/../node_modules/react-native/android" - } - maven { - // For developing the example app. - url "$projectDir/../../react-native/android" - } - } -} - -android { - compileSdkVersion 25 - buildToolsVersion "25.0.0" - - defaultConfig { - minSdkVersion 16 - targetSdkVersion 25 - } - - lintOptions { - disable 'InvalidPackage' - } -} - -dependencies { - provided "com.facebook.react:react-native:+" - compile "com.google.android.gms:play-services-base:10.0.1" - compile "com.google.android.gms:play-services-maps:10.0.1" -} diff --git a/build.gradle b/build.gradle new file mode 100644 index 000000000..f89d2c594 --- /dev/null +++ b/build.gradle @@ -0,0 +1,25 @@ +// Top-level build file where you can add configuration options common to all sub-projects/modules. + +buildscript { + repositories { + jcenter() + } + dependencies { + classpath 'com.android.tools.build:gradle:2.3.0' + } +} + +allprojects { + repositories { + mavenLocal() + jcenter() + maven { + // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm + url "$rootDir/node_modules/react-native/android" + } + } +} + +task clean(type: Delete) { + delete rootProject.buildDir +} diff --git a/example/android/app/build.gradle b/example/android/app/build.gradle index 5e58e57b5..c5bdebe4c 100644 --- a/example/android/app/build.gradle +++ b/example/android/app/build.gradle @@ -59,7 +59,22 @@ import com.android.build.OutputFile * ] */ -apply from: "react.gradle" +project.ext.react = [ + // the name of the generated asset file containing your JS bundle + bundleAssetName : "example.bundle", + + // the entry file for bundle generation + entryFile : "index.js", + + // the root of your project, i.e. where "package.json" lives + root : "../../../", + + // supply additional arguments to the packager + extraPackagerArgs: [] +] + + +apply from: "../../../node_modules/react-native/react.gradle" def enableSeparateBuildPerCPUArchitecture = false @@ -70,7 +85,7 @@ def enableProguardInReleaseBuilds = false android { compileSdkVersion 25 - buildToolsVersion "25.0.0" + buildToolsVersion "25.0.2" defaultConfig { applicationId "com.airbnb.android.react.maps.example" @@ -112,5 +127,8 @@ android { } dependencies { - compile project(':react-native-maps') + compile 'com.facebook.react:react-native:0.42.+' + compile 'com.android.support:appcompat-v7:25.1.1' + compile 'com.android.support:support-annotations:25.1.1' + compile project(':react-native-maps-lib') } diff --git a/example/android/app/react.gradle b/example/android/app/react.gradle deleted file mode 100644 index 11a4f8b87..000000000 --- a/example/android/app/react.gradle +++ /dev/null @@ -1,97 +0,0 @@ -import org.apache.tools.ant.taskdefs.condition.Os - -def config = project.hasProperty("react") ? project.react : []; - -def bundleAssetName = config.bundleAssetName ?: "index.android.bundle" -def entryFile = config.entryFile ?: "index.android.js" - -// because elvis operator -def elvisFile(thing) { - return thing ? file(thing) : null; -} - -def reactRoot = elvisFile(config.root) ?: file("../../") -def inputExcludes = config.inputExcludes ?: ["android/**", "ios/**"] - -void runBefore(String dependentTaskName, Task task) { - Task dependentTask = tasks.findByPath(dependentTaskName); - if (dependentTask != null) { - dependentTask.dependsOn task - } -} - -gradle.projectsEvaluated { - // Grab all build types and product flavors - def buildTypes = android.buildTypes.collect { type -> type.name } - def productFlavors = android.productFlavors.collect { flavor -> flavor.name } - - // When no product flavors defined, use empty - if (!productFlavors) productFlavors.add('') - - productFlavors.each { productFlavorName -> - buildTypes.each { buildTypeName -> - // Create variant and target names - def targetName = "${productFlavorName.capitalize()}${buildTypeName.capitalize()}" - def targetPath = productFlavorName ? - "${productFlavorName}/${buildTypeName}" : - "${buildTypeName}" - - // React js bundle directories - def jsBundleDirConfigName = "jsBundleDir${targetName}" - def jsBundleDir = elvisFile(config."$jsBundleDirConfigName") ?: - file("$buildDir/intermediates/assets/${targetPath}") - - def resourcesDirConfigName = "jsBundleDir${targetName}" - def resourcesDir = elvisFile(config."${resourcesDirConfigName}") ?: - file("$buildDir/intermediates/res/merged/${targetPath}") - def jsBundleFile = file("$jsBundleDir/$bundleAssetName") - - // Bundle task name for variant - def bundleJsAndAssetsTaskName = "bundle${targetName}JsAndAssets" - - def currentBundleTask = tasks.create( - name: bundleJsAndAssetsTaskName, - type: Exec) { - group = "react" - description = "bundle JS and assets for ${targetName}." - - // Create dirs if they are not there (e.g. the "clean" task just ran) - doFirst { - jsBundleDir.mkdirs() - resourcesDir.mkdirs() - } - - // Set up inputs and outputs so gradle can cache the result - inputs.files fileTree(dir: reactRoot, excludes: inputExcludes) - outputs.dir jsBundleDir - outputs.dir resourcesDir - - // Set up the call to the react-native cli - workingDir reactRoot - - // Set up dev mode - def devEnabled = !targetName.toLowerCase().contains("release") - if (Os.isFamily(Os.FAMILY_WINDOWS)) { - commandLine "cmd", "/c", "react-native", "bundle", "--platform", "android", "--dev", "${devEnabled}", - "--entry-file", entryFile, "--bundle-output", jsBundleFile, "--assets-dest", resourcesDir - } else { - commandLine "react-native", "bundle", "--platform", "android", "--dev", "${devEnabled}", - "--entry-file", entryFile, "--bundle-output", jsBundleFile, "--assets-dest", resourcesDir - } - - enabled config."bundleIn${targetName}" || - config."bundleIn${buildTypeName.capitalize()}" ?: - targetName.toLowerCase().contains("release") - } - - // Hook bundle${productFlavor}${buildType}JsAndAssets into the android build process - currentBundleTask.dependsOn("merge${targetName}Resources") - currentBundleTask.dependsOn("merge${targetName}Assets") - - runBefore("processArmeabi-v7a${targetName}Resources", currentBundleTask) - runBefore("processX86${targetName}Resources", currentBundleTask) - runBefore("processUniversal${targetName}Resources", currentBundleTask) - runBefore("process${targetName}Resources", currentBundleTask) - } - } -} diff --git a/example/android/app/src/main/java/com/airbnb/android/react/maps/example/ExampleApplication.java b/example/android/app/src/main/java/com/airbnb/android/react/maps/example/ExampleApplication.java index 1a7f6382f..30a52850a 100644 --- a/example/android/app/src/main/java/com/airbnb/android/react/maps/example/ExampleApplication.java +++ b/example/android/app/src/main/java/com/airbnb/android/react/maps/example/ExampleApplication.java @@ -7,16 +7,22 @@ import com.facebook.react.ReactNativeHost; import com.facebook.react.ReactPackage; import com.facebook.react.shell.MainReactPackage; +import com.facebook.soloader.SoLoader; import java.util.Arrays; import java.util.List; public class ExampleApplication extends Application implements ReactApplication { private final ReactNativeHost reactNativeHost = new ReactNativeHost(this) { - @Override protected boolean getUseDeveloperSupport() { + @Override public boolean getUseDeveloperSupport() { return BuildConfig.DEBUG; } + @Override + protected String getJSMainModuleName() { + return "example/index"; + } + @Override protected List getPackages() { return Arrays.asList( new MainReactPackage(), @@ -28,4 +34,10 @@ public class ExampleApplication extends Application implements ReactApplication public ReactNativeHost getReactNativeHost() { return reactNativeHost; } -} \ No newline at end of file + + @Override + public void onCreate() { + super.onCreate(); + SoLoader.init(this, /* native exopackage */ false); + } +} diff --git a/example/android/build.gradle b/example/android/build.gradle deleted file mode 100644 index b249b0409..000000000 --- a/example/android/build.gradle +++ /dev/null @@ -1,24 +0,0 @@ -// Top-level build file where you can add configuration options common to all sub-projects/modules. - -buildscript { - repositories { - jcenter() - } - dependencies { - classpath 'com.android.tools.build:gradle:2.2.1' - - // NOTE: Do not place your application dependencies here; they belong - // in the individual module build.gradle files - } -} - -allprojects { - repositories { - mavenLocal() - jcenter() - maven { - // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm - url "$projectDir/../../node_modules/react-native/android" - } - } -} diff --git a/example/android/gradle.properties b/example/android/gradle.properties deleted file mode 100644 index c04c048e8..000000000 --- a/example/android/gradle.properties +++ /dev/null @@ -1,19 +0,0 @@ -# Project-wide Gradle settings. - -# IDE (e.g. Android Studio) users: -# Gradle settings configured through the IDE *will override* -# any settings specified in this file. - -# For more details on how to configure your build environment visit -# http://www.gradle.org/docs/current/userguide/build_environment.html - -# Specifies the JVM arguments used for the daemon process. -# The setting is particularly useful for tweaking memory settings. -# Default value: -Xmx10248m -XX:MaxPermSize=256m -# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 - -# When configured, Gradle will run in incubating parallel mode. -# This option should only be used with decoupled projects. More details, visit -# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects -# org.gradle.parallel=true - diff --git a/example/android/settings.gradle b/example/android/settings.gradle deleted file mode 100644 index d9c3d2776..000000000 --- a/example/android/settings.gradle +++ /dev/null @@ -1,2 +0,0 @@ -include ':app', ':react-native-maps' -project(':react-native-maps').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-maps/android') diff --git a/example/index.android.js b/example/index.android.js deleted file mode 100644 index 3d259cfd3..000000000 --- a/example/index.android.js +++ /dev/null @@ -1,11 +0,0 @@ -import React from 'react'; -import { AppRegistry } from 'react-native'; -import App from './App'; - -class AirMapsExplorer extends React.Component { - render() { - return ; - } -} - -AppRegistry.registerComponent('AirMapsExplorer', () => AirMapsExplorer); diff --git a/example/index.ios.js b/example/index.ios.js deleted file mode 100644 index 3d259cfd3..000000000 --- a/example/index.ios.js +++ /dev/null @@ -1,11 +0,0 @@ -import React from 'react'; -import { AppRegistry } from 'react-native'; -import App from './App'; - -class AirMapsExplorer extends React.Component { - render() { - return ; - } -} - -AppRegistry.registerComponent('AirMapsExplorer', () => AirMapsExplorer); diff --git a/example/index.js b/example/index.js new file mode 100644 index 000000000..1fe6aeea0 --- /dev/null +++ b/example/index.js @@ -0,0 +1,4 @@ +import { AppRegistry } from 'react-native'; +import App from './App'; + +AppRegistry.registerComponent('AirMapsExplorer', () => App); diff --git a/example/ios/AirMapsExplorer.xcodeproj/project.pbxproj b/example/ios/AirMapsExplorer.xcodeproj/project.pbxproj index e2e276365..efeabceb4 100644 --- a/example/ios/AirMapsExplorer.xcodeproj/project.pbxproj +++ b/example/ios/AirMapsExplorer.xcodeproj/project.pbxproj @@ -11,45 +11,13 @@ 13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB11A68108700A75B9A /* LaunchScreen.xib */; }; 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; }; 13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; }; - 2166AB291D82EC56007538D7 /* AIRMap.m in Sources */ = {isa = PBXBuildFile; fileRef = 2166AAFC1D82EC56007538D7 /* AIRMap.m */; }; - 2166AB2A1D82EC56007538D7 /* AIRMapCallout.m in Sources */ = {isa = PBXBuildFile; fileRef = 2166AAFE1D82EC56007538D7 /* AIRMapCallout.m */; }; - 2166AB2B1D82EC56007538D7 /* AIRMapCalloutManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 2166AB001D82EC56007538D7 /* AIRMapCalloutManager.m */; }; - 2166AB2C1D82EC56007538D7 /* AIRMapCircle.m in Sources */ = {isa = PBXBuildFile; fileRef = 2166AB021D82EC56007538D7 /* AIRMapCircle.m */; }; - 2166AB2D1D82EC56007538D7 /* AIRMapCircleManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 2166AB041D82EC56007538D7 /* AIRMapCircleManager.m */; }; - 2166AB2E1D82EC56007538D7 /* AIRMapCoordinate.m in Sources */ = {isa = PBXBuildFile; fileRef = 2166AB061D82EC56007538D7 /* AIRMapCoordinate.m */; }; - 2166AB2F1D82EC56007538D7 /* AIRMapManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 2166AB081D82EC56007538D7 /* AIRMapManager.m */; }; - 2166AB301D82EC56007538D7 /* AIRMapMarker.m in Sources */ = {isa = PBXBuildFile; fileRef = 2166AB0A1D82EC56007538D7 /* AIRMapMarker.m */; }; - 2166AB311D82EC56007538D7 /* AIRMapMarkerManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 2166AB0C1D82EC56007538D7 /* AIRMapMarkerManager.m */; }; - 2166AB321D82EC56007538D7 /* AIRMapPolygon.m in Sources */ = {isa = PBXBuildFile; fileRef = 2166AB0E1D82EC56007538D7 /* AIRMapPolygon.m */; }; - 2166AB331D82EC56007538D7 /* AIRMapPolygonManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 2166AB101D82EC56007538D7 /* AIRMapPolygonManager.m */; }; - 2166AB341D82EC56007538D7 /* AIRMapPolyline.m in Sources */ = {isa = PBXBuildFile; fileRef = 2166AB121D82EC56007538D7 /* AIRMapPolyline.m */; }; - 2166AB351D82EC56007538D7 /* AIRMapPolylineManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 2166AB141D82EC56007538D7 /* AIRMapPolylineManager.m */; }; - 2166AB361D82EC56007538D7 /* SMCalloutView.m in Sources */ = {isa = PBXBuildFile; fileRef = 2166AB171D82EC56007538D7 /* SMCalloutView.m */; }; - 2166AB3E1D82EC56007538D7 /* RCTConvert+MapKit.m in Sources */ = {isa = PBXBuildFile; fileRef = 2166AB281D82EC56007538D7 /* RCTConvert+MapKit.m */; }; - 21D346651D933B8C002BAD8A /* AIRMapUrlTile.m in Sources */ = {isa = PBXBuildFile; fileRef = 21D346621D933B8C002BAD8A /* AIRMapUrlTile.m */; }; - 21D346661D933B8C002BAD8A /* AIRMapUrlTileManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 21D346641D933B8C002BAD8A /* AIRMapUrlTileManager.m */; }; 21E6570A1D77591400B75EE5 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 21E657091D77591400B75EE5 /* SystemConfiguration.framework */; }; 21E6570C1D77591A00B75EE5 /* MobileCoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 21E6570B1D77591A00B75EE5 /* MobileCoreServices.framework */; }; 21E6570E1D77591F00B75EE5 /* MapKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 21E6570D1D77591F00B75EE5 /* MapKit.framework */; }; 21E657101D77594C00B75EE5 /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 21E6570F1D77594C00B75EE5 /* AudioToolbox.framework */; }; - 5647FBD81E47A82C0054FF00 /* AIRGMSPolygon.m in Sources */ = {isa = PBXBuildFile; fileRef = 5647FBD71E47A82C0054FF00 /* AIRGMSPolygon.m */; }; - 8620CC871DBD814A00B79BFE /* AIRGMSMarker.m in Sources */ = {isa = PBXBuildFile; fileRef = 8620CC6E1DBD814A00B79BFE /* AIRGMSMarker.m */; }; - 8620CC881DBD814A00B79BFE /* AIRGoogleMap.m in Sources */ = {isa = PBXBuildFile; fileRef = 8620CC701DBD814A00B79BFE /* AIRGoogleMap.m */; }; - 8620CC891DBD814A00B79BFE /* AIRGoogleMapCallout.m in Sources */ = {isa = PBXBuildFile; fileRef = 8620CC721DBD814A00B79BFE /* AIRGoogleMapCallout.m */; }; - 8620CC8A1DBD814A00B79BFE /* AIRGoogleMapCalloutManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 8620CC741DBD814A00B79BFE /* AIRGoogleMapCalloutManager.m */; }; - 8620CC8B1DBD814A00B79BFE /* AIRGoogleMapManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 8620CC761DBD814A00B79BFE /* AIRGoogleMapManager.m */; }; - 8620CC8C1DBD814A00B79BFE /* AIRGoogleMapMarker.m in Sources */ = {isa = PBXBuildFile; fileRef = 8620CC781DBD814A00B79BFE /* AIRGoogleMapMarker.m */; }; - 8620CC8D1DBD814A00B79BFE /* AIRGoogleMapMarkerManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 8620CC7A1DBD814A00B79BFE /* AIRGoogleMapMarkerManager.m */; }; - 8620CC8E1DBD814A00B79BFE /* AIRGoogleMapPolygon.m in Sources */ = {isa = PBXBuildFile; fileRef = 8620CC7C1DBD814A00B79BFE /* AIRGoogleMapPolygon.m */; }; - 8620CC8F1DBD814A00B79BFE /* AIRGoogleMapPolygonManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 8620CC7E1DBD814A00B79BFE /* AIRGoogleMapPolygonManager.m */; }; - 8620CC901DBD814A00B79BFE /* AIRGoogleMapPolyline.m in Sources */ = {isa = PBXBuildFile; fileRef = 8620CC801DBD814A00B79BFE /* AIRGoogleMapPolyline.m */; }; - 8620CC911DBD814A00B79BFE /* AIRGoogleMapPolylineManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 8620CC821DBD814A00B79BFE /* AIRGoogleMapPolylineManager.m */; }; - 8620CC921DBD814A00B79BFE /* DummyView.m in Sources */ = {isa = PBXBuildFile; fileRef = 8620CC841DBD814A00B79BFE /* DummyView.m */; }; - 8620CC931DBD814A00B79BFE /* RCTConvert+GMSMapViewType.m in Sources */ = {isa = PBXBuildFile; fileRef = 8620CC861DBD814A00B79BFE /* RCTConvert+GMSMapViewType.m */; }; - 8697D6221DBEDE6100DB7D0F /* AIRGoogleMapCircle.m in Sources */ = {isa = PBXBuildFile; fileRef = 8697D6211DBEDE6100DB7D0F /* AIRGoogleMapCircle.m */; }; - 8697D6251DBEE22B00DB7D0F /* AIRGoogleMapCircleManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 8697D6241DBEE22B00DB7D0F /* AIRGoogleMapCircleManager.m */; }; - 86DE6F881DCE7D21002A5053 /* AIRGoogleMapUrlTile.m in Sources */ = {isa = PBXBuildFile; fileRef = 86DE6F871DCE7D21002A5053 /* AIRGoogleMapUrlTile.m */; }; - 86DE6F8B1DCE8543002A5053 /* AIRGoogleMapURLTileManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 86DE6F8A1DCE8543002A5053 /* AIRGoogleMapURLTileManager.m */; }; + 8490F2161E8879FB000099F8 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8490F2151E8879FB000099F8 /* CoreFoundation.framework */; }; + 8490F21A1E887A8F000099F8 /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8490F2191E887A8F000099F8 /* CFNetwork.framework */; }; + 8490F21C1E887AAC000099F8 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8490F21B1E887AAC000099F8 /* Security.framework */; }; A622B8115793E41C70169A8B /* libPods-AirMapsExplorer.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 0E5044A406006E7C2A53E05C /* libPods-AirMapsExplorer.a */; }; /* End PBXBuildFile section */ @@ -79,80 +47,14 @@ 2166AAF41D823402007538D7 /* CoreText.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreText.framework; path = System/Library/Frameworks/CoreText.framework; sourceTree = SDKROOT; }; 2166AAF61D823407007538D7 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 2166AAF81D82E9D0007538D7 /* React.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = React.framework; path = "Pods/../build/Debug-iphoneos/React.framework"; sourceTree = ""; }; - 2166AAFB1D82EC56007538D7 /* AIRMap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRMap.h; sourceTree = ""; }; - 2166AAFC1D82EC56007538D7 /* AIRMap.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRMap.m; sourceTree = ""; }; - 2166AAFD1D82EC56007538D7 /* AIRMapCallout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRMapCallout.h; sourceTree = ""; }; - 2166AAFE1D82EC56007538D7 /* AIRMapCallout.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRMapCallout.m; sourceTree = ""; }; - 2166AAFF1D82EC56007538D7 /* AIRMapCalloutManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRMapCalloutManager.h; sourceTree = ""; }; - 2166AB001D82EC56007538D7 /* AIRMapCalloutManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRMapCalloutManager.m; sourceTree = ""; }; - 2166AB011D82EC56007538D7 /* AIRMapCircle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRMapCircle.h; sourceTree = ""; }; - 2166AB021D82EC56007538D7 /* AIRMapCircle.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRMapCircle.m; sourceTree = ""; }; - 2166AB031D82EC56007538D7 /* AIRMapCircleManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRMapCircleManager.h; sourceTree = ""; }; - 2166AB041D82EC56007538D7 /* AIRMapCircleManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRMapCircleManager.m; sourceTree = ""; }; - 2166AB051D82EC56007538D7 /* AIRMapCoordinate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRMapCoordinate.h; sourceTree = ""; }; - 2166AB061D82EC56007538D7 /* AIRMapCoordinate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRMapCoordinate.m; sourceTree = ""; }; - 2166AB071D82EC56007538D7 /* AIRMapManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRMapManager.h; sourceTree = ""; }; - 2166AB081D82EC56007538D7 /* AIRMapManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRMapManager.m; sourceTree = ""; }; - 2166AB091D82EC56007538D7 /* AIRMapMarker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRMapMarker.h; sourceTree = ""; }; - 2166AB0A1D82EC56007538D7 /* AIRMapMarker.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRMapMarker.m; sourceTree = ""; }; - 2166AB0B1D82EC56007538D7 /* AIRMapMarkerManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRMapMarkerManager.h; sourceTree = ""; }; - 2166AB0C1D82EC56007538D7 /* AIRMapMarkerManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRMapMarkerManager.m; sourceTree = ""; }; - 2166AB0D1D82EC56007538D7 /* AIRMapPolygon.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRMapPolygon.h; sourceTree = ""; }; - 2166AB0E1D82EC56007538D7 /* AIRMapPolygon.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRMapPolygon.m; sourceTree = ""; }; - 2166AB0F1D82EC56007538D7 /* AIRMapPolygonManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRMapPolygonManager.h; sourceTree = ""; }; - 2166AB101D82EC56007538D7 /* AIRMapPolygonManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRMapPolygonManager.m; sourceTree = ""; }; - 2166AB111D82EC56007538D7 /* AIRMapPolyline.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRMapPolyline.h; sourceTree = ""; }; - 2166AB121D82EC56007538D7 /* AIRMapPolyline.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRMapPolyline.m; sourceTree = ""; }; - 2166AB131D82EC56007538D7 /* AIRMapPolylineManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRMapPolylineManager.h; sourceTree = ""; }; - 2166AB141D82EC56007538D7 /* AIRMapPolylineManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRMapPolylineManager.m; sourceTree = ""; }; - 2166AB161D82EC56007538D7 /* SMCalloutView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SMCalloutView.h; sourceTree = ""; }; - 2166AB171D82EC56007538D7 /* SMCalloutView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SMCalloutView.m; sourceTree = ""; }; - 2166AB271D82EC56007538D7 /* RCTConvert+MapKit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "RCTConvert+MapKit.h"; sourceTree = ""; }; - 2166AB281D82EC56007538D7 /* RCTConvert+MapKit.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "RCTConvert+MapKit.m"; sourceTree = ""; }; - 21D346611D933B8C002BAD8A /* AIRMapUrlTile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRMapUrlTile.h; sourceTree = ""; }; - 21D346621D933B8C002BAD8A /* AIRMapUrlTile.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRMapUrlTile.m; sourceTree = ""; }; - 21D346631D933B8C002BAD8A /* AIRMapUrlTileManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRMapUrlTileManager.h; sourceTree = ""; }; - 21D346641D933B8C002BAD8A /* AIRMapUrlTileManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRMapUrlTileManager.m; sourceTree = ""; }; 21E657091D77591400B75EE5 /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; 21E6570B1D77591A00B75EE5 /* MobileCoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MobileCoreServices.framework; path = System/Library/Frameworks/MobileCoreServices.framework; sourceTree = SDKROOT; }; 21E6570D1D77591F00B75EE5 /* MapKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MapKit.framework; path = System/Library/Frameworks/MapKit.framework; sourceTree = SDKROOT; }; 21E6570F1D77594C00B75EE5 /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = System/Library/Frameworks/AudioToolbox.framework; sourceTree = SDKROOT; }; - 5647FBD61E47A82C0054FF00 /* AIRGMSPolygon.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRGMSPolygon.h; sourceTree = ""; }; - 5647FBD71E47A82C0054FF00 /* AIRGMSPolygon.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRGMSPolygon.m; sourceTree = ""; }; - 8620CC6D1DBD814A00B79BFE /* AIRGMSMarker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRGMSMarker.h; sourceTree = ""; }; - 8620CC6E1DBD814A00B79BFE /* AIRGMSMarker.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRGMSMarker.m; sourceTree = ""; }; - 8620CC6F1DBD814A00B79BFE /* AIRGoogleMap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRGoogleMap.h; sourceTree = ""; }; - 8620CC701DBD814A00B79BFE /* AIRGoogleMap.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRGoogleMap.m; sourceTree = ""; }; - 8620CC711DBD814A00B79BFE /* AIRGoogleMapCallout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRGoogleMapCallout.h; sourceTree = ""; }; - 8620CC721DBD814A00B79BFE /* AIRGoogleMapCallout.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRGoogleMapCallout.m; sourceTree = ""; }; - 8620CC731DBD814A00B79BFE /* AIRGoogleMapCalloutManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRGoogleMapCalloutManager.h; sourceTree = ""; }; - 8620CC741DBD814A00B79BFE /* AIRGoogleMapCalloutManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRGoogleMapCalloutManager.m; sourceTree = ""; }; - 8620CC751DBD814A00B79BFE /* AIRGoogleMapManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRGoogleMapManager.h; sourceTree = ""; }; - 8620CC761DBD814A00B79BFE /* AIRGoogleMapManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRGoogleMapManager.m; sourceTree = ""; }; - 8620CC771DBD814A00B79BFE /* AIRGoogleMapMarker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRGoogleMapMarker.h; sourceTree = ""; }; - 8620CC781DBD814A00B79BFE /* AIRGoogleMapMarker.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRGoogleMapMarker.m; sourceTree = ""; }; - 8620CC791DBD814A00B79BFE /* AIRGoogleMapMarkerManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRGoogleMapMarkerManager.h; sourceTree = ""; }; - 8620CC7A1DBD814A00B79BFE /* AIRGoogleMapMarkerManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRGoogleMapMarkerManager.m; sourceTree = ""; }; - 8620CC7B1DBD814A00B79BFE /* AIRGoogleMapPolygon.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRGoogleMapPolygon.h; sourceTree = ""; }; - 8620CC7C1DBD814A00B79BFE /* AIRGoogleMapPolygon.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRGoogleMapPolygon.m; sourceTree = ""; }; - 8620CC7D1DBD814A00B79BFE /* AIRGoogleMapPolygonManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRGoogleMapPolygonManager.h; sourceTree = ""; }; - 8620CC7E1DBD814A00B79BFE /* AIRGoogleMapPolygonManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRGoogleMapPolygonManager.m; sourceTree = ""; }; - 8620CC7F1DBD814A00B79BFE /* AIRGoogleMapPolyline.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRGoogleMapPolyline.h; sourceTree = ""; }; - 8620CC801DBD814A00B79BFE /* AIRGoogleMapPolyline.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRGoogleMapPolyline.m; sourceTree = ""; }; - 8620CC811DBD814A00B79BFE /* AIRGoogleMapPolylineManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRGoogleMapPolylineManager.h; sourceTree = ""; }; - 8620CC821DBD814A00B79BFE /* AIRGoogleMapPolylineManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRGoogleMapPolylineManager.m; sourceTree = ""; }; - 8620CC831DBD814A00B79BFE /* DummyView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DummyView.h; sourceTree = ""; }; - 8620CC841DBD814A00B79BFE /* DummyView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DummyView.m; sourceTree = ""; }; - 8620CC851DBD814A00B79BFE /* RCTConvert+GMSMapViewType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "RCTConvert+GMSMapViewType.h"; sourceTree = ""; }; - 8620CC861DBD814A00B79BFE /* RCTConvert+GMSMapViewType.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "RCTConvert+GMSMapViewType.m"; sourceTree = ""; }; - 8697D6201DBEDE6100DB7D0F /* AIRGoogleMapCircle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRGoogleMapCircle.h; sourceTree = ""; }; - 8697D6211DBEDE6100DB7D0F /* AIRGoogleMapCircle.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRGoogleMapCircle.m; sourceTree = ""; }; - 8697D6231DBEE22B00DB7D0F /* AIRGoogleMapCircleManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRGoogleMapCircleManager.h; sourceTree = ""; }; - 8697D6241DBEE22B00DB7D0F /* AIRGoogleMapCircleManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRGoogleMapCircleManager.m; sourceTree = ""; }; - 86DE6F861DCE7D21002A5053 /* AIRGoogleMapUrlTile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRGoogleMapUrlTile.h; sourceTree = ""; }; - 86DE6F871DCE7D21002A5053 /* AIRGoogleMapUrlTile.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRGoogleMapUrlTile.m; sourceTree = ""; }; - 86DE6F891DCE8543002A5053 /* AIRGoogleMapUrlTileManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRGoogleMapUrlTileManager.h; sourceTree = ""; }; - 86DE6F8A1DCE8543002A5053 /* AIRGoogleMapURLTileManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRGoogleMapURLTileManager.m; sourceTree = ""; }; + 8490F2151E8879FB000099F8 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = System/Library/Frameworks/CoreFoundation.framework; sourceTree = SDKROOT; }; + 8490F2171E887A36000099F8 /* libicucore.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libicucore.tbd; path = usr/lib/libicucore.tbd; sourceTree = SDKROOT; }; + 8490F2191E887A8F000099F8 /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; + 8490F21B1E887AAC000099F8 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; }; BE5DE1E9AE25978F88CD940A /* Pods-AirMapsExplorer.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AirMapsExplorer.debug.xcconfig"; path = "Pods/Target Support Files/Pods-AirMapsExplorer/Pods-AirMapsExplorer.debug.xcconfig"; sourceTree = ""; }; E138AD0CDB08FE57B09B18F8 /* Pods-AirMapsExplorer.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AirMapsExplorer.release.xcconfig"; path = "Pods/Target Support Files/Pods-AirMapsExplorer/Pods-AirMapsExplorer.release.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ @@ -169,6 +71,9 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 8490F21C1E887AAC000099F8 /* Security.framework in Frameworks */, + 8490F21A1E887A8F000099F8 /* CFNetwork.framework in Frameworks */, + 8490F2161E8879FB000099F8 /* CoreFoundation.framework in Frameworks */, 21E657101D77594C00B75EE5 /* AudioToolbox.framework in Frameworks */, 21E6570E1D77591F00B75EE5 /* MapKit.framework in Frameworks */, 21E6570C1D77591A00B75EE5 /* MobileCoreServices.framework in Frameworks */, @@ -183,6 +88,10 @@ 051AB288C799B62BE091B88A /* Frameworks */ = { isa = PBXGroup; children = ( + 8490F21B1E887AAC000099F8 /* Security.framework */, + 8490F2191E887A8F000099F8 /* CFNetwork.framework */, + 8490F2171E887A36000099F8 /* libicucore.tbd */, + 8490F2151E8879FB000099F8 /* CoreFoundation.framework */, 2166AAF81D82E9D0007538D7 /* React.framework */, 2166AAF61D823407007538D7 /* CoreGraphics.framework */, 2166AAF41D823402007538D7 /* CoreText.framework */, @@ -211,56 +120,6 @@ name = AirMapsExplorer; sourceTree = ""; }; - 2166AAFA1D82EC56007538D7 /* AirMaps */ = { - isa = PBXGroup; - children = ( - 2166AAFB1D82EC56007538D7 /* AIRMap.h */, - 2166AAFC1D82EC56007538D7 /* AIRMap.m */, - 2166AAFD1D82EC56007538D7 /* AIRMapCallout.h */, - 2166AAFE1D82EC56007538D7 /* AIRMapCallout.m */, - 2166AAFF1D82EC56007538D7 /* AIRMapCalloutManager.h */, - 2166AB001D82EC56007538D7 /* AIRMapCalloutManager.m */, - 2166AB011D82EC56007538D7 /* AIRMapCircle.h */, - 2166AB021D82EC56007538D7 /* AIRMapCircle.m */, - 2166AB031D82EC56007538D7 /* AIRMapCircleManager.h */, - 2166AB041D82EC56007538D7 /* AIRMapCircleManager.m */, - 2166AB051D82EC56007538D7 /* AIRMapCoordinate.h */, - 2166AB061D82EC56007538D7 /* AIRMapCoordinate.m */, - 2166AB071D82EC56007538D7 /* AIRMapManager.h */, - 2166AB081D82EC56007538D7 /* AIRMapManager.m */, - 2166AB091D82EC56007538D7 /* AIRMapMarker.h */, - 2166AB0A1D82EC56007538D7 /* AIRMapMarker.m */, - 2166AB0B1D82EC56007538D7 /* AIRMapMarkerManager.h */, - 2166AB0C1D82EC56007538D7 /* AIRMapMarkerManager.m */, - 2166AB0D1D82EC56007538D7 /* AIRMapPolygon.h */, - 2166AB0E1D82EC56007538D7 /* AIRMapPolygon.m */, - 2166AB0F1D82EC56007538D7 /* AIRMapPolygonManager.h */, - 2166AB101D82EC56007538D7 /* AIRMapPolygonManager.m */, - 2166AB111D82EC56007538D7 /* AIRMapPolyline.h */, - 2166AB121D82EC56007538D7 /* AIRMapPolyline.m */, - 2166AB131D82EC56007538D7 /* AIRMapPolylineManager.h */, - 2166AB141D82EC56007538D7 /* AIRMapPolylineManager.m */, - 21D346611D933B8C002BAD8A /* AIRMapUrlTile.h */, - 21D346621D933B8C002BAD8A /* AIRMapUrlTile.m */, - 21D346631D933B8C002BAD8A /* AIRMapUrlTileManager.h */, - 21D346641D933B8C002BAD8A /* AIRMapUrlTileManager.m */, - 2166AB151D82EC56007538D7 /* Callout */, - 2166AB271D82EC56007538D7 /* RCTConvert+MapKit.h */, - 2166AB281D82EC56007538D7 /* RCTConvert+MapKit.m */, - ); - name = AirMaps; - path = ../../ios/AirMaps; - sourceTree = ""; - }; - 2166AB151D82EC56007538D7 /* Callout */ = { - isa = PBXGroup; - children = ( - 2166AB161D82EC56007538D7 /* SMCalloutView.h */, - 2166AB171D82EC56007538D7 /* SMCalloutView.m */, - ); - path = Callout; - sourceTree = ""; - }; 2BAA8C4A80B44CFBB3F83458 /* Libraries */ = { isa = PBXGroup; children = ( @@ -271,8 +130,6 @@ 83CBB9F61A601CBA00E9B192 = { isa = PBXGroup; children = ( - 8620CC6C1DBD814A00B79BFE /* AirGoogleMaps */, - 2166AAFA1D82EC56007538D7 /* AirMaps */, 13B07FAE1A68108700A75B9A /* AirMapsExplorer */, 83CBBA001A601CBA00E9B192 /* Products */, 051AB288C799B62BE091B88A /* Frameworks */, @@ -292,50 +149,6 @@ name = Products; sourceTree = ""; }; - 8620CC6C1DBD814A00B79BFE /* AirGoogleMaps */ = { - isa = PBXGroup; - children = ( - 8620CC6D1DBD814A00B79BFE /* AIRGMSMarker.h */, - 5647FBD61E47A82C0054FF00 /* AIRGMSPolygon.h */, - 5647FBD71E47A82C0054FF00 /* AIRGMSPolygon.m */, - 8620CC6E1DBD814A00B79BFE /* AIRGMSMarker.m */, - 8620CC6F1DBD814A00B79BFE /* AIRGoogleMap.h */, - 8620CC701DBD814A00B79BFE /* AIRGoogleMap.m */, - 8620CC711DBD814A00B79BFE /* AIRGoogleMapCallout.h */, - 8620CC721DBD814A00B79BFE /* AIRGoogleMapCallout.m */, - 8620CC731DBD814A00B79BFE /* AIRGoogleMapCalloutManager.h */, - 8620CC741DBD814A00B79BFE /* AIRGoogleMapCalloutManager.m */, - 8620CC751DBD814A00B79BFE /* AIRGoogleMapManager.h */, - 8620CC761DBD814A00B79BFE /* AIRGoogleMapManager.m */, - 8620CC771DBD814A00B79BFE /* AIRGoogleMapMarker.h */, - 8620CC781DBD814A00B79BFE /* AIRGoogleMapMarker.m */, - 8620CC791DBD814A00B79BFE /* AIRGoogleMapMarkerManager.h */, - 8620CC7A1DBD814A00B79BFE /* AIRGoogleMapMarkerManager.m */, - 8620CC7B1DBD814A00B79BFE /* AIRGoogleMapPolygon.h */, - 8620CC7C1DBD814A00B79BFE /* AIRGoogleMapPolygon.m */, - 8620CC7D1DBD814A00B79BFE /* AIRGoogleMapPolygonManager.h */, - 8620CC7E1DBD814A00B79BFE /* AIRGoogleMapPolygonManager.m */, - 8620CC7F1DBD814A00B79BFE /* AIRGoogleMapPolyline.h */, - 8620CC801DBD814A00B79BFE /* AIRGoogleMapPolyline.m */, - 8620CC811DBD814A00B79BFE /* AIRGoogleMapPolylineManager.h */, - 8620CC821DBD814A00B79BFE /* AIRGoogleMapPolylineManager.m */, - 8620CC831DBD814A00B79BFE /* DummyView.h */, - 8620CC841DBD814A00B79BFE /* DummyView.m */, - 8620CC851DBD814A00B79BFE /* RCTConvert+GMSMapViewType.h */, - 8620CC861DBD814A00B79BFE /* RCTConvert+GMSMapViewType.m */, - 8697D6201DBEDE6100DB7D0F /* AIRGoogleMapCircle.h */, - 8697D6211DBEDE6100DB7D0F /* AIRGoogleMapCircle.m */, - 8697D6231DBEE22B00DB7D0F /* AIRGoogleMapCircleManager.h */, - 8697D6241DBEE22B00DB7D0F /* AIRGoogleMapCircleManager.m */, - 86DE6F861DCE7D21002A5053 /* AIRGoogleMapUrlTile.h */, - 86DE6F871DCE7D21002A5053 /* AIRGoogleMapUrlTile.m */, - 86DE6F891DCE8543002A5053 /* AIRGoogleMapUrlTileManager.h */, - 86DE6F8A1DCE8543002A5053 /* AIRGoogleMapURLTileManager.m */, - ); - name = AirGoogleMaps; - path = ../../ios/AirGoogleMaps; - sourceTree = ""; - }; C2ED0F349F22CC794F9BC33F /* Pods */ = { isa = PBXGroup; children = ( @@ -453,7 +266,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "../node_modules/react-native/packager/react-native-xcode.sh"; + shellScript = "../../node_modules/react-native/packager/react-native-xcode.sh"; }; 17E7BB4CEC38ABB7449E144E /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; @@ -514,43 +327,8 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 8620CC891DBD814A00B79BFE /* AIRGoogleMapCallout.m in Sources */, - 5647FBD81E47A82C0054FF00 /* AIRGMSPolygon.m in Sources */, - 8620CC8D1DBD814A00B79BFE /* AIRGoogleMapMarkerManager.m in Sources */, - 8620CC881DBD814A00B79BFE /* AIRGoogleMap.m in Sources */, - 2166AB2D1D82EC56007538D7 /* AIRMapCircleManager.m in Sources */, - 21D346651D933B8C002BAD8A /* AIRMapUrlTile.m in Sources */, - 2166AB2A1D82EC56007538D7 /* AIRMapCallout.m in Sources */, - 8620CC8E1DBD814A00B79BFE /* AIRGoogleMapPolygon.m in Sources */, - 8620CC8C1DBD814A00B79BFE /* AIRGoogleMapMarker.m in Sources */, - 8620CC8F1DBD814A00B79BFE /* AIRGoogleMapPolygonManager.m in Sources */, - 8620CC8A1DBD814A00B79BFE /* AIRGoogleMapCalloutManager.m in Sources */, - 8620CC8B1DBD814A00B79BFE /* AIRGoogleMapManager.m in Sources */, - 2166AB2C1D82EC56007538D7 /* AIRMapCircle.m in Sources */, - 8620CC871DBD814A00B79BFE /* AIRGMSMarker.m in Sources */, - 21D346661D933B8C002BAD8A /* AIRMapUrlTileManager.m in Sources */, - 8620CC931DBD814A00B79BFE /* RCTConvert+GMSMapViewType.m in Sources */, - 2166AB301D82EC56007538D7 /* AIRMapMarker.m in Sources */, - 8697D6221DBEDE6100DB7D0F /* AIRGoogleMapCircle.m in Sources */, - 2166AB321D82EC56007538D7 /* AIRMapPolygon.m in Sources */, 13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */, - 2166AB3E1D82EC56007538D7 /* RCTConvert+MapKit.m in Sources */, - 8697D6251DBEE22B00DB7D0F /* AIRGoogleMapCircleManager.m in Sources */, 13B07FC11A68108700A75B9A /* main.m in Sources */, - 86DE6F8B1DCE8543002A5053 /* AIRGoogleMapURLTileManager.m in Sources */, - 86DE6F881DCE7D21002A5053 /* AIRGoogleMapUrlTile.m in Sources */, - 2166AB331D82EC56007538D7 /* AIRMapPolygonManager.m in Sources */, - 8620CC901DBD814A00B79BFE /* AIRGoogleMapPolyline.m in Sources */, - 2166AB2B1D82EC56007538D7 /* AIRMapCalloutManager.m in Sources */, - 8620CC921DBD814A00B79BFE /* DummyView.m in Sources */, - 2166AB361D82EC56007538D7 /* SMCalloutView.m in Sources */, - 2166AB351D82EC56007538D7 /* AIRMapPolylineManager.m in Sources */, - 8620CC911DBD814A00B79BFE /* AIRGoogleMapPolylineManager.m in Sources */, - 2166AB291D82EC56007538D7 /* AIRMap.m in Sources */, - 2166AB2E1D82EC56007538D7 /* AIRMapCoordinate.m in Sources */, - 2166AB341D82EC56007538D7 /* AIRMapPolyline.m in Sources */, - 2166AB2F1D82EC56007538D7 /* AIRMapManager.m in Sources */, - 2166AB311D82EC56007538D7 /* AIRMapMarkerManager.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -623,6 +401,7 @@ baseConfigurationReference = BE5DE1E9AE25978F88CD940A /* Pods-AirMapsExplorer.debug.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = NO; DEAD_CODE_STRIPPING = NO; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -632,7 +411,6 @@ HEADER_SEARCH_PATHS = ( "$(inherited)", /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, - "$(SRCROOT)/../node_modules/react-native/React/**", ); INFOPLIST_FILE = AirMapsExplorer/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; @@ -646,6 +424,7 @@ baseConfigurationReference = E138AD0CDB08FE57B09B18F8 /* Pods-AirMapsExplorer.release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = NO; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)/build/Debug-iphoneos", @@ -654,7 +433,6 @@ HEADER_SEARCH_PATHS = ( "$(inherited)", /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, - "$(SRCROOT)/../node_modules/react-native/React/**", ); INFOPLIST_FILE = AirMapsExplorer/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; @@ -701,7 +479,6 @@ HEADER_SEARCH_PATHS = ( "$(inherited)", /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, - "$(SRCROOT)/../node_modules/react-native/React/**", ); IPHONEOS_DEPLOYMENT_TARGET = 8.0; MTL_ENABLE_DEBUG_INFO = YES; @@ -741,7 +518,6 @@ HEADER_SEARCH_PATHS = ( "$(inherited)", /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, - "$(SRCROOT)/../node_modules/react-native/React/**", ); IPHONEOS_DEPLOYMENT_TARGET = 8.0; MTL_ENABLE_DEBUG_INFO = NO; diff --git a/example/ios/AirMapsExplorer/AppDelegate.m b/example/ios/AirMapsExplorer/AppDelegate.m index 6f006087f..a3b8f5bb9 100644 --- a/example/ios/AirMapsExplorer/AppDelegate.m +++ b/example/ios/AirMapsExplorer/AppDelegate.m @@ -35,7 +35,7 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:( * on the same Wi-Fi network. */ - jsCodeLocation = [NSURL URLWithString:@"http://localhost:8081/index.ios.bundle?platform=ios&dev=true"]; + jsCodeLocation = [NSURL URLWithString:@"http://localhost:8081/example/index.bundle?platform=ios&dev=true"]; /** * OPTION 2 diff --git a/example/ios/AirMapsExplorer/Images.xcassets/AppIcon.appiconset/Contents.json b/example/ios/AirMapsExplorer/Images.xcassets/AppIcon.appiconset/Contents.json index 118c98f74..b8236c653 100644 --- a/example/ios/AirMapsExplorer/Images.xcassets/AppIcon.appiconset/Contents.json +++ b/example/ios/AirMapsExplorer/Images.xcassets/AppIcon.appiconset/Contents.json @@ -1,5 +1,15 @@ { "images" : [ + { + "idiom" : "iphone", + "size" : "20x20", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "20x20", + "scale" : "3x" + }, { "idiom" : "iphone", "size" : "29x29", diff --git a/example/ios/Gemfile b/example/ios/Gemfile deleted file mode 100644 index b9ec3be2d..000000000 --- a/example/ios/Gemfile +++ /dev/null @@ -1,2 +0,0 @@ -source 'https://rubygems.org' -gem 'cocoapods', '~>1.1.1' diff --git a/example/ios/Podfile b/example/ios/Podfile index 80b14bdc1..ec73199a4 100644 --- a/example/ios/Podfile +++ b/example/ios/Podfile @@ -5,7 +5,9 @@ platform :ios, '8.0' # Change 'AirMapsExplorer' to match the target in your Xcode project. target 'AirMapsExplorer' do - pod 'React', path: '../node_modules/react-native', :subspecs => [ + + pod 'Yoga', :path => '../../node_modules/react-native/ReactCommon/yoga/Yoga.podspec' + pod 'React', path: '../../node_modules/react-native', :subspecs => [ 'Core', 'RCTActionSheet', 'RCTAnimation', @@ -20,8 +22,7 @@ target 'AirMapsExplorer' do ] pod 'GoogleMaps' # <~~ remove this line if you do not want to support GoogleMaps on iOS + pod 'react-native-maps', path: '../../' + pod 'react-native-google-maps', path: '../../' # <~~ if you need GoogleMaps support on iOS -# when not using frameworks we can do this instead of including the source files in our project (1/4): -# pod 'react-native-maps', path: '../../' -# pod 'react-native-google-maps', path: '../../' # <~~ if you need GoogleMaps support on iOS end diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index 5e689bb4a..60339f2b0 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -4,57 +4,76 @@ PODS: - GoogleMaps/Base (2.1.1) - GoogleMaps/Maps (2.1.1): - GoogleMaps/Base - - React/Core (0.40.0): + - React (0.42.3): + - React/Core (= 0.42.3) + - react-native-google-maps (0.13.1): + - GoogleMaps (= 2.1.1) + - React + - react-native-maps (0.13.1): + - React + - React/Core (0.42.3): - React/cxxreact - - React/yoga - - React/cxxreact (0.40.0): + - Yoga (= 0.42.3.React) + - React/cxxreact (0.42.3): - React/jschelpers - - React/jschelpers (0.40.0) - - React/RCTActionSheet (0.40.0): + - React/jschelpers (0.42.3) + - React/RCTActionSheet (0.42.3): - React/Core - - React/RCTAnimation (0.40.0): + - React/RCTAnimation (0.42.3): - React/Core - - React/RCTGeolocation (0.40.0): + - React/RCTGeolocation (0.42.3): - React/Core - - React/RCTImage (0.40.0): + - React/RCTImage (0.42.3): - React/Core - React/RCTNetwork - - React/RCTLinkingIOS (0.40.0): + - React/RCTLinkingIOS (0.42.3): - React/Core - - React/RCTNetwork (0.40.0): + - React/RCTNetwork (0.42.3): - React/Core - - React/RCTSettings (0.40.0): + - React/RCTSettings (0.42.3): - React/Core - - React/RCTText (0.40.0): + - React/RCTText (0.42.3): - React/Core - - React/RCTVibration (0.40.0): + - React/RCTVibration (0.42.3): - React/Core - - React/RCTWebSocket (0.40.0): + - React/RCTWebSocket (0.42.3): - React/Core - - React/yoga (0.40.0) + - Yoga (0.42.3.React) DEPENDENCIES: - GoogleMaps - - React/Core (from `../node_modules/react-native`) - - React/RCTActionSheet (from `../node_modules/react-native`) - - React/RCTAnimation (from `../node_modules/react-native`) - - React/RCTGeolocation (from `../node_modules/react-native`) - - React/RCTImage (from `../node_modules/react-native`) - - React/RCTLinkingIOS (from `../node_modules/react-native`) - - React/RCTNetwork (from `../node_modules/react-native`) - - React/RCTSettings (from `../node_modules/react-native`) - - React/RCTText (from `../node_modules/react-native`) - - React/RCTVibration (from `../node_modules/react-native`) - - React/RCTWebSocket (from `../node_modules/react-native`) + - react-native-google-maps (from `../../`) + - react-native-maps (from `../../`) + - React/Core (from `../../node_modules/react-native`) + - React/RCTActionSheet (from `../../node_modules/react-native`) + - React/RCTAnimation (from `../../node_modules/react-native`) + - React/RCTGeolocation (from `../../node_modules/react-native`) + - React/RCTImage (from `../../node_modules/react-native`) + - React/RCTLinkingIOS (from `../../node_modules/react-native`) + - React/RCTNetwork (from `../../node_modules/react-native`) + - React/RCTSettings (from `../../node_modules/react-native`) + - React/RCTText (from `../../node_modules/react-native`) + - React/RCTVibration (from `../../node_modules/react-native`) + - React/RCTWebSocket (from `../../node_modules/react-native`) + - Yoga (from `../../node_modules/react-native/ReactCommon/yoga/Yoga.podspec`) EXTERNAL SOURCES: React: - :path: "../node_modules/react-native" + :path: "../../node_modules/react-native" + react-native-google-maps: + :path: "../../" + react-native-maps: + :path: "../../" + Yoga: + :path: "../../node_modules/react-native/ReactCommon/yoga/Yoga.podspec" SPEC CHECKSUMS: GoogleMaps: a5b5bbe47734e2443bde781a6aa64e69fdb6d785 - React: 6dfb2f72edb1d74a800127ae157af038646673ce + React: 35e039680feacd0563677d49ba410112d2748559 + react-native-google-maps: b2668747ec289759993dc2411a7078afafa8adea + react-native-maps: 326ddbaaea8f6044b1817fb028c40950c71cc38a + Yoga: 86ce777665c8259b94ef8dbea76b84634237f4ea -PODFILE CHECKSUM: ffbc20bd08f662256d501d07a70e77862684f702 +PODFILE CHECKSUM: 206f5482deac191368c01dd654d14fbd3e5d6b8f -COCOAPODS: 1.1.1 +COCOAPODS: 1.2.0 diff --git a/example/ios/bundler b/example/ios/bundler new file mode 100755 index 000000000..905387619 --- /dev/null +++ b/example/ios/bundler @@ -0,0 +1,17 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true +# +# This file was generated by Bundler. +# +# The application 'bundler' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +require "pathname" +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../../Gemfile", + Pathname.new(__FILE__).realpath) + +require "rubygems" +require "bundler/setup" + +load Gem.bin_path("bundler", "bundler") diff --git a/example/ios/fuzzy_match b/example/ios/fuzzy_match new file mode 100755 index 000000000..f71547393 --- /dev/null +++ b/example/ios/fuzzy_match @@ -0,0 +1,17 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true +# +# This file was generated by Bundler. +# +# The application 'fuzzy_match' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +require "pathname" +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../../Gemfile", + Pathname.new(__FILE__).realpath) + +require "rubygems" +require "bundler/setup" + +load Gem.bin_path("fuzzy_match", "fuzzy_match") diff --git a/example/ios/pod b/example/ios/pod new file mode 100755 index 000000000..3c4a4d04c --- /dev/null +++ b/example/ios/pod @@ -0,0 +1,17 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true +# +# This file was generated by Bundler. +# +# The application 'pod' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +require "pathname" +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../../Gemfile", + Pathname.new(__FILE__).realpath) + +require "rubygems" +require "bundler/setup" + +load Gem.bin_path("cocoapods", "pod") diff --git a/example/package.json b/example/package.json deleted file mode 100644 index 378bd5578..000000000 --- a/example/package.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "name": "AirMapsExplorer", - "version": "0.0.1", - "private": true, - "scripts": { - "start": "react-native start", - "watch": "node ./scripts/watch-and-copy-src.js", - "packager": "sh ./node_modules/react-native/packager/packager.sh --root ./node_modules/react-native-maps", - "dev": "concurrently 'npm run watch' 'npm run packager'" - }, - "dependencies": { - "lodash": "^4.17.2", - "react": "~15.4.1", - "react-native": "^0.40.0", - "react-native-maps": "file:../" - }, - "devDependencies": { - "concurrently": "^2.2.0", - "fs-extra": "^0.30.0", - "minimatch": "^3.0.2", - "node-watch": "^0.4.0", - "rimraf": "^2.5.4" - } -} diff --git a/example/scripts/.eslintrc b/example/scripts/.eslintrc deleted file mode 100644 index 3c1eaf35a..000000000 --- a/example/scripts/.eslintrc +++ /dev/null @@ -1,6 +0,0 @@ -{ - "rules": { - // Scripts can import things in devDependencies - "import/no-extraneous-dependencies": [2, {"devDependencies": true}] - } -} diff --git a/example/scripts/watch-and-copy-src.js b/example/scripts/watch-and-copy-src.js deleted file mode 100644 index ed8684894..000000000 --- a/example/scripts/watch-and-copy-src.js +++ /dev/null @@ -1,51 +0,0 @@ -const path = require('path'); -const fs = require('fs-extra'); -const watch = require('node-watch'); -const rimraf = require('rimraf'); -const minimatch = require('minimatch'); - -function copyAndWatch(source, destination, fileGlob) { - console.log(`Cleaning "${destination}"`); - rimraf(destination, () => { - console.log(`Copying "${source}" to "${destination}"`); - fs.copy(source, destination, (err) => { - if (err) console.error(err); - }); - - console.log(`Watching "${source}"`); - watch(source, (filename) => { - const localPath = filename.split(source).pop(); - if (matchesFile(localPath, fileGlob)) { - const destinationPath = `${destination}${localPath}`; - console.log(`Copying "${filename}" to "${destinationPath}"`); - fs.copy(filename, destinationPath, (err) => { - if (err) console.error(err); - }); - } - }); - }); -} - -function matchesFile(filename, fileGlob) { - if (fileGlob == null) return true; - return minimatch(path.basename(filename), fileGlob); -} - -// JavaScript -copyAndWatch( - '../components', - 'node_modules/react-native-maps/components' -); - -// Android -copyAndWatch( - '../android', - 'node_modules/react-native-maps/android' -); - -// iOS -copyAndWatch( - '../ios', - 'node_modules/react-native-maps/ios', - '{*.m,*.h,*.swift}' -); diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..4f308ee0403a6fade6ba2b25249725652ed80a33 GIT binary patch literal 54208 zcmaI7W3XjgkTrT(b!^+VZQHhOvyN@swr$(CZTqW^?*97Se)qi=aD0)rp{0Dyr3KzI>K0Q|jx{^R!d0{?5$!b<$q;xZz%zyNapa9sZMd*c1;p!C=N zhX0SFG{20vh_Ip(jkL&v^yGw;BsI+(v?Mjf^yEx~0^K6x?$P}u^{Dui^c1By6(GcU zuu<}1p$2&?Dsk~)p}}Z>6UGJlgTtKz;Q!-+U!MPbGmyUzv~@83$4mWhAISgmF?G;4 zvNHbvbw&KAtE+>)ot?46|0`tuI|Oh93;-bUuRqzphp7H%sIZ%{p|g{%1C61TzN2H3 zYM3YD3j9x19F@B|)F@gleHZ|+Ks>!`YdjLB;^w;?HKxVFu)3tBXILe21@bPFxqwIE znf7`kewVDrNTc3dD>!$a^vws)PpnUtdq<^;LEhuT$;)?hVxq?Fxhdi{Y)ru*}G{?0XIuDTgbgDhU{TZBc@$+^ay*JK-Y1#a7SpO zHyWJnsR7T|T~Bv6T*n>U;oojNGn}}GOCkMk$tSQ6w{djY2X8sv z`d;xTvUj&RwNbF9%Uq2O~P)32M5LhEvu)YifH{1z#~{bWNWb@jLMh zVUJV2#fMpMrGIr%9Y7o#C)zVd+KQX8Z)V`&oL^y}Ut?pT;i8{o%0fdIdjtoI5(~Y{ zl$R_`XQt0k0VLP&_!>>&wg55P~iFB}0=c!p}&pO(~&fo}p9!sAW37Mf!kAsUZ4@ zwYFm>c`ib_KqQ|-f1mK47)b3M%)Z2KT)vjM>^`gn=~VsD%Iyl77GI{(9#eGF0Ao6S(TAGLd+S<_FpyMWx={C_7^bT$Bbrg{4Bex-6CxC+|3- zq-eUnX4He-g``+N04TM@rr|3$bFmDJz_Oxtgj-HMLL}x?xt0LJZOW+8cgLnDeSviP z+~H_$+_wl(UWUCKktl{p{0p7l8GOP((+bpm>KqIG{0Nc^gP2jVEgeGC1)41Qmf$GA ztV|uyJTjG?BbIT|YCPeWKDTUGMHyo??xB-yw_N?@6)--PTy6=|ge97~FsHIA6+Zlj z?>&AY_|8}uVjW^javZJ#ZHh9@$;1T%RK%qs3oX3Q{|U=4C0pAP;TvE&B?eaxJ+_g}vtIrE=zaCbk^9am`Fyhw!*X zf(5y2gXmQUWg)$8X>C~+g}k_F8P+fni0nq}RN_pq`P0P^!I*Mp(gK0|RlKIWBA6z+ zZvXp_Hp8KRiwNMwLun?;)l})q>G{HkK^3t@znN?AGnI5!^ogl;>Cq#F|Orith$uD5^dob0h8vyOzOu2MKJUyq{(MIx-^e>y#K0oqJug- znT^aGBM&`u6gvDu6;_!pIhv`i?^JJ3pDprdv}(_9;+=Ub<&Vj_z7nL#{lzISdygW$ zS;Mm_eAx{{ZeO`u(NFR~UdmTUQehNB{7>b+o!b|<@4Vfd*OWj(U=bxEug6FmX;Iuc zldB0@l*UM&GRw8n>=)-VlXN+q$~%nY>?zH2by=_U&1$aGwXNL`A>|})<{n{soC{$f z6i{}Rq~K;U@!0~l0*!C)-VOGv&L>;)DIe{~MOx}*9-Ilor5hAU<|QurOl76NzoN3V zFz=oQ*mRGk@zvH6bG=PAVuhP#vQ)|NqkokQjR$y!VE`vqM(9pk6O3%eF#5L)yu2A+ zs*{Pv!F6}w4%j=vsHRJRBQFSruEA8b+xm116n3s9l*X^2CIqvWhj3h>YKD7;Vodb*~~wfg>xvIfk;u|-e5I|v(RV` zfVcu;xAAxGfjJ}RpiGe>hrN<&TjLbp$?XY{pD8hDB;3DtAmV zOU8|p1xwqShBr-NT}{v1+|S!xNU5h>%WD}IS5wdewOiX8W;fOdo*A_H&U|h?L(e>Y z+pdZ5JuYFFG5hLVA*lzhsL6A!QJrgiynro+pe}MwuJMaD?c>~oZ86oJv^p`~seL|~ z1ArVq0QgvgpqnwMr|XIY4uJWp1|TCsL??Ec(|na|KJjYy28(mJ+-pqtRmNvp*i%Bn>YoSNj+$8+o{rJE{3LOmHi-8jE|VJk_ot%f8pC+4sRyV(3# zW3O2ekaOSg_hUNR7YtwtYU4(m-K}~6*>ToXhNBN4SJ^3&JH}VFGf2J)odBc@>*Gl- zu!@kC8GN(Z%CmDFt?t)BFVTrrZ!TnsPU=#=U$g_cdL4gn$zU5h5vGgRrg@pWEHx`Y z|LMgbYmX`<5rDTUZj18LN6hc9Y_ch?Mvg14mUt;M@RzemPs;Q4n8`|C<7dRgZGJHI zwVvX>w5PjdBjX<^bnISW$31*#3Mt_V3Ao-Pm*S)!i<{%`o-C~T>iy;u%@3-6-z`da z;}xiz)MqEgBfPGcZ39Q~i%t-b3?ye+s zkV{&6m%A-gUR^>9Cg;E*M8+;83~U?~k$A^f&yHwE4pT*`ItMWs>*JDDl0*7UOs3rb z{N%7rt%axd2NKO377KmHN-?%orIejNHen&@RYXd9e{|0?3Z@QR&K_88nhI*wn zl_95|n6VThK4AIQu(kAlGG#LYNFwEsi~vd_%0*~WeMfzssz;mj4JG${`-^wNa@^*u z?1Se|Y4gsSwq$N7$s7O8lxI5YL)Oh?M$6Cl%*79o9n4SU9#^DbV)ckzuSjG(`2aL} zwyJ#Mm9)AVg#`Ve-l&XvA!>fDv5SG+-nff!a0Z3VkR6sLz14*8$!#4O56%GT?HC$Q z5UTKdWBAPI=Ng*Kfg^*L&X6^-Zs>jlJ<+WKk}kp#?ZhoI{iAYRH_Fh8@wW)lPUOBO zy%**V{0Xh--4K$N^hncGQ@CX^6{yB?J(OpDDQEN^8Jn}a zkClUmg|oT7h0oKtm5qh7zC918qdLFWd$5n<43cw2ta>hB1zq{>t``4oEHts?wEyHs=F{&{>VYY$DN|T5^;50-h$n*X8tDV$ zVr~9Nk&!g~n6K}EH8Uk&F@*5|$fEErn^6)H8!_VPoN7$moX&?~o% z!6kGR_z~thhh53cpJ1*`T)(qa+tG*IhNzCAH3wpZPe@O&rOclYvKv_ z$Hytrd^BA-$jHy+Y|Qan157h8Y#;?EzO(dW?&*I);tr@ysC4#JwcOXX^jUhA$=kjE zJfioI8g;!`WvNYLW4-xBl{dVBfX8L;w$#Wu$YH1zDokI{a0e!=41*dG;R1vbHGEHp z88sW%D^$I^8JgM;&}_x0%tdqs#BdypVQMz43>ih(iH+fx)VuUpW=ol9ek9@GA_dT18;t9-Mb&B2VurL628tpA$#ZPxIjlxWVD(7rsfn(hajk_}%sP9xNhl zrJ{)y=?ZENjKlW>@fHaLx`TaX7bSGN=!p~g5#y22p|5_@a+hV=mdqo3 zCuyRIO;)UZ1<=N0Ml8GsSAZ+d8gPqO2u%0N1Y#K13SxsT46W@7M`X^-G#AdceVFsls%T{Z^LV&`j4|WDsRZ{7y557 z5BiXpTcO`?X(K>&nMIwU#I)&g9PjW{o~Ij!#IUhElGfxc)lQ#Q$iOjA+x%=@2{t!X z`&-aD`#Mar42lblnS=)o**}54&DVL5xKCWAi)ww!HKT85aIf`c)Gi*QBZ6)C;(fhE zJRDf-=;x5!szU?NF{J3|Xp*V+W|4&ns|StSqY|=Pmay6SSXTCIe#$ilOgaR2wCa1V z;=4b@*@z+}3wK7y0X2B(?GepcPFzP-97U%GXP$aA!LCHq{9S{hYNR@IM%Stzp4(;u z?@Sj@=pNq5>}tl&r=HbUM%ZUW%l=T6o+l5Jxk}i&A}ZJ&<3In4q%mB*PPhMCE8(C3 z02u$hRtmcrS~)wKyBLd@TN(2k8X7w~O6%L`oBmJX)O5r&Mfc%RpI^Ut!nfI1VXsc$ zBPMN*M-hvYE-e`556f(=GdOQ%(w5Y{j8g3|Xp%6%LxM18Pga!NfJ@yA)}fo6MK33E z3$_Dg)Ec;jY`uhLowVb3>(*YoBfnl`{EoiabKiM++g{rFei`8fWDD0lbHgfv@j^gd zq^sJC;MjMQ8HkJ~lCXH_)aaUxMqT&*6*^pP62#?kg%POWZPqiHB zjK-Gm`fY`sQkQFkg{|Crb(`3w!P&hDj_ZsKh`~|4YXNj#b27M))fy}etvh$C46TcJ zN}WBC)5fMlmfgwbtnbx%o5`npSMNMD&XLTSk_F+lk%b9=I__!1UAw8b?tr0?OITYm zZwZ3v3@8tGTJ0XKXa{_zTZiSGiq)je$wm_^h6<5p?&r2$Ay-#o)^TrDz(M&H&wL?v zG()L5-FUQNvBMGh`+=p(C?cCTCF`LooUlRFyFw+w=lQUyexY`Lp-*=GxT%AC59vYJ&WHijkfN>?*}Xx%{_#wN<6Q3-=x z#yg8RzNweQR4j?ybGpetSoSMyPQk`7KgPFGL0E0 zg|d`R9ScEK^)03o*8-GQ-qY{-RbB`#JXlx*w?%|i?OFj27IiqI6cxuB)g`4fznbzQ z=t66!^#15RjJ#FZ2tt?};n9t1Lvg$-&Fr?zHbGC@Z$lGK+=00=CYmemy!LIt1$6N6 zS=qh(HuL0F;=w2%Vu!KYjDf-8V};oV&rXfQ$Q~@o#|6*Bgs)C4KwHTfHYF2gt%E=~ z1sYV844uKUAgBvGoU}I6YG$3AD{(Z-e_)Ah5bT^9QoJK+x7jaE@7NJ8N%yod&;##c zq~7YbR?2tUslO(C5u(9&5D%{RzJ(3ls*N@$ScyA-r5s*V?|D9^#?tJMPRr~5-f&|| z5hG4_qe_t?&JYXofBA`%*zTKF@&}e~+-eQbzS;U|V4!bYf3kU3qDfy}Xi2#cwA91u zj_?Lz=NH$77i>?Pf1aOj}Wer%O5^pQg2XI&tg@}X|aQ9xmEwfVE_C@_)0A@ zSGbHYe0oR3Gf4i43Hljw_0hu?@Ie-iHVqD)AY?D`Sb*oU*SI=y?DNMJeH**aXfzIW zEEVH=en4^dv`L(oJv;9AMCYDGAdYbBJ63c8>xcQn1DBAQA>FTxCXeW`yB zVT|dk=M&LV6!Mh4MYhG<2jZ*1=nl}&+nl-lSJ*9#SxOy z?b$iv;=He)Bb670FaOG}HWrc_?A`tcSF~bngbktNmslVzr3`Y`*o^@}`<;VXcMii= z=FGm2$Z2w-t{?Y9bN!c3eTM3yvIysmd zI6Il!+WZ&kub?T3$&d6sZL+oGRAJxLysp{k9%^~9zOO0Cj{t(-7=(iBMJ5%GFVnsT zogf|YBhe>!o5$OWtIWk1JYNduwVLMmLF2eO(Szy>&^c7WKB-p)1}iK5IEgjm-T5d_ z@@maI8l#j$w{sevL!hGGS%dKAvsq3leS2@nTzUz|f{}JTh)um77U^p~cO!}I3;%Yv zt%v71C1f$|j;mCD9~0Ph{&*)oH)iz^ySrT9Ohm<`M8ON~DP7hB{tKaBWEo*BZ+86f zAm1_)0mZsz`nkyh#xbcVa2HRysG8Wn$lb`bylI>o!AEm7?(K)TBU{1w;rKe7YebV7 zom96W&t~j`C=+gtr4>M!3k*(=yBEs@_%-#Zj^EAIH|BC!LtJP*jF+{eJ_!**xncaC ziKX%(XYY!$@Wo1Avwzn^ zPfE}$xxI4jvV^r|P&w5rGW2kuo|IImxq`L9 zyCnpoTEiCp0N#LriHe0Nio6-=zo=rPncSuGj1@+m5CtzTfZ9zJI4YTL!-s_C|powj7a%txF*KQ(sgv@^^Fq6{h218-K34C$?^mfUa*|L-w z?9l+DEk8JVrcj#Pj>?DOyTZivZ6|Rr!O?m%`kW(CV35Nos1;(Ij2fs}S#FWLOpe-i z2&lK72Yv1-iGGA`i6|fz7<$NsAX}|3worY-PRsm!L(~& zF%V64k%>!j>#dHjkdkS<=~pPQVH&tG1iZ$Sot>eD&DJj;mzN`v!q<7}_YB8o%^CEV zRJ$5ar>Yh74Ew$1ho)*4iZ%#w#!z+PQCZ;<-UnrZ%{LB*^u@G_RWK6t4k6dm8^vOi zs*+pOUb+hHwACR}wc4+6@b6R7U=4h8DPJ!LwOy8C`H^d3rg%!QFf8|*SdK-48Bz~x z_C4vZpU3(Fr;N2963h1zueM5{oDJIkGr^2JCU@fhCKvZ#p_T666HL+F(aG5QZ+89F zBc05R9mVu*{)(CZMKMLGXew$dBYm@ov*BZncQJ`+7B&THD$t4%H&P%GAp;SE73rMg zXOe^jJMNE(1KK{lYv^K`o(I^%OtVcdrqGQ>dcTO4?Z^-uE{_}4Kd)PQdtNp5G_A;d zzkkH=0(OSldY=vz`jg|H)13`COHroY^$|wdzUAtv$Pg%W%Cpmm z)sYQJ<0?^!yH&zZxRt}qerk7WQqzHlUubrT5*JxYd21*th(^py+7g5K zbrD{*0kGDNd<3{(b%~OONM{9sUm=9xuuYA;gWvVRU`lB}I20DBI`T_i#p*B& zt;lg`Zmz#JGVTE)a?U;@a?XKYIPGnbe~pq?lr6|F*=+?N>ZBAkKI)<&wlT8D8H{m*1(^qX#M5Zs~^uY9_HY(sgHR5yrRiBe_-U6uCrAQc64e zU@d95dqi)+O9UxR6|!e00zhixU>_U_+A~NiuD=MF)g6cr z!)U%>KSa}*le&IsOYJ&Fg#|t$))2q~6`k4T z8N6{9<2Cl)J{A3=Kn+0mhd&w`t)EU_i>f;yLu|K2aIxxYfSENl;6v0c7zejsQ1I&$ zKapAFStLZ%!EAS><+t-DHFD3#7>-9lh};UyoX}%g^D&kNT0V0~bDVc0FZy)e0YDbe zTpVyFid*1?Qai}-mX9lp>G~(T6L0_R++iD*$1t}KY*WrG`{B!>w&@vnFFUHr%Qrik z2Ndetsc3B2Z+mv$cluy^rg=hGTw%^5bvJvMsl&P?sP{2lT=k0+)6hl`_Go!bQfhsK zhH&`RMjpHZSoEjg-}-N$HM^>j$KqNBjXX{W$cHrgk8rMO>w->*YoZ?3o#83B4CG68 z0hFR=#7&LS_K*9fT78yOLAX1PD|C`{@>DW?u1V`nUVyqK&muaW54!){-?A#uUKjt8 z0W7fp-x7h1qm#as6%qY^f~Ks$)B}<#x{vHL!-UBnI1M{ZvpJDfDrm?&IdDG+aBIO7 zK1=}+L+5%3#c_47lN5t(D z72Y$f_o_$49UxP>fnm>nhbChvPEC(QJu?vbQv>ei8-c~VLV#=Y`{ zyiB$E@}}T@gQ+3)3)RM`Mvv2u#x|MAM14TDE$H1Qpb|Hm!}yqZzMj6~6wPO-V8uHE zIekC2?=Ac!EjkC=;2T7&qt?)7Xd**j;!$I{B@_eFvv+L6ChdsF=zW1kb7;khE2icG zt=A^&t4Mdm1^s#e2Ak8qC;CM%C7RzWpgUdg?3DyZNo_--;0t+zCN(=c!i|5V<83q^$>9^jYxY_Y&AT@s7w(?6IR>jTJ}ovoqtf{CONXPfB(nIXG?*K zv_iwOtk!4D0KsU$D4Pqyb(0OI@0fex7C4;p(qcnoo#l_Pt_~43wx0XkV+$o%oBK$WL#QLM z{dERKhszLa4B9snqT%6#Nt(7B<%ivM@`q)HHIsw0DW+*ucY*i}`U@3H|6~92=7tBu z5M;kZgP%)AuC?wk$9glV>NGV<8%mZj~TT znW@zaG*6L;2x8FNNQb6Edo7bcCI54Lov1d>C-or0_@ch;&rYpoBx()nqXl>;zJpHs26q$+#~UgR2JePYBZWD2A;z** zDuXm7FO<7UWwRQ&24Gmb$OW9pADw8A+fMioI;ggQJF$F}E?2IgR5w*xUD18FV+f9N zH5cr$1Jyb7>PL!X*P30qq4A2&FFA}dgC*h09WCJ(;mSO|FgmX~511Bh80rq)KPX*+ zW=60pbL^Wu?bie{wCJW&UYUMo6dFV8;CDPBu8T??ib|&y`!E#B_NK26S*^0dHTvEl zWoD;W)nOc!?3>(hokwq6aFRpSds*SA(cJfsG(oJfXrV12Z6W*$_SeKhijaxnGkK=_ z^S(MY?$OG3*Ax}~Zl8BY#VD-i=^~Naqd{5p!SB2tCLzg zoN?jWFst}W-dL9G&xF!4R|Gi@M)O4ON_Zi~WBDhCI3h6G`bj&5Lpyc2KfQ3@LHbQN zzZXe#BpBS(p!agicj27@Llz&CJ-}mrRi+Ixyt@Oy(#s?!XWY@{?7xz#Gx-M? z!MH0PC~0tqiN31nD_|3)3m&TSUyYEZ;piW>*riHEGYnIB+>~4yGV28245RIl5z9*q zcRa`CjR*w)(v7QSO)ks7xkq@6Udo;9*kgk~?SUN$cmvtS?aUbboeFX5t2{Kr^!h>j z&zgASp^dSPfDuA+VKzL(TuAN5~HWY?N7u* z;U*hv^(l9EA`U{76b7`C?6n7yqi?At*$EDJjEc3k{r*x*u%irpX>Hr^a?hc4^_MfQ zB&5Vg1vwb$j1(jjTZMyTD?m@@ChbLys)B$^Fo^~~l`;RNNrSqQ<}9tf5{4j=rmn23 zOdYjjDKxh|D*g(+)_n30#e; zrlB&+&Yg&THMR9hn%4bm%49}r(thGWQ@z>TvRFPoSDySnJx;RBn6RUd>i48wBf0F< z=uqdel4w(9fstNSPz_@MT7Ui@m?#*Bb*jHnyJkTf$TZW`WNiNOpp1BkA3CudfD+uI zecGD|xs+u6v3eA%gTEoDy0HKO8<7+3b^Cy=;ORU>>{~4CyMoz#`r01UkgN^_!?R1W z^_Y!i`$S*W_-1I{#^1He0|RA|yuxQnqjfOi+tm#^!60}>N>LrCc^ARko2Lgp1o~25 zCHe%tr2lNS7I(E4A0W1nQ6>l4B6&sJoFZR(=#XPJs~B-6A<^Y9O?c24q`C-|yy!KA zcJ&d^G>4ipI-G4v2r+Uw$P_S`T^QToGw`Tj#8AHC@ZQe)AklsEdPb+4veveTem1*% z2kG$1GO6tRj%bJ?)~XaQ)*wapnxEG1D@G6%kNRS{&(GNf%2e^dC zBi=B5tzIw{_&#f(iO_+9o>LLEi0m8^`Xjt?LkxQXgkEe3!Az?dg0O=}O%WnX($gPh zfhp_kK}#a%@?^-A7mmAayl}C^1*4#Dyrx8zF~dL46SDNFX;4=c2EL$sMP;Ur-HQ8v z+)hm+rJzGe-F{J^L135e?h=CZf9v9g_tXA-KOluL4Sa$;P^+&Gh7H7^I?c!K@CXa)ja&8#UC-etu4?M+p4Do7U+ zo1ps5jBU-`Oy^`771U@XfkDpUl%x>U?iWJZk|Vyp6_Ee}4s;^zQ7GGzvSOSVEB$0X z?Me)`U=O^pPUvvlUM0AJvjk8AB51#GL!t(tovE?C|CfAPBlWB&dQU!$}YoI8d9Rx zK5L8CKckM5!?+(4TIzzLgi*@*qYfNAY~b~wNM4)bJ!!EGIEG?UGN!OJkXs_<r2(QEvMBbQX}G>ErdB+ZtJRo;yuUZJpc_U$E!yQ21mXP!KAU^ChICNq zE0XyLwJdHj#vu^s!>8~KPLkq-cb`-V#v)ctC~?nVuu38U&pvbC8J7H;OIpr6YgGVW zuNx{={f(0#C+;)Y%sY6Mp%nz&c)o__PlKafvP?6#9Xu!Ct1`g!+ioIkbWchTRUTzv zw+#LV)&R1^b-@InMgfiC*NGsmo*^M2H7{BmQ;HXw>SBJr{DGye$_G{x}_3CIE#f~E!)cd{c zssrB)IXbxM%zqYPeUI~zerpUsVr-l0F;}CR^?gA9rQ8!oaN`F;oV^BnMepd@y*7JE zZ^eOg`b&;((?~4dDx+u6U%9$-|IP<=8{vi1{?7Y`5_R?(>Q%jC{q>EayAT&2(UTz1 zP2<{Ky@xp;Xgj_q%>LPh)lD2?JF&;<@LJ7ufa~;G;D_%eJM!ZE$u|HCeL1Aa@h#5t zqaObmk@-~taP{ zmP;ehKFgGMkw4aJuYYO~L?bnhOlclwwmd|k-FRxyMAP4{RuIwDu0{&lXkpMr!eT~1 z0079CJ+*G5JABWzfe04UK0Wj%=ZOFfHg&TVY5ae+H_dUafCDm~r7 zI;K6tQatQE@#^i&O5DYfnzrtuC$--3K6a8ig5yAa$E86fc=&K@5}_=>$a31V+0$&8 z#yz!G_PC^^h!j)iWj@==$7V9Qxn{g=I+CesW=t|KGR83R{LtHPxt^ZToj2trtiyUr z-s2Cz+$uD)2D*YeCowg#uweSh#rWr)6?4b2`oeQ-2FhwDNE^1~+}_iC`l^^_s9w!c zk)mW*T>;JOgmt_Pox%|_HW_}nX$ki6T;b7Lht1hcu@ckP>fiGu=b$bVkyof`oA?_! z&Y>s66dWtr({h@wcae|9RiUWnP5bjz(iw4Mjz;l3iJmRdtzXF*;*#ag%1TGIYDAmb z!f5gI1f&-gY)WZpO1}@)r!K{g7?W*dQuJG^yIC!6D)lDHjaD2J-TLg^lkB3{kllbR zH_j#K4z~ldvf_`-h3(}jU@9m@ll=GGhSui~-Ig*!HW#Uah%-Ag>W!OgE2&BBrN-&) zX^*9i=u8P9M}%ZxQ0Zj{O}u$gC&n(5pDhd$$gBGZf$A!hf-#d*RLkL3EDRdRn?p-U zn$!0=?7PTq;5MYV{(MM(lK4y@v4&q!QAD)ORv^q}mrs))D>!ef;))|%JFMn~xhOh? z${^N^*k-s<;+#Acy=g<(N;{z=Wk}18i(R!pef{euv#k7*BBOcCZ`R&NL(G8mF0`?WHAR3J4z*$uD&Vs zF-TS@;A<#rO)I-FjYJ?{6!fW2H5W-N7hCJRu+XkIPi>TZUzMh(8z>ZtIV3R*Dkz*V z>9BV{TQFOZ2C0%78}M9cqE=|hWB-20wryak(i5wHmXGGG*+x)R&fRXTGRBr%mmg^O z8hCC@nz;q7D?1NT6f7}HT_TQqBdw~{nnzlpj<8LUXh2HuFr~QiC>Q1&dVR)z22f5+ z`ZjakxF?~WSLxX)TUFRMO@@!O(p6@xvkwbTHz{rU1}BWyi(Gp-UISFQ-O?%fDBbyF zL5wS(4ks>yh+j{(l+Ln#wy!=146rWobRD$R@-=97Ym5(466kKN_AWwoCHFC2k5Ju) zUdq}jtpu5vDqS!3QKlJHuDOYieoNZ{cWTozDZ4MWIPO-TkQUQxAnz!SVlON`S^=n1 z*PPj6I`PkVM%Tm84;v{0jQWJy_n|m&tB1wE3|p+ER@6H9EIoJ|S|hWJf#`NKw|<*+ z&1yJs*F@n@69=wlW-NIx*qk{!JL0_i!OiFt56x9Ww*_A=N>)6UTA5k;NY-(#$9|l! z#c-E>O3u%*>=&}WrX03ZMx|i1L050%*H(S`b2>qxsL*irL+2u2_qb}X;O&W>y)fZc zUPNVi!1`IqxSuhd?Ru@RcUcv1bH)+7V);oN+x5`>S!i43D)-~CjO{vopQ4oqqu^XEm*20FDU1b#;=dYdK554TnG0xMJ)>N8!>{IY zni*o8P@T>GWJNI5WykKJ^;QUd+m`1InBR4P&eZ726EOT-Z3?%maw|?eb=^3|&l^%AT_0=4K-|c&-N^h`O?jJE(yQk;m zms4(!1sg(y$Wu@&scQ=hH$)K{eMP_(E`Mj)z4hB;pk^%*CiLz0KNs1S%*)K&MprBv zQBAEr)n`w(g_k9BaN8=qQKU=7T^pz2r%@N_5Uby-vN)n3xCLJw`@fh(ZfUSa8qf-c z@x3xVbN04T+g_Bfy%TU!XeRYRpSl5iB7dV-u`X2W>UWwiy8eRQLw0%r5xJ|FOdvVu z71plt$JbVMd5+jKK?k$WB#R&z2a9_P|ko=t69ab}>GjRiRC) zHQ)*xvemft;tPxmy}K!(9b)x~EZk;On$;!vMQeEb5Xhtd17dY&yXgY^zJK9r<27@M!LsJkn7P0(H@pS`nap9Cz7WhG^0OLk3L5nK`knIwlcb60>(; ziXm@jV{}|pcMsf(m9Nv|Bu}?9dXbPqF46VhN}b$)&psq%@9>3--g$!LWi;KrutVCJ z0)O+dUt#G}UvrCz_JI42s{6a&iDr%gJ=&pfhae|<+0q;QpxLU_jo!Q}Y@Jgw46e&C^DaRD``Hf$5s}}NgM^4bG(WOwnL8F zcZ>c87Ib4Vm*k078x>~sCx(weoR%~`PmC^Zkswb<;YN%|Qy>egv3ihr^J_4^)|-0D z1N+c-H!uwk{+D6ms_a8doA))K{EfNjPY!#PsdT##$5K~&o#3wq$%;Q5Pz|3)Me+j4=#tiuF8JDVu zL?OH2o;zUr)B&*8xG`Y)fx}y6Y_URmxmWcuM$pNJyI((~@o+xC)WOhv&)|&YQJd5t zx8m?LgdF|KyL%g#>fzm5CqwVaZ5v?c5_u;D-$XB@;nO^m*a8`n3S`j3XQzlqIueiW z-pp&;+KgpU0WsgnJ%{=7?^mGhTszA@%eQX4wuvVs=H)=0X)R=4dHvQ5=6}DwYX)e# z6^5{dm8-b5-i!F^6y%|aE0)lw=Cj_cwiEr+Y~PVH;IsU-Nq+BgWY3D3zf|P2O+FI} zhN#Sjk}IQzAkCHI`O07}6@&=5J{C2v#z0?oOB3V?yh!MHut^H}E<85@{Hfk8z*7_3 zLODdLO6G-(NM9yhmuj;t+9)I-O9zUHp}JyivE5pbSLS>WT&$eI!ct|qR@ZHFfKl9k zEZL;3AuSZ)yws>s41b|9%~Z{UBdMk_xn3z8KYL_BqD!>BRFomLka1w5DxFdmMCc)1 zQ}*WV&B-+q^foIUjO^|rfO0AZ|{X3%g%o{t- zsDHJnhK0aGTQnqFta8a9omw*rGidmL27rABg3v^bGL44j3#5xjJpnO7yE$!46BqVE z3Nbw@bvr(?`QlgvI$+<=Ed*t)GA-DvgriHP1#o7{?ue>8ObE|AcVLlO(v}VZWkJ0f z!^%F}&a7lEiHUh4bR;>2U50g^*#OaASoE1qaZNnIUqru_HR`$0%a(yq>Hzzmeye<~ zF%MiZyuPH-#S$`w%34|^jYLG~DY%k9sD|J5;nb#hh_vy3lfI%?9ex@*I1S!H&2-76 zd+9XJb`^nb&eKR;U~i_68tqa{L~onQ?<6t0P~jMbJKLr!CJg$Mxi2A$x!|1kDW zQJQthzIRsIwr$(4v~AmVR%WGb+qNog+qP}<#?^q47}~AMXi&C`()sm#Ybsc~_IhTYnNR+VvBI)uvlWik#~q%MF$hQK>jbXkDKys1)#IMY8yRh{!JQ%TNuy2b6()&oc!C-Zr}GhI zLuPX3_nc*2>V|{LT{k*+01BIOi7d1d-9Kd*JD+;)ZDLAV#3y4J4I!prCyWOowwo1R zG=6}xOfO`s7?a5X*A{a5+@&6ktTj@aGO|9nb=sxE9peF+fxx-R`mDh2SJFOBOJ6T^ zr~$Qfw_z^WQHnGXCJrtUE{EYGgqPY)Fve# zPud^{Udiq(xbjmrZ7~mNj#J-8d`^S9p-d)ladBrr(&z?+toB*y&O&A@PoGvYaO_sm z#nq*uK%9ol*xJ~>JaZDKzr56afl<2f=-54RvskyBnctuCBjQ)ptl~FkU}=`G#0kb* zrZD&fA@T9LQO`>PrHC3Za%%2@@}lSrd9(7?`Q1IS`iKY8M}W7pI+Z_$%*65#7 zFRt%~gIygaa*fFSIMg7n@GeG*9JDS>|Tl1F&Q3bHKiEHe$mhgaxLRw3E0y zt3bh(KtVGdaRVK4>?NdJwROnc_XcJn)LDa%6cdB`NJ+qQSe7D}%@`CoXTtE{dtR&A z*w1Od@%B%PdGx;brAFN_n?$_*4}%&YN}up225Y`5c#2JknvmeUY#G2ryj|P!hUiO` z7knSlgR5T3b?anxk>E^6p_|E=bm&Y>Y-HX_ViiP7AQ9~&;l@w7KTVQwjb|RzM&>iP zD>XtLK?~a2i1knoOqg}8EKrfSX-671Q&0~n_S6lpLN!iZ*A6i%iGmu=7T6ZS1!gc9 z5a>h5I6Emd)DY&R!ji^Jdi^HJ8n~y-dowYpb>l{Y=Lg7g3wdhfZL`q1MP)FF#1aN4 z4d`(WazPoF5d&NbjoOtLWKN9g!nR)YW34ST<3@QE6!uCl4t5Jq4p5UCD ze2XC(=!;?Rn(lB)Uf~$UT-s zE&pP^Nu-n||3c1Je*L8M+38#BW>ry09;D$61unVdkejt*Ks%4YW+{Z|%_sNFk(hl1 zbW(z&IIuH*RVT}3NZHj*7p6ofes>EFWn9LcsJp{MPTr4)C|O-p99glb^h>&E;&tCI zvb3EyDbBXA#?ngODiXg5Lz%fCZoJkCtYAZnWqg&{pH20Xzn zk27dh<^b>Z4Dw6t0PhZq@+)AgU#(gZwCo-AOX=Xx3(kB_Rb#Y7*HJdbyJO-OiqpH_ zmZYYKRAkXD-HzdBqMqrXnP~-V?x207`kfNd1+1QMyFsgY!#>dvF&p+plr^L!L8yqelQe-7F zjZd}UNLlM@(OigQZwytWzxABpIQBz3R#kF#uVh+A+uhI))*l8q(>}k)dfLx{*$Cpb zX3=I5aP@oko0N^Er^#247O5$GrgysM(PTomX=viH;zEg-;=LtPYzLO0b(4@2SzC4| zg7+kn7p#YVUn6pjoj7=ye=NVGz9o+Cot?67*bdA&MBu4!3Q-WvpkLJ5@!mVHny>Ko zN91-|S9oeYP&mX(U6LRT9?<84(P9}!M6`Lo8jJOW$}7#D?~7ez6l5M(TgvtmiAyHC zVYY}r<}>=@@hlV8O?{maOkAtG#7VM^&k*S%w5ZO$L9g{i4c!+;Tjv# zYTZT(3$^O`gKMBqa)0zcY3s=YWS%yvaR({T?vk?<&L4nwPbTwsm}@ew#q^=!Aq_c= z4i;dbHtD>nIVxO>>(&5Ads-#lxoGJb2OFqBqnH|($3BHCZooa|EfnnJ&a=eczmj05 zU$o_*6bFnmut~(xF`==>@hlcgC>Jrwj1rH{u{#2aDg0TNv$mLc4<@qIYsmyk+v^a^ zAZHG8H=43P$j$Maep__LCCf-VZ>tU1`?W-sr)S;-A)+&a+yaYV(AwC)+FZ&ea!=04 z1Q3rm_f|1~bPU6UR1Z0RtmXKU$CX*Wyj_Dev_3y?w5HcjGk zRl9huBzrW3JlW3)L|a@+b%!drsz{JSbFV`VcJ&cS)aWhrjxj5q-WAUK#|7GrGYq-g zO@=0~nEQbcvKiHQwiq2uoJY!FqAE6NVf!up%V;_5+_MmCFxIpT5#B0?8b;oT6Q@y% zWPJ&+t?6_mI)$s*Z1VA#@MHRL|6{sXqG4C47ViD8z|Jt-*h6p-u^va`0RU;W@S>c; zcYDm}?uenWYm_If!Y4R*c67J!_5)!9POvC)0PZtw{BU z)6lP=n_lDf0wbw!(cWqt{Ph;O2j@)!kPDPqg`b2z(@*0a%szxT zP_JR{;Z>Z1#S4cZcc5lbPd1})lpuFt$M-Y>KU)uNRxXY{hIHU4fs`1nk`|Z|E&}1( zB1xxJ_zkhN+z=*;E|{ZfgK}M_Q|DnF15UVS&4HX}N#=ioI?ow9QREZ@naQsOWXfG5 zR&;`ijOO2&Lu^Ps#p)(ZraW-A;)w|M>n#A?;}@jxx0&(b_^Lxu2yFF2(wPY#6TGsH zw<2o6eQ(wyiC0)}G@DV@>%Mz2NP1a);haSU*tWwaB_07&dM{?@ki$llB#-Q(I#yZZ zGX%g^swjg7#8M+&i)M@anj?s^$y{V#Zgl|08B+Xukm*Z6FOO1OR&-DgNs&2JEOe_b z9KW9qH4ZR564Adm_l}jVsl=xA?~TsBg93`otRRp8OTz^yC0!j3F_y+nN`a4eE;9sx zT0O}f!2#5cyvB*}sGpVAEy|VFojIyXr4!x>s8Cr+Zqd`TJ1LolTn7^L?P<3N(eVhe z0>XQ#@Sj>CTL9-AbUq0Zw^fb(I6yxMJB&uFxjI6%nmrmh zQ>*0L=lwqyf2`Jlxc@}#4WxN959@QG(z(lA3fBN=tFt;>6J<*7=?%Ye0B=Pj z$b-X=9=>DPM*y=zQ)F0e)Bo_)t9`3ES&znmnxpo*gx_h)FLfo< z&+SXj4!{Z5vl+ep!Jzg^Z(s;+#|??!3AX(KTZ6du2$0bcGKhBkQ|$xOijQt)Y`Zzw zWR}V|4{u${BT>gc+0vZsBSt4U8LxL8Zzg)ib@`WPU(ll{#*~jRUo8(`=w|;_W>b*u zv?gnV<31x*qrJ^Qa`!KdohTxwk^BM}IZwx*`a=MLj+ez+R{~Q#QpYH(+);phQ?tl9 z)|7HYm{RuS1#accS(~+el%h6cie9+B34RmCC@$Ped%4vQ6&dQG(%TIVSUQPJXn?x@ z`-w37u%i#y>ld+VJ@X)ag6ub6gwXehY8?@JZXl$dC=}-`#P7-G1juN)sQ%gzCLNMp zzRPp#u$z?`MN8Iqp{_m^Hr_{?Bej}IC(NFSFPAa&XOLi#5`DT zEeZM&nXv0be-vxY6e#fIj~V$Ha_%Px!hm*ptceCePwE61@W)s0*K}Qgq$)4ue z!JbEQ9Gt#t(*sUuPwv-j1-@p4rp>rm>E~ollRlvF@g%gJcr5bHM6F}5^zOAOeK!Tn zc+ogj1jp)6fQ-iB1Wt&iUx5Zr@B~iaO8P#*HSqGQUYN+eBfMT^Q;C_;)-J&Av6fx9 znpU<98VjB~Ft{#3Dl#Jt=}I8aA!E{g;L31^YrwES!B^&58e#T)0Kv%qZ2I#478?S8efz>410xbZ0KN^Pf-W8+Erzq^+XK`dLIAkFxWNu_B9(sWbk#B2@$}r)R!=P%d{fQ0eX{w~`Qd%_);Sda<^Ie7 zklv4q!e#d-Y{D&6ONTN!nSwn(Ps}g;+5x2cdN1);yTqkV^TuI3Qn6eQ)K^N)4EkO(S`A`C0bjkIee2b4%4+l#0 zULPf|Uv$|sI&al3lAB-;8H$(004sOt?%Z<(UUnjL_TAncWG6mf7dc#ZT(E9jMAq%z zSlo>2`*WFJwYcVG(%8~Rv(V?SzG&OBXVlKhZLVKls)#%QwxT|Hj8a4}T+N{LHX_~v11vu^ z5jA|20abDCXUD7_7pk6$J|I+0*TP721~Kz%S7GlC&<_NA<9w4PqyA7*(cgVGl+t|3 zl*T|)Zk0n(*Aee-bsl- zw)G2NRZh^>&J*URFCXP|d=TFrom5#WRHLSBr1RMx=4V)!`7_sNEH_izf3h?^c$@GzkoQ zmHC4HH#)RdfJWS5)%v1BY8xZ3SDFo074TZ$(xh};=A~S#G>Y)J3&Eey%<{xxEV=Y~ zy|N3!5H_Y5ElE2vRVd^WBnV~XiB6bf16~&Ggrm&zw3Nv5rJ+9wb3!PkmBI(Y)bc_x zYZGMB_c~{{m|kX+Wz=SxV|fxRfKh6tkkG`vy+zH7NRz@*0J&E0g?k$Wi9k0HObG)B z8F&&gi%o?@Cya)b+4?6DIMbN-a>3Kr5qOLPES3r_(oG7@uVM{F`e*wkY9%C~%?%on z(V*AZ+zn@2M(e#AM6|}IA5#dhNcQsripqhN#mGd+3s=hvEDb8vibEgrRJIv!?JT9q z_0iJhEY?GWqeUWP<(TbpKc&M;=7f2w4Ba2e=_0h!Q%N_h;H2OB6PJi1t>uLCNm)Z8 z+oSxf`qG+#|4pm}ij=C1{Uis!QxqnnnpKS^q<$0|HX!DU7Ru|E0Kl8|%F1Ts>8Z4_! z-wWxy>`?TcaAle5c=seZ)*hK9UHO5+CB1mNuql#|4rNmwZU>rn_d?e>s>9EnQYQJLge*V(hP&T@uV`l94)IBn8c z7TIcs)k=y~&h2<%hiP-L1?_>oj5-9-@lHcFPiDkz&E93!CdDeMx^zy+49hrPSfpk_ ztn*058P}bl>W!+qnOD_=4#pjdzx393#E%usL1_9Ijn{194&F52=69hU#c|Oz6n^3( zxE<_q?zshu(!;t>yMZ{=f>nA4p99woX4pNTKp#BlI2~ckdrwX`HB8=VNl;}{bQHhr z^YC4*jH4vyAp;cw$k!I^S zrMzXM>ExeRsb4MA&b2e}OtR18RN(bmSPjAg@B%Xg0AUAJ@7Vm1XvUjdDPPAMUrDz2 zAve{Pfh54A*QzEXhUQQM`U!&s54TDl+=9B+o!I=l{1Bgi2;nmc-w(kcRxKm9S)ms< zyWg*BP@MYwaQ7@#aON5~EZti`7j*P@PW7?;b1)jH#A~qkk48TKS?C4~yHwz0$?M+~ zN-=eHE#zv%=4c?^Fc`pT;big)6~HKh;l*;&2?H3^BRQnQ@r4tgIX-*Deh&2&Ek=FB zv=%D<7JbM`aA1-}HGYpeWmDs#P z+r3(1P*xYprI()mA#k2f*V=2L*u z?8P`xfL7%LVOx!gt>+PgQEc)MYr3LVL`rW-&LP|9C(0G-ES)~HCdR5JGtMa+KLG2R zNyhRP2FhzuCiQ^6tf84fdNH&Ze@nldw>mB_7_HnSUe>imSH*i=mG&M&HyPEi_)9W1 zTU~vSpQZIS?F>R_*+(&^0nuPsb)iX;(AyPW$)BU^EKl==mXlsbI94%MA~nBO(3Hn@ zwyZB0kr)Gf1i&D0`dUCUI>XY3R_$Eyq&(=b2)STo{d|=mov6RT?)|t`K0keB7EkyASRR?*SXdB~cKN<+VOpN+(8n~a?*G2a$ghetO+SD+g?yd7 zXq@tJoA8{9eWPrc?wK92ex$QQiSJ6^@;uia%9^+*d;ac^A5#OcND(Vf3A0R{jJ&r_ z(dqP)x7A<0)bG7Cu9LvRBF~LY+7wtbjS?!pT z(SEHZkc;c-^pv|Greb?zI*#Yf7XFgj&pdA+Cx|qb`bvdXGuOo$+33}#eX^!~x}|`Q zF~=a0(xc~#wi(?~xO6~hw?I4_`1&_8C2*<7hSqnxxcs-E=zkFt{T=BlI~qHP*;*S* z+1gq<+x;EvMk;E`VtxZkL}IlU9~3Ic8=EXNfi+h&E|ll`$I3#L!0{nujRGO6Xxog` zt=?5Th%GE;hj{NrS$O&ssD}O9Mp`CZI~@{ zh-f{B!i&`4@3i>E0Cd26$creLN%u-ZNJ7VJzCOMRQ0lIZRM{5Z&kD#)CArLHI|bRD zF0->RkJXfGOgc)pwT{wnL{fcww}`9>G)Yg7Sbej(TC6O6Pmn$fhuyBgr6(v}=4O-C zqNmtgzASQjVAf1Xl86GS^eZ;Y;PnZtU{o}3cH=%u^eT#X7y50SRG1*)QTuX@1r|!w zCEhlXj!A9n;sadf=C-qWw^4hUG-nI%=2Zk!^hmOInzX1UYmE&0Ta6V9*TVgbBF#gC z-vq1SOcZg-!t?@KyzX`4A^Qjd#O(^T5h$P!CNMvIq^~b)OWgcXP@dpTQjW9UMCKYO z*Nwro=gQr}UFWNl?xD)vqT!(LT(QBNue-!vuTzpcqU0_sc5X2H^b$QWmIyGfA_!2s zyh#u{Y)0JZ@H6dWj+?zDg3KnW=&3hD>v#a{`Lp(d(JzNQ=Le}bUgbS-K0?CG<4^|B z&3ofFM17FIo2&2%QrU&#;*n>>m}Y^X(DZaQW5`GJsMw>xh?VhtDY%JodYN$><7G9B z?wR|%laJ{xKm0rb`D05!I|KZaV>pF+pF!1AmI4Wdp$Sz&T%e=HC-H+?&Uz71$w?nc z=1#k+k|{L36ji}d=yC$UNAA4=iNdz5=lwBVGP4hMmqazagZKf~Z zTJZnHO#hjR3EA41n43B~=>IoICoPjn+XC=nL!yE zMa)a6$}WlMAZlHkVszf-JkwgOKS_{V zW79;8n)6d>mhE!XLzCxxUHg+sInw6EWooANT>XnWF;dU(3#NI@swLLdtd_0Xh^Z`h zFDv&!nSE95qx_9a4^mTtb+0wZMcVduxyljSsW%73T94Y``lLennK{bhJ=&_$^YXOd zvaiQ75z)3dQ{fea(m$ptAAp` zpg_;)=-SX$vz)eRPP`somPfKV!}t#~L1+9T_@ugFL5^9H+btT84Eh1{bCdlcTQ{+a zQ+HS7YNu9fI`SkDDuGbMJ^qpJ7Sb-sY1EC4_bYI!V}e#nCjP{PU9a6d3F);M)YhmS4jVGQJ%*721f#$n z%J;7V5zG!a@GtuJT}_FY0%*p3;Fd~I@lkxog48P@1$g{;iI@uLx*Xt^e9)0m{AlsJ z0yr^wUnvR!1;$}V5;0|%xHy3%@%mY?0%Cp(iI@gx1y#S}Zx|GGolM%2H~%Q05$F8+ z2h{&8HtYpX>*9VF8L+>fzf?(oPn)3m=LiX!f6RZd`=$fa+WmhF7b^16DG6y>iY93~ z38@kB1?kC=eM-s+s*!Q&Mv#9I1U>xQ(2H-1!as&y{Bxj%p_Tdnm{9T8>!LFz=W*XV zE#q51^l$jZzg`!zwYL5S$Vi#n7|ZE9e4h!#vUY#%G{tXrm5u4&$3mjwg$&X+v1ksi zDWOq&G?_fjPkEKbm|~YKWDpaH=m!!s=oid|T9TD(`o_R<{xk4rqA>nUKiG9{gliF% z;2Q9=pcB)z0 zvv#_DKtb$J>Ci2WJfE?eu&(KgCdX?wj;Z?HmcdO&arFjmF3qF#n&&)A=@ixs#1=Y2 z^hQfosufp%Tmrt5uGj@#Zco=&b~|bI$Wy^xFMI{In;nd?PM>xhrdRkN`3?s30Ch}x(x#a zEuqc2^JbT&{XC!ZV^%gt#ehWXVSv8z&;}OBZEfJc*0_l~eS?&?^?3WG-QI98J>*F_ zE*TP~kIw0U9(x!YMGbABQ)=c`VTeHmjkHmieYGYd^vs#1r#u8B#ZVI#b(S)FosjE5 zaSA>7^@_#inTN|bp25fDG4_+gCO;kL1Xl1exQB~t-5CAMv8C|oe$>56VQV1Le9*qXNlU5%lOC{_|ze;cakm*5(& zh(wTof@uRb!3RqG7i-X@l^53zGrnc5{(#Wce54!w3vyl-YNZ36Ij+DJXmmCp8JC_= z*o5ddOq^(MZt6jcVLxo^cA8&$CJ`CaG(FA)e_uq}?|YkE-{#m}>-7_Tk=@o*bJG;* z@>zy)O3nU));RQyOCGJCm~7^Ov9JHK;r=plT{zy^{BIMd0Q-M5aRHNW{q)~saCbQ=VTJ>&GDNF~#w;zQu90>A05N)%gJ+Hy8$rGKX20azZAq%1}-a=?+7R zs+6Ei&A5O1tA2#1eAkV&&ust=rksqRfG zk)Y#L6PQk{@71N=B)qu&FwVGncd145pf}dTND53-CY-?M$XG9Y$QE$usi5`Hy-Cg4 zz1%q70yhFX9D|gAboY$n%pkt2dIjqTn!wsHJ)^e!z?Q?@fll8#c)%WuiU})*f)=xp zgLXVLP$!yDNpmm#eA1e{Ib#kct7nX7zXWYwIL*^m^zGEkX6w~QDe03csH^8f5;h&K z_<%AfeZ_Y-MEuA>4N5{L$O|Qt6t*#hf76a_c@*#Qz>wI80@6dgydIB@l2$WbKlC7Z_dwaqO5QG#0#7IR9Qj z0gtN!dY@!Hj3EJ5h+wQVh9RgPVGp4)=a}3}^tC0|M?}J8`RN3p1_MyidI`1${zsux z6mj7GT{C*_l?aPvoQ2mMvAdJos zbDN>-w5>o=GOnV^M6*eRWu#{q6H+NkJbJ}gzn$L#rHKtT1N#; zD3AmH!!PDrATE^ivsPJDDOOAUaQ3a^1FHSL@}Ll|L9w@B-08Jn$n=%$RcQ5>sEW}_ zon%pb=w#MH)`qQX7tbx8&$qMkO}??l=AtJt?x`SBn zr@3*H99)A~527>_5aErQJT3K$VJ7GxD#&xA9?TiC6D8k@?13*Mv0p@nlN1pj^h7i& z-#<=LPnu@=CE8JbNEv0bU&L&xCODL!!>n9vV2Sv+*o9MS1G7MVScI*~7T!nZE+~It zU@Xp*c>+d)y9!@}$ujSdN}7)8OoU<2C_g>wuIbt%CKj}zs6H*xl%yIsQelxkFA;KP z(pkr!xh%#8-fE_qI9qW^Ey2DHzFHUFl2?feO_R)azh2VVP>>dAzcEj`F>Hf4gRn85 z8IP!N0uaF4D$aP-ipo5J&V0s*GN82>TmX4P zwfqvHm4Q4>_G2@VJ~w4Q4upr$jjZVh&M=FJ*l3zXMRCfLs=uQl5HZdao9zz z=riLcu7$ic$VdGyKiTV2KOn(Z=}^%5JZDkSM%Cw=MFe6laZRF zY|L9v!M3RqggNcg;6ljI;H4#bU-SjP979ekDsUWSNs@_z9=$npa~>OcA*OJ@o{FB7 zfQyrvuevA>6=f1aR7h+BSjU*k{3Lz&_?!Z$vBji{HcXehyEgx=SMoSNW4-)l%luAh z_=&BjyX*|R1E9^(Do1HZ+E*9#UxOrw?lHFn7QaNf2({>pvjj)Eh1S*;8~6l>@0b>O z1R9EB>#0J-n;q;xa1e0~umYR=??OYz=|Z5Z_|5yy^S|kip_{9*dya4hUY7-5$gR`i zxQBJ=YC)j~+=UDp?ZV;EG(oZ3SE(P|sfX#Rb}7#xkfQX!&9gGtB)5hMC{@Z6_I%Z< z6qz~67AhQ<0TY}*E@~}f9K*>I-qv%J$2=p9SiEmmY;EUS1vn^tMmWfH24lMih`mL_2&Y5Nx2;t_6(0Ut{)4CSoN9e~zL<` zA`U^;-rRI+foNa?vPQmGRU%W>jYx+VzfcRPEb+3eusNWKWtuzky62TR%c9!)`7del zUtXQjO0`MiJCXtZ_Ut168QcG7ur8$UX#6b-Ft%|tclze1{~fh|zh4Yie=aNT<5VQ6_CnoCppyOO$BCV**PnGbv_ zS;rj4IKBrxfU9*-r^Sx)M_Gj;y|oWh~rW{N2@sZO&yRr3a+$17c&xF?FjPi z?Xwgcc;X<$2;-st^$DO-$f03XLOV{8u#5|~*EJ1|9Rn}o3ek|t;tL;L#{gRVg~TYpVs z8Bx&2g9U??Nc7?IMFh@Ld@FC?V;EQgSei}_M%dZ0IHEr<+h`sfJ#3Y8UZyx#I5iAj z=&9;8-M*cXx%4T%>@MfaA+|5fer`5|I66r*I1X8Q^#UC{*Xm0||D@F0&59pIH3D}a zu`E#^6MYLtoyt)vLiuBpJUG>XeLS~}E4@9`AB3@vyfoLmG+TsxyqLWhFA(s$sq&(>_O^xDWNe36o0Uz<@OCmRMcv<E&}=w2K4{^TmKHb{{HZ9Vw02cKXYjX?Y|h%JoW1JF4EEsX}hiw6e1Kh z$hyRYX8g#0kg?p)tl~iz!zL;wWF%ktT?Mj%yw5Ut%J@>m1Z*-jLJN%LH{5;0Sk3fBsOE*a|v$U$q1(on5-Yj zr(2p|?G;#djs)oMJdO;jZP;gmZ!oS;SFblJ2(l4o5&Mx3O{fJ6l(^F&3b4g}!&#qN zPFHyITSvKKIs3dS$mb75peI^jc@i)VH}6Z8pGYOUP#z3_YWR1`1?}XmdhKty!`q{P z(&QIHo+(mI2KQ>+>?GmA1D$>T-Wpg1Z|ueUG%kX1Ta-FD18P?M{3;gyABjK zNK$m}VJ|~CrU)zw1@4%=D$^tDXt!Q)hta~kIAbQGkH(AYlS>n}ka+aco+k$yni8t= zw1NZ}F_=91^t_1w_FqXb^8We_hkPUg{QL~w+`vj*&>SL5L95R(kT-!w?PyH>OYk^i zV5MsyoTyifJ5r@KDXFsf9mWD~)cDv+fAS%gj2iwIsj&XzzbLc*GW2i(7Avps#fSP{ ze9r%L%ikoui=X~3U%GsAdjAX8l^G`~+sls}I0XVM?8PV7mv`O`jEUsD zMyt%1o0)IN=p0w6vrfTULAf?!v@eN}p=)winuCh^IVw=>EDJ^-hf?yXc>xD6nZB7fbS9+$yq z*b=6<#|Jjjj@>`g6-=Xci(QG{^pXz~L+)O`Xfi$3Iw4~6g2z8=TnG|Gu^!102dW6Q z_(y&?k{84ngI4s;y~e3MD2=z!obIs%U|QDCvCv}+z_iq#R1hUEu4JVTaR1YJkpYWA zV|=fv>0gC||6J4meF-Dwr6v3L;l1Y;2j{EH$fgLHAw{aCDa7QF0U;qa|D3d1iL=#h zBz&^MeFFF-G)w0K#|xq*WxCg2eWSyUp3bnkc_wk3a54}xh!vr#U~;#himiIy6DW4N z(5qJ14+J1Qab(>M0IMMpIHSh`d@xf>Tl|^)u*7pyMp($!7a-sy)QlRG2+=|9vE3dK zvpn^S0_m933)W>7PP!O)j^gE6(-~MG3Rhd|&u|J@JF7AWgOPu(siGK!DwrL2dy?IQ z+ILxSS7a(A9B}T)GB&=Vk+jTsKxl1MsRfK(Or}={T>3!uPPpv)qrOB?)vqX}^PA~8 zr_l%^(WGCjR2bi|Vq>w?=qjzJNerpL+Nt$h?t>2vc;5aCo9VAT<3_rxr1yOZh50>n zm+L?OUjc)^cy|A9o2F7l(-rd@Y7Gl5#h7~Nm&-z0DGrSS2vgZ)PQxrQH?KGHvozG4 z%EcEV71_kjBt-bj|ElW1Q}+zYT1!$j`vd0_);aq(zEMq~dhf2*%eP%?o@de-hgh*mWT= zToY&wPk_DG02x=iJN_=g)|XiS5}^b1XF-wWBceYW_KE>~Qe@sJecX(bbBD@E`Jp$7 zE~z-aA#%cPl7WTSCL-ixmI;H_6uJq84r8K$dL-JY26y5gD@BUs^dfm>X-&mS<9r4A zdqTE0t79-?r3v6ZHE|vl&h?Vjv|Of$V4_s-1OCutln&&n)uN(gG3VYw579=H$_iAB zB997n5JgLMY-;q^DwVQSU=Cznh$f)bA_I+paHO4TPQ##;rL*{^8HaCm5GmsaplC^0nUPk=!qzhg~-|5Xx%VK4kQ=gM$Qgc_Lhk!L9 z@(qkJTX~|>fJ@!m9@gDT@!Bv&Pt_yL@JdVUmMWAB;V!ED=xMUMVX3BVRaFZR&XH^l&w+vp6YHI3|0&17<=CrvWM=KX=aG z#gv-Jk682uV@4-=_`wA`7WH>y0@dYO>T_>l^rFF0Gj^-&IoFC4j%I0Kk~oRkdl>?4{3X{BHZ{ zsDi;+VA)Pm7$NywT=+iP`rwZB7c#}46qh?s^NP?GUI%G~YS2*3KZ)nf-Xd!}U9$&F zrps=Gq#xbLPn@R6IM6Ri&`gfM1~{&x!3S-58n33QWq3BEpAWPBKLml`NJ}5Mdhv_8 zuPXC>@0tO?0qJ05_~uSc-DNqi^s9^;Bvy4!=|sG{dg}KwZM)Mq5K55hV4fEZV4jx@ zm{G9Mmp_**0RS80ft|uSj}Qo>v3s26G?0EXLC!?SZh|Z4&|jFeyTzbBeUiC9DQ1T| zbiqKg;^XLt=zq*27zJh52>LTY)9tiSNP+*}0Tn^@7TB6X51(~L>;2Ne8(t==YaqiuQgTM|{=A#)H=+-937xGO!M;x;h{ z;Ycr$+97?`i}?|84+c2Czyi1iuy!QpQL zL&!(q!FO^ALkJ5Cm60_9>-3h0759#fg3_cCbgy-_#89Fs(SG@UZ4WN>Mq;tG*0l4a zLLvx~*zX)}Uamc5bb4P-?0;PSxdPa?*A#%>gXE;25h%}~kMG?d=t=N19~ZV~3A2QD zSlP?M9l#cPM{pf$Z6gJQJ_TA^+%OJL9`i`mHyE&w%-FfjD?EZsO4W3cAhAJHmC~%< z6*=9$gC@AdgdRyWeFvFRUuSi&%(7es#TkGKRtwt6ALo^=jmpN41({>*_zBA6ol(mn z;5lHrh|xPH6B~AhN>QFTTXe~Ln4Uzdvya@|IH|38?ytA(X%Qy|Bzu0;bT|8}`5-mw zBRPX6!45GcYs>g}(_2T!AyPv8503&{=1NYDp<>Wk<>}gHT#P4UruiS)FhjiAP4gU^ zwFm~CJtBwE%{nIr12**T>r+1F8h4jX+qwoG3Mriw3jHDs5se>nV~ZJKn$uUQc^{>Q z97wy7lpZr=aok5mF5KOzSke=O8eF$m-J!oI2n#UR7vDl0S$Kh2Ze zB8cUAGuM7JP|eUvb?O>|#Wd9N1T>uE_O3qT?&EOA#1N+YNilsQFunl?dW*2V`SCuY z6dy~KBkBQ|0{D>78huJ=QM^#eONHc_+S4|3O6nMi?<_TX5)$@yzO-9BFmD^PNB01v zLdDcIMGvPFZC^R-wSac=k1F*z?ia>)^Lg2orOA25MudNcr=VZ?n#4Nvqd-_E&#(S8 z!;^QoCCDdKTbAu#scwx!R8~0^qoW1W!YaT&2~S~7!r=p0<4{-t!{bw&C{;%3OXNR7 z7XivN6noxVR z*iB3(?)QjPN-BVSN!~o=gM4|Op0{dgrOHq75c!JAD+B9t?+sq7tBZ$C%{5P3&ovKA z&6BRj)YNe)SklM6y>lMV>W;U-FkPUhO280U*CeLAU&%#Y?7=|h}HCraHxGB4bMd$F7-HznMY zM}FM2`%L>x8heD9u-E8#(F^9>(R0hybHun;drSvUz%NqBVd9+HeevE})I_EureP6M z4>!zaBXizfO@mBMko4jEh>?=cWd@J-sSO9W5W``RFG`U9lsjCCy!FDejW#a0*?o@t zia9r0nW&D9gLh6EqjxMiIrfnXvbaz)iIktF?BOU&)f>5&sc0?E-4XOR);KwuOz+J$-9;; zyh>$M!S|fC@H-xM!+h@nF?A33NLQ9XGd0}v?^$2m>eY@MGXGqoaHh8}3{B)gywBv- z4^;Bn#E-Z{`b+g2Re%RqnrRP53{;@cr6_0K=n=1@M}ziRJI6-JFj))|$w&TSkgj4f zTnw`thaB>|*_NS7524u7$?UY@nroKqTkDI}*7tO1#E4X%8EnS*!wf61J5Zc@rblUq z4$FkH0A|P#(qw9xZ*2kTS!x}rDeuW#WFKJOfXTs!9yx&3)+AUB%d`#%I##hLHb08F z)XZe;yQ*z6KN=IxJv@fq{VUSRk|DF!;$an~9J7geevxjguGQsY^&pv<{zcV>$u&(` z`$n&X(xOqltz0GD-V8-&n3>Xms;z=+#83&-xnl()ZGBKrb2-BGXKmj>YJK>5HUZPR ziZPQ~Gb5sPxkY#y4MBMs2XckPxwSF9)ygQX7GM^L2|4nLGTyp%Bk}k^KUNJ8OV$qE zIC7I(rhNH|Ql~F6IULq%oqsGPO9L-vKfPKugR~$;SyC2SM5?9`D)pr{GBntpWQrC^ z;aSSMb1bSPD^w$9D`%6&Ors#UJQdM|iCHEF%;;5r4%a4b0Hz|ZzHO7Ku$Q<*b$|pR z9iL~+$Q*@a%3-1vw$;F_m3)|wWE#KSuqEy@L=UVLK<1b$o92jbKki|2fqbPeXs4-l#TcsToBj}~h@98k&Jyq(foKD{W6QqgWRWZS)F=SYd9`oUv zh7hGUfkiqg7*iW0`=!(l2CzSz);g+CNbWiu_lrzyJfuuztz7Z32m3I=1#t=L99FCP z?vA(opn$&-W0A{Y;P&?#;shcx0CiL&R0ujWgR#bCtkzAKAzfRARM4db99gZr99~Is zNKmK&G5yv08D}bI!VG&jQi;NYf^|KL^(G4$>S1K=i#>~)>X8s^Oi>WGLX7b5kHs1W z!bszXaZwrpY%51mMq=NY8&yCJ^GYq-7GRc_&4XI;=M4k*bLbnq$~& z_PCrLir?dWY7&D-XeuGL_SPmwu1iZC$`oAvQNhhl+COq4)?{(UN{_Iv7+;$}RcG9d z!a$`w?Dof{u_;V;5C*Y9Y9gdrg#wRp>gh*N_^6SgWTq=|eBb(f@#L`*<*A8dJxaKA zI+r8q+^9SI z&0{%z?MQeYa=cFf@L;TNxfqs1r1ra9$K+71=Iv|SHl4FM!6ytwySY*R0_U-Vn7YQ- zxSLead_>vhsb#_3kJx7#>fVuqZ_u4d)pKrLJ=q6mFrV0402yOZH2${xKq3BNkp6sA zY~RgW6wDo`sOoHc=p`k~ZZEqN2cTQMV9=e3U3%Bn??3%*kGKHLNF)slA;Ja{jX}3Y zzygnH{jUy%0IXT)<`^Y|`_0`$Yr`fIjm5^8*`-y|$MR>y=C}Lu?w5Piv7j5p1eqS4 z;e1B6JzseJuh4|JyIs-W@%fCd`@Dv?>E?JqzlSSYc=c~rga5GtgB@k{$J?tW1tLW1 zBKg&sxwG9UKj!D3Y64U5`+q9?3aG5Mt!=uM?nXMK8>G8LI;Fe2yE~-2yO9RzkZzz( z^TnHpq)ZrezAlLnrC9@)tyIpR&4kwVM-O9up8*P_ZjS*J)Yyc^q7M;)*=P9>G}_># zFUH69#MmZ#Lso1^v@B|>A#aRLrAl9si6omRD=&uihB|_89P}_!8pvbW!7de_3_^VA ztT4Gx*6Y5I#10&&VncdukIpL6Y0Zcckezm5fUyt^krJA+uvTT@rwn&OQ7vDiFT65BKz^Ppi@l}-HpogVwp?onP0FD7E00*j7P){h67|<3xG_fk+rHoe z)oe==omT5hH)-C+mjz!$UO|S)oC(uAI$3e-4Cpl6q&`@6pj*G?C#=z zpnYiBjp!+h;Dd+0v~ID=EFI-2R8Zk@8Kd#^ZQ3%-Li@^Hfr-2y17ozY+Ei(0mBd2? z+SJaAdcVq4o_lVWm-EErU$VnAbJH7{bkIfa7tkgSh}%ui%SC-X19BlxXRQxeYhXru zK>3l)38i7tq8F=l$@(JGw`m+#kw-Y;69?+b4X(kJVq>ew#=wG}Y_NbzGv6|qgI!XV zG8*5627xktzsXaJ6jSQ>@WJ}xqVnvFGEsJ@xFTEp`Wxb%$-2r8ZP=%wgN2hc13msk z43*Z|A)H=Y-kF*}G`M=@=1qcQ;0h}iQ04lOn9c%9t<+jH`~j}R=+LZ!onnw% zRA0Zd#D{v6vlI=DID~K)v`d4+Doiw5rN2p>&yFr1x!{XdOMLz6^gE$7tM1N_jGz%( zHSwr8^R|EG{QDi`Rmk0JU4f!NU!O3XdVDQm1ENgxv9nTTTc$*}gCC#B!fsx(VCKiQ zERXvUgRtHy#a>)ay?}ll6}H=&v6&t6Izb@?viSt9hT1p3J&OrEL1d(P}P>g6SS3wKDoY=ePnB-TE8M6Tc3|ON;o#9 zZyfJ3QsHqF2h(1t%!&>q6p8m-Fc?eh2jXKaf~_n>ryMzI>rgm2EQn&YQPalWl0XST{;q7uR#m~L2L64VbGii{A2>X zp=nx9q0Qje$jN>@tPA;&GNs*m%5VjX5QVqg{E<43P`A|w6{}BO=NOHCML!76M?tY2 zc{W)u&mK1Qt5AT`oJ8--jXUi9G`{3e{Z#j02 zCF8#`DPV}VPIjN(3C+!Pg0OitnM2vRotIIJa zgni%+JE8ZxSKnz5vua9OS@aRf4WP=lX78^z+xW|9Im@OO~`oe0_2+dd2SOp%zvns0l z8291AaYmIr=y;cq&BcI+Mz`-%gCa&0b^~Hctn{9K`S5uO2)keP&#)rgxN5Qkw;+kr z)hW{>J^-zRGexkB%Xd4`Xh@@vqp3 zuqI+m%M-EEXN1oqGka1}o3WCQeGS?a?J2{0hQF)$NVU|9KY73&^N4iEEm~=z*QK;; zdc7V#*oj)*p=@8mL(0sSZ?RXIq@!zzzB~&YU7wmN%94sg+;cKc*W#o z=47UC>r7zU1MrLs(ihVkb{7b4__#C9%5HkG3miuV_;FXT+qIeYFG3c$BJt9jA7$~m zAycl%=!IpuGos5_x?8;-p`Ic({PFe~C33G>Z>pv+dAu*Gr2LEqAVt3#%#e23Gq zrd3|tZr8z&c_2vvZ_a8AsFL!*ZmrF1Ysp#{{JfxWKyixFh|e#M=4>$Q1Uj%-Jka5Q zzBP9HfY*IQ3*ufIRFu^TfsCaV-5%59L+6dBYV&>SP9Kz>9ejqAAPK%M39NZYQ0*0M zsW<*i*C_TX>$oHGJu|emmaC8mu_tngdiyETEt=7yJn!UM23chnbEZ?0X2+ZkZ~665 z9vg9$Eplsd2&yKf7vmB>w}fVz+_*(h55_*z&}VEu<-DrH53!oH9XeAl5< z2_Bj;d)xT92$oUSXhK8eEfMdM)J}$Q`N&N78JmBG zTqBfti`$aR_*pMaIV*CeWK;Y)$-8rKk@me@EQrxmQ#f}mBDN}m=%FEU-3PF-1$C#! zRtgyi=UC2;aZRT^QoptM0y#n_5)cVqQgrBj5ts!2=5L~_(@?O;#@NEihy2On@k{V! z(gf#^;J}x*e&csg2`hwt@A${uB*|0?>Vbk+*4$iDw#OWA)Nk=-$FCa0m)A7T->!)B zd{^4(yXScDlkt&2T7I3a!$zScGz*kSqGwBZNACjL!YukFtxdr44cAJ6F;FuZ{T-*@ z<<(Tk^w!_>Q~?%STY}st>MPzAR3N7DX7iR(ixmNz3JKD z&dqyEI~aVsonVv&sWBy^)ShI}>MC|)`kh9-rn)q;E+3tgiCZ>t%83*&e-UWpe(M65 zeP1IRkD*ZD=d)|i$#dB{`B3t5Iw6O|cyr3&N18AjSVlnL9sQip=tiL!|DDk% z43TO26kj+5qftK33LgjbeYZRx2iDhqh?M0^Y_AIPG9LtC=4FU8AJDFqY>3EK0wr&b zx_6cR6}jG^Iq;+_7%CN{h2q`fYX|i_Nqlis-v9b`A`ShiL)K>GnD`0*VO*OYUVvf$ zqF}15P<0p~oX6MU{5^{D;X8hdSw?w93{L42L-O<5VnT=zKa=nMT<4Fa#O^_*Xkj=) z8Vwb}I_TL;;hbu$^8n+TfGg@ex6zePpW&Eh*?oiWWutu)+JQYrhMxn^{AhM7-kFdQ zPv9j)Eo+nQ4$%Cl?;~j~tFHy_*g3A{A!p=pRP^Wn|5tb(ym@|{Y&S9E3unGuZtUZn5({7mpen7x8>jswuE7Y-8?t6rO0WuP za7Tu~ARPO!I798iVy`ZddmSI=9{Ab1jCm6)c;;P~^{!cu7rl;&#aGe}X4nYF+dDsl zh+2rNLmlhG!nLVdjmNDvaLLw5x>xlQtNiZPr~1NK4cnodF3uxn7${H|%GRedsFD*I zSe&^FkhKEPor1TeiSZayX1-Uz4Bg8}%8s$dQi*K}?Bk1?i(Z|j-_^b`G#^AyC0aCr zH1C~tO;;|;Lz`kcN4r^rl+0ZvA6)(rQU5?QrufASw?x>^F>-52O;dHns>Bg~;WXPrVLbXecIH#W z8z81lgqw1tck0^oZfMu8kRCHvBlmrI*7zfi9!_PC8JZtPorF4sS|}?$2z$yuMF;(0 zxtIgZX)0c2zV}a<1!u{f#*Dz4jjh9blhHkGK;!~iA?hU8p+3SOmLo$PV4U7wBE{K#56T;OjBTnF0ry!Bx}=4>@8VDwD-pvG&W$$d z48zf)-Kh0@3b&3I1t3zE4b9yJJU&?WubQIBzi z#+&HJWSv)}WY@FmDIYm`@)}uIOY$W^Q^T+6Wvr@bO%<6aVugzHh;f*ZS+)^$$|WH0 zl=HvJ>*&0jFk5psKFqv1a`BOaBQDCQn+sTlD}?d{gC!)kK|Gbe%n2ua z9r_$mitMZMyGtGXRX#JvV92V?JiP9@K(3%N+BZKgH{>v}Ng~^LIKo2$D~(@&wbIky zaW2Jr8=mgZWc6BUDD$+Z*SJ&~U*t3r`mJSZPcjl*bmr#*#`?K_JOmj&B$?QYf-03% zz62+<*7Z_HU;DPpp;xyj#&A*QAdptJS{n!|G8-%=ViHbR3bBO-?lsC}bir}9$~;3O zOI9387nE&nTE%DYdu-D=deBh{k-119#5uU~GL5dq(}(&g3|pKiLU~fxzL1#bI(gxU zNu%lS_lr&GtL(UzHD%5!9zWu++^Vu(+?e5KkK1G6UwV!DOXpg8=yQN5p+>Y*FCn|8 z7@Qy~stL7E`xsQ1-eRW|$lC5bc;4uk&}RB(#@Nnr1#*b@-HLWGWmB7Dg-4U(8}R$& z^R>`Cw%MbZtH7}2qSjuWNd=W}Ox-;ZzfXtnv`2vmf>nN_nP1u}TIGpaA394%sM%+I z0zul7;-uW-AG>a@j+Ahm?gaUSc=Un#@sPbGbkQ@_#v!pf8|6w1*`kLp<^d0UjZrh; z$(ORHFZ#^4-EJJ?T4fPJ7P?r32C7P`n)tO&ZBuKBK}G3;mIz8O3^C9 zbp3Ir@_TKVbv}QJF<%%tt3V}fxNxnhACLhBYjp4SNL1MC)-cNb!y+fIkO?2L_c8R{ zp)Cq%DZ7+qRw}%oj5!1P_)ni+tPo;>IFo+*ecc0&gW3POLU@^p{gatO{RqwnfZ|gyZzCl(9l27zTfpo#+!^LMkbx)Ulv#LfyHkRL?SarDB|l@ zNo716eHu<}Z1HSq18xU4OCW#`Co)6HQt=xGF+_RO#E~k;|YeqO7)$qo29eD1nY&0kVW~iuI`$|Z=ep`T4`o+!3R^2lEmr-v zm0%Kz)UU4Pm7NB%LoU92G7top&jb3-j*gyOvcEN)(I_C}eC`C?lM$$qgaI|vdylD%Gyl|+dg zXM0D>3s`1Ci&JjtR=w6orLy(?N=4rWGYxh~Y?a@3UhBp3B`b;6js|>~I-9e|2=M3I zY*m=zcc%NQPhkJ;_9a{gb;S*Eb*k9sI5;I&9o!eGL zXj(#{Acv-xlZjznji2xuG>_Oo>U=6%b-p%BnoaKET2M{ffgMGMkSo>7K80|;QF}% zJWZsSlru4$R8u^?ewU;l*#VT6rv5Qu#RJN0L-i9P9FBm8j;ALlmHe9vSM@Gp`#2PRf@Z$*ja0H`i`RBfx zeDSCEf)ykq2OU0N-y0QNNLK_F{Q*wHu^QH4XsLpKP{=UV?I zE&NZPo7l7#)E2-bO8|&_p#JMb`>&y>_siJ)HKy&SXa&H*=CQ7x=71SLZqV5d;eZmlF)}A{+2Eydov&;MT|N($}7E>hMLq`&Eu%Bf$GcE_v+mB zwh%}dB-bG`YbCz?>cPvzxqZ(^Z-UNG z8yvL2LT1BC&6Fd8T1hD9DRRslG9##*DVU>(VJg z<&OP{fx4exjuOwr2`q*St5eLme4K%MoXOeC4qCNSw~1>>n)%a-V3!<)(dARGbAZ0C zYr_Ob+u55k`uc=Mg0@|?o@X9%-DBHr!iRE$xs5R$(UW`9#V3Bpyb zGqsK1^*O2p(}o813!#VCvMzC5^&VjiPv}PkPJVbycl-c3vb7z=3B-G!%OVZyL?$1T zBKe$*>%Jm>JY?MIg!$<{3cQn&A9gWM>oFIfsMjD1IAb=nZN{Q-dPwO}Rh@(pjg?}F z&qQ{@SM43CwxUSc-?Y8Q$37icVlr^Uv@;aw{XkBIeZCsw16o)GuXnGT(0lVb{99cI zJAT~Li#TRACyT^S0E0vy;%|Lt{xS;wj3`k0=83I@`Y626KOtD9&=;{psxZkGug@Mp zJmypsxlB93PvrY(jLsg6>HVX9vVPy0=+-1TcUa4+mgCdoFsPK zB)HmW@GJ+eBm52wz5y~Q*yuUW)Y;|qrxk_n#c(KpzL;38RmF=QV<=zsU zQDjM9j5);jZF~PGV^qk{cvW&^-!l^TW9#W+BY$XHYguL(xu&c%8|sKKM0SO`+7N@e zL&d!D>rw-`&5qtQAm7(fc{IrqsvVHx#!6-qxb-2^LhH6UpI;k_S3vEwV%M>BM1=1J zSVW5L49!raRx(R)f1D7$9T5$ZOazy58a*~B4&7${0evFH@A5TONy1QG0^QWIre`yi z)Q>+_3YyTp!tavf2uHWh_$1|n!?hh~T+|ZfQdrmd$o@AcQc+GF+MPI{B~rJ&uLj|l zmjnUCc1#nM>gBT5Y`mW5hljznVPN{Y5{5#(>vbwr*Oz7=-y?mJPyjfmhj-={!Djo$ z;@dGOo)C2Ov>2j|p|7oTtGs%L9$)k7<&B`N!UWhhcv z?WevPC{SyecZeLzVk)7w_&VylDRo>O zyMyzz!;|P8Zm}}fF)O0nL-E9)AhUD}AL`%BcZ?p}LPNG%v!(79eP;|uk8YlIQVVW{ zXqVfjt&Tz+TK(jMdheq&N-F2;DD*C8HQ^dHP`JW}LXs*G=;nc0QU6}JgN(jlwf-7c z#Ca)9s{m#C!*EHC(iU@MU|P9M(sH`EWiQ=klzY6A z;qNT;WQ3`x_R$vUvZ-B7j-RXKv6Ax-ze=zk*(lrG4n?U!rj_B+rwVP*IR+C8`lS6B zO|OFxI2;W#e}(y-UPR4_-|8_V#elS^98Q(43 z*X*o>9lo@<-E?f)w&K$ZOIr)(M#@vRpH1(QO7M&)gtd#^l{IQY= znWvyg6dEo(w6D7VF=6?)oyS{(*+7=kpBIG0H}Ap-zjk>sdC}<|w!}1pQ#fL0HL5|a z@cQX|(%FajZci^=<*&025%XaBo>+2wwo*4vgP%@5@&Bieh<& z9T~p6(g)wsg=$n*VbiXAwD`ekl8WVUS*HSj6J65|BMc}Q4;4A4f9y*nS!attu#CAz zcKYOi*V&g=LC6Ojv5v7S8i^>>3H=pj8o!beHyZM*xSN zctD6ar(DL+WUg`)=Jvp( zB!AFO-wBv8>?|U6?Z`D)MqW4HKBAisClQ}{<6}yHD(XJNEhNA4g|Q?XOlO)1P9Mi2 zXdANm&=tlSaq1n=oDfZ-6$E-bM4P!&kLpI6a(uADf6Sex=1+BaLD(PQcI=J0$?uJr1*36(SB()a<6 zMAJd@9yQy~Kf*|WqnTB3TeaZKvuk8wCrRQclx=#E7UmMo%VerADm?n`enviCA`tpxN1CEOmlK z(fSwaD^cwX5_caoKu}lsz=itw=zx|4m|DONEmrk~KWQu{8M!mjR~}k^g;teJr7W0; z$)F*+c5vXF6t&5P?%PID#TD=V7J6N3c=u}b^1Y|I!|g?ESqXj#-cNgIe^^$W$efwGJ9qsku!8*D797R5u>lZ~yfwn<`h#VpT5=h$<&;Q z54}u+HU{)htpvJ3US6a=wDi(U9a=t0@TE!2OL7xvE3_>qz1R-~nxffnPCDUN0~yi_ zXl$`1dgDnC*kwj<(q?P_mF7Fs4;7XEyF#~YP%IP4bO|L=V!WXc#jqefb`LW|&%FIB z2|@Zky7Rf%46B9lgI5X79KM&lP)nMOjT<|!yVSo`m-G}5Q{`(e(uc1nE0kEvQeg96 zJ&;E5##4L^A%wd^>*BA&=e39>tTs>}&)_p|Xj594IVf;j$c%VpjG$twpsNjzOPj~v|q+XjJR)?*F11Z{(A zZrZTD&pH+PunB}q!&#Z#NdSNgdCVe2k(ptT}V&&fwJ7z$U5(G1Nw3F z@JL4;F|>}ds^Qth40GDprK7=QVw8nvjl;ml@_>rJ!`chBF+0J0|KMr1PW~#whmq}v zwUGqKh(L%8CPC7Zw-qj^e-X#0Bl89sytfC~ELH`7ZkT`1DZ4(t4nhl7oy+}n+# z>8_WL7e|(~K)Kc*dsT+gvJEtaF>G-#F_F;psaI8jBpOCef)lB2OQGgoVKOMP&p=d; zSj+W7yo;j`l8Q(TL#Sgr#i_@u?x_qHdKw1@A=?ZqFSszEvHhWC>OqzYGG8b zP*Sdf$xjPdFw)YO%D8lW6k*$1Vo^6RN#XmN+>F(QsXb>hC7x_ALZdK%^fgKUb5ogW zQzC14Oy(eh=J;Vsd|kepee)POvpWMhc0iWOw_?=_Q?QgXV$6fRAZaXeeBS1uNoTYG zzDe@AV*PFWZ%xKlZX{RnxiX5*=Uwcd! zL+x_hkJmHeas_{Xy$GJX1urGn3Sq&HXA(=f5@xN=(wGP*;tdQ3zamcQTqDi7yXDI8 zCb`zg05iLFUpETYpo>y2IS2>muw4?i5jC|d$VaOkOauQ65-qNa0GWQWd9?K$TN%ELe>BiI$)xeb0+_FObhv?k$-^L(}|Uh0lP@ZPJi zYK5>WX5u*x1~cE~Q1-w_{RHLEwg6~JBy;-Y>}Yu4eS!cmT=!4k#dNSfAP}oGIX7^X ziB8#y&^Tl&ezEF8OQWMlpMdG2m)K)8v>OJ~snJLREA|j=+jc%D%Kcg8QQs8`CKmiUmECrm z&5Cw*Z2*VS4|D8{4CLY`WT{Hm z4u7nMBktDg@TA0e3vzf^6(0ppWR^=cDOgwM{T!n#p*gjD?!&_suZY|2Ljs}}Wsg(8 zvYz23@^~{}SBy|2t9)83eMBFXwJ%hl56X1sP)^W}b2iGS!cof)z#G_95N3}CwXt9O ztI}mal*>U#8TsfTD61rS=Tr5Kb_^&kaJOdF=u+s1gpp#}yXUbEy)mqC;dNF6$pt<} zh|KOMR}CMT8*s`Ek$Y1c^$&}!OT_o)mL+{ZMaej4&R|NA1r(8r{BSESuj z%bpW(M~z=2NO*_--`%REREpuJ5~(l1^!SgwK>k>j{a$G$O@8!Wwn&2}eQoos(;ThO zKB`&o^(Y8L#e;H#p{o#);ewa*5Axwu90m^KuPfRIQXpMVK!QnoYdk-l3_FzZo0_oM zEvH}(yjoZoD8)iY`wxT8L!IJ9rp?#`JBiRuaIme+ZPg{5a3O-+pm>E z7@xtTHTKnFNe81yw9jRlt6X&%TlO;rgQ~S@=R1US`8)DL@W2T}(W5l53HwV>8IJI3 zS2rRq#0ES8omp$@3NzT1dZ>C8>(+p8$AU|BL&-E!op`VX<;ksR>6Xro%W>jxE;Ng> zlZ|ehqNy;GXwqF~ZzPtYZ!|bI0;WSk+|e^*H3<>#1!iHP`j#J-OVv$lmAI=-_=-5Q zu}-cAm0Shc;|TL+F%aT^+}-rVH2Ez)0bvGQ>USaX$pu$m&=wE#&Trw9)HnIh<$vgH zTR1nFfi1FNUYfQL!xbm+)&r5LD%bU0bN(2izoyn4VaeVG_q}ME8*kDbp?D()j5NwX zRAYO%(z?sI=|d?ET9*^;XAHc{FVM*t3pQ9C+SdU_SO&Lg9Sq$3zQXHh+$yisp(UEN z=ack|RS`ZmfIUgR?t>}=rRq8wBvkY)bl9-;NIw1-gDWF2W^B4-fj1D;Z{HlXZ-HOZ4!T zZf@`9g3(;7KqZD;I&e7VQ;H%TGqdcPR5e#j>_t4|5`-O0Z;@8SDLvQglbS?Wb39!= zMihL0;GFN=1ff#|OIpA(Q8zDiEb7`TZ4&`~y%?|&`Tywae2&^Sf2xE2GMknu08~L` z5xDCC8XXQ*s97GXkUEG>C@{?Z1u#hT#IKU4m^wV`4^+|Xo3{>UB1KN1?>FG31jC8n zc>%O|)#6nrl7-eYMn;B`Z1Wwr4j=C?9w5D(OUa_TU%ld}J~igg$wrOzXT6zHji zKm|l5FcZ@i=x7Q>6ROyzNF7c|#OpGIC8&>+Gl5ks7-Si!`S+f1pC&ZXb(9(Fo8-!11WI;dqESg4#j zF>vpw6lK2guZ^ft9-|Lpj{O2CIkto6^TEn7sJWveME+tOR70soFP25)w)Mm4o5YDZS ztKqax{tGl`w1e`yd3&-2NoT6V=Pmo4I2wz=$m&9kxwMaiaooG#%&rR4(oMN=3c|** zKNL6`f_2&Sc-yJIPYW-WM)q5OUN8f7m? zIyYRctk4EywjeWayt}|YE(7Fy$2>B|Dd&6c50Ik!5apLuIYnX+bwO-udlNJccA?%D zV6zL%8x6cO1e?U}A4jMVIRh0u1dE&qFZ-+A-uR0ME@F9GQG z^nbf*0PM5v&Gjwpgq(Es|0RL@r+GbkSR9ld#b4%@G3RrgsyWqO=V7e^cPCFIk`lUs;YxM3uiIR@T zcJ^(b0&bt%EKeEyB6L|qmj`)kM2E-#FnY{#SH`7 zI)rJ*eyiOHl;`|HeTZj1L9Pi55k(l-{r)gDiNWW4>{{>?3E2{>z0_hxMnzxL5o!~h z?(*SC#or~}%vjN9s$`2@_pV@4(SQmv&nWKA{rP+HeeQOGM(>q&>%cQ2xZaZJ&wh5;?I0GNna z|F%{Bw21ui(FIsatbP?Xi&OZQYO9CE?6@okhNavwxF8(1rM?#d9Ac^t8aiDP;fXHh zF!iqLghO}68vI)5$97Sj>-|Wg^aU2%O7S%TSHRwneYEkarPj0D;{oD*dqf!1mfrcP z68shkbw5HCxi0h|lBT$FboBZiil&(I#<4xL5HvQDCZnA>M*NyN1F_AGJ4BTp{vMn= zYS)BgN;v4!O(||-E@t5z^YG#`2qX}zTa+~gP zUB820#`Y8p!;aE1gc?#ErsB~Y5?}m63Kh2b>b)G&G9~#MuKngPKfPH`0JU+sW}W(y z&8tziaZcUH9s-oGRqie)^%*vcPgzz+jSUV}nKp0&vUxdZk(RKO8X8wV1Wbj1Pz^O~ zdHdy<`b82gZ48S@%VfKJueW@@e8!^++56+Kl!ipYdp?iDY?sT$(&~D*S++89xu4sk z5FW?pECC(Js~VR_rM?S1_5}m>JwIF*ckm~Si39S|<^s#$rIg*dPwS7VEgwoHv<5zb zHKfvE2Dl@8{Z5W@INZg6@4Y~jB+IZ;t2Q}Up2cNT~97Xk~Z|Jo|u|(nGJk_$d zd_~GVJ1!TUyL}>4LFpWHP=dj6Ug!GT*;iFzMjd#(*Q`g1*MwB1@> z;_>u+gs=*F0}8#rGsle35dn-l8h6F-%#Q1f3yv!k;M8-WuA(2bby@(Yx^!d}FdgvY zBv!j(SZL715n7DZZDB86wNv2^x^Q6h&?{@|*k6~UbI-2P*ioZq22WJ`TlL|UOZ=>? zp8X2vHouLm!Cb@8#pkDtqa9MgIK>im5|$;rH*kH8y-D^KNg9K;L-i=x%7ct^&6k+< z`t0}tqM;->6V-J=KILK)rf;XYsr$nL{w=FM+NPTALmexS^eC-6pW-k}Dg1x1d)JX0 z>(ObtS2=%dYGWO%>a!}@` zzeef8{NuD(XS;d8ko|0&AoQJBBAe(s-fPSd)2ITI)><4)Y)opoMQ-T7zKnJA4%mYaXwF-o2uMW5%coztRNCf z3}-QmHDjp=vnVzI-SJ7II2wgRYGF~;lJ)^B3x(`2Nr)y>=Zuuerf1&?E52#IfsKwt z4@yT7e`DnT!P;+b8S3O{5{62T&l$RO(&J5`JjS*(C52_$a%Fq7jErBloRe4Jr;?Fq zXf_tIZHzvi&d z;xyIFGmH=b|2#;jjm4?}fXhA*;FKKjcVG|{AVBQ^&@gUq{sj#fHUBCA53d(RN=TlM zMod~5pt||rx6RypU;Na1kq7*KKI(J%DGm0Y+obrU#e{|A6Q$G?dI z28v%wGT{2BhRomH0WgdHQriB!<4@I@zq|40dw4FpfXiRxYW~bP@E7L!$3WmdC?KFu zfV+R{Ha-^|z)I;i07^F6R#y5pLQeX+_Ww~8eOayTeP!EX0Mr8DNAwH{xT1jhEvlFx zKsCqAQd{qjh1N?vooi#N9l-hk>-8Vr5YLdvfY8M`?uWQOHAFl z!(?j!CIZ|aO7YK_Jb>Q)8%)4r(9GTzpsXrvY^KkrtE+EoE2V9rZTP-QFo@{>i@^-{w+t_RVMPH+CH`kK zq?KS?PXU^N1(3huzq^Vg;IF@F27tt^owk`7@t*>sFKc_`qMC37sO>bMwm-AUJQpp% z`27tYzon(!PyIQopNT#Jd)jA##+T4WK6(Z@0K93y@69tV;41m;Z=wJ5s{cn_^PK6L z6aj4q1o*K3oK2sL2kmbGB`ppAXLnn=U7^4LD8MfRIv3$H65t9EU?Tm^ga5mBzaMfC z=J?6DfJtE=@YV?a3(g2IJN^dl&vyAe+RLP?&wyPYev2mZ`xLA%o8)DRt7qIYjlaSD zUBauE&@a;xJwwZD{TBMqnejJCie5s$%nI`iO{e>xZ|a{j_HVzdzXJaBnfwXxvmgB| zfN}Ioi39-t(pW$BX~PNCcl?;f2oW6%mQNn7nc7ImE4y+FSS~qd1f5`!t+aK zda)&X3Hwr_^cj}L=`XPV-f{gCmEV^{FC_(^iH_X#O|CgitOXQdC!q3RYIsZ5E?;HB1tI{(jU&&uE z|N2_~#&PLo?O(ctJTnQD{{yDKaS(aQ^zz{NnJKXPA29u&v*61U#Ap2F+JAumcjt*O zALZo%&NJ25`hQII`{SIKR4)zZ&s42Ve@FE{%;+!SUs`~l;pJNX4*t*a_j`NrOOlsH zv}Y3gFMlEV_XPh-ul_&gke7y$XLz8_|19bLmzm_>b^W(dZgeiU?c<>M2Z3b7YOM80h6n@EC2ui literal 0 HcmV?d00001 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 000000000..3b6c26cf7 --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Thu Mar 02 17:03:11 PST 2017 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-bin.zip diff --git a/example/android/gradlew b/gradlew similarity index 83% rename from example/android/gradlew rename to gradlew index 91a7e269e..4453ccea3 100755 --- a/example/android/gradlew +++ b/gradlew @@ -1,4 +1,4 @@ -#!/usr/bin/env bash +#!/usr/bin/env sh ############################################################################## ## @@ -6,12 +6,30 @@ ## ############################################################################## -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS="" +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null APP_NAME="Gradle" APP_BASE_NAME=`basename "$0"` +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD="maximum" @@ -30,6 +48,7 @@ die ( ) { cygwin=false msys=false darwin=false +nonstop=false case "`uname`" in CYGWIN* ) cygwin=true @@ -40,31 +59,11 @@ case "`uname`" in MINGW* ) msys=true ;; + NONSTOP* ) + nonstop=true + ;; esac -# For Cygwin, ensure paths are in UNIX format before anything is touched. -if $cygwin ; then - [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` -fi - -# Attempt to set APP_HOME -# Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi -done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >&- -APP_HOME="`pwd -P`" -cd "$SAVED" >&- - CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar # Determine the Java command to use to start the JVM. @@ -90,7 +89,7 @@ location of your Java installation." fi # Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then MAX_FD_LIMIT=`ulimit -H -n` if [ $? -eq 0 ] ; then if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then @@ -114,6 +113,7 @@ fi if $cygwin ; then APP_HOME=`cygpath --path --mixed "$APP_HOME"` CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` # We build the pattern for arguments to be converted via cygpath ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` @@ -154,11 +154,19 @@ if $cygwin ; then esac fi -# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules -function splitJvmOpts() { - JVM_OPTS=("$@") +# Escape application args +save ( ) { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " } -eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS -JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" +APP_ARGS=$(save "$@") + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong +if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then + cd "$(dirname "$0")" +fi -exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" +exec "$JAVACMD" "$@" diff --git a/example/android/gradlew.bat b/gradlew.bat similarity index 88% rename from example/android/gradlew.bat rename to gradlew.bat index aec99730b..e95643d6a 100644 --- a/example/android/gradlew.bat +++ b/gradlew.bat @@ -8,14 +8,14 @@ @rem Set local scope for the variables with windows NT shell if "%OS%"=="Windows_NT" setlocal -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS= - set DIRNAME=%~dp0 if "%DIRNAME%" == "" set DIRNAME=. set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + @rem Find java.exe if defined JAVA_HOME goto findJavaFromJavaHome @@ -46,10 +46,9 @@ echo location of your Java installation. goto fail :init -@rem Get command-line arguments, handling Windowz variants +@rem Get command-line arguments, handling Windows variants if not "%OS%" == "Windows_NT" goto win9xME_args -if "%@eval[2+2]" == "4" goto 4NT_args :win9xME_args @rem Slurp the command line arguments. @@ -60,11 +59,6 @@ set _SKIP=2 if "x%~1" == "x" goto execute set CMD_LINE_ARGS=%* -goto execute - -:4NT_args -@rem Get arguments from the 4NT Shell from JP Software -set CMD_LINE_ARGS=%$ :execute @rem Setup the command line diff --git a/index.js b/index.js index b2d7d79e1..207d0119d 100644 --- a/index.js +++ b/index.js @@ -1,3 +1,3 @@ -import MapView from './components/MapView'; +import MapView from './lib/components/MapView'; module.exports = MapView; diff --git a/lib/android/build.gradle b/lib/android/build.gradle new file mode 100644 index 000000000..062f040ca --- /dev/null +++ b/lib/android/build.gradle @@ -0,0 +1,40 @@ +apply plugin: 'com.android.library' +apply from: 'gradle-maven-push.gradle' + +android { + compileSdkVersion 25 + buildToolsVersion "25.0.2" + + defaultConfig { + minSdkVersion 16 + targetSdkVersion 25 + } + + packagingOptions { + exclude 'META-INF/LICENSE' + exclude 'META-INF/DEPENDENCIES.txt' + exclude 'META-INF/LICENSE.txt' + exclude 'META-INF/NOTICE.txt' + exclude 'META-INF/NOTICE' + exclude 'META-INF/DEPENDENCIES' + exclude 'META-INF/notice.txt' + exclude 'META-INF/license.txt' + exclude 'META-INF/dependencies.txt' + exclude 'META-INF/LGPL2.1' + } + + lintOptions { + disable 'InvalidPackage' + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_7 + targetCompatibility JavaVersion.VERSION_1_7 + } +} + +dependencies { + provided "com.facebook.react:react-native:+" + compile "com.google.android.gms:play-services-base:10.0.1" + compile "com.google.android.gms:play-services-maps:10.0.1" +} diff --git a/android/gradle-maven-push.gradle b/lib/android/gradle-maven-push.gradle similarity index 100% rename from android/gradle-maven-push.gradle rename to lib/android/gradle-maven-push.gradle diff --git a/android/gradle.properties b/lib/android/gradle.properties similarity index 100% rename from android/gradle.properties rename to lib/android/gradle.properties diff --git a/android/gradle/wrapper/gradle-wrapper.jar b/lib/android/gradle/wrapper/gradle-wrapper.jar similarity index 100% rename from android/gradle/wrapper/gradle-wrapper.jar rename to lib/android/gradle/wrapper/gradle-wrapper.jar diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/lib/android/gradle/wrapper/gradle-wrapper.properties similarity index 100% rename from android/gradle/wrapper/gradle-wrapper.properties rename to lib/android/gradle/wrapper/gradle-wrapper.properties diff --git a/android/gradlew b/lib/android/gradlew similarity index 100% rename from android/gradlew rename to lib/android/gradlew diff --git a/android/gradlew.bat b/lib/android/gradlew.bat similarity index 100% rename from android/gradlew.bat rename to lib/android/gradlew.bat diff --git a/android/src/main/AndroidManifest.xml b/lib/android/src/main/AndroidManifest.xml similarity index 100% rename from android/src/main/AndroidManifest.xml rename to lib/android/src/main/AndroidManifest.xml diff --git a/android/src/main/java/com/airbnb/android/react/maps/AirMapCallout.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapCallout.java similarity index 100% rename from android/src/main/java/com/airbnb/android/react/maps/AirMapCallout.java rename to lib/android/src/main/java/com/airbnb/android/react/maps/AirMapCallout.java diff --git a/android/src/main/java/com/airbnb/android/react/maps/AirMapCalloutManager.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapCalloutManager.java similarity index 100% rename from android/src/main/java/com/airbnb/android/react/maps/AirMapCalloutManager.java rename to lib/android/src/main/java/com/airbnb/android/react/maps/AirMapCalloutManager.java diff --git a/android/src/main/java/com/airbnb/android/react/maps/AirMapCircle.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapCircle.java similarity index 100% rename from android/src/main/java/com/airbnb/android/react/maps/AirMapCircle.java rename to lib/android/src/main/java/com/airbnb/android/react/maps/AirMapCircle.java diff --git a/android/src/main/java/com/airbnb/android/react/maps/AirMapCircleManager.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapCircleManager.java similarity index 100% rename from android/src/main/java/com/airbnb/android/react/maps/AirMapCircleManager.java rename to lib/android/src/main/java/com/airbnb/android/react/maps/AirMapCircleManager.java diff --git a/android/src/main/java/com/airbnb/android/react/maps/AirMapFeature.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapFeature.java similarity index 100% rename from android/src/main/java/com/airbnb/android/react/maps/AirMapFeature.java rename to lib/android/src/main/java/com/airbnb/android/react/maps/AirMapFeature.java diff --git a/android/src/main/java/com/airbnb/android/react/maps/AirMapLiteManager.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapLiteManager.java similarity index 100% rename from android/src/main/java/com/airbnb/android/react/maps/AirMapLiteManager.java rename to lib/android/src/main/java/com/airbnb/android/react/maps/AirMapLiteManager.java diff --git a/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java similarity index 100% rename from android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java rename to lib/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java diff --git a/android/src/main/java/com/airbnb/android/react/maps/AirMapMarker.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapMarker.java similarity index 100% rename from android/src/main/java/com/airbnb/android/react/maps/AirMapMarker.java rename to lib/android/src/main/java/com/airbnb/android/react/maps/AirMapMarker.java diff --git a/android/src/main/java/com/airbnb/android/react/maps/AirMapMarkerManager.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapMarkerManager.java similarity index 100% rename from android/src/main/java/com/airbnb/android/react/maps/AirMapMarkerManager.java rename to lib/android/src/main/java/com/airbnb/android/react/maps/AirMapMarkerManager.java diff --git a/android/src/main/java/com/airbnb/android/react/maps/AirMapModule.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapModule.java similarity index 100% rename from android/src/main/java/com/airbnb/android/react/maps/AirMapModule.java rename to lib/android/src/main/java/com/airbnb/android/react/maps/AirMapModule.java diff --git a/android/src/main/java/com/airbnb/android/react/maps/AirMapPolygon.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapPolygon.java similarity index 100% rename from android/src/main/java/com/airbnb/android/react/maps/AirMapPolygon.java rename to lib/android/src/main/java/com/airbnb/android/react/maps/AirMapPolygon.java diff --git a/android/src/main/java/com/airbnb/android/react/maps/AirMapPolygonManager.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapPolygonManager.java similarity index 100% rename from android/src/main/java/com/airbnb/android/react/maps/AirMapPolygonManager.java rename to lib/android/src/main/java/com/airbnb/android/react/maps/AirMapPolygonManager.java diff --git a/android/src/main/java/com/airbnb/android/react/maps/AirMapPolyline.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapPolyline.java similarity index 100% rename from android/src/main/java/com/airbnb/android/react/maps/AirMapPolyline.java rename to lib/android/src/main/java/com/airbnb/android/react/maps/AirMapPolyline.java diff --git a/android/src/main/java/com/airbnb/android/react/maps/AirMapPolylineManager.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapPolylineManager.java similarity index 100% rename from android/src/main/java/com/airbnb/android/react/maps/AirMapPolylineManager.java rename to lib/android/src/main/java/com/airbnb/android/react/maps/AirMapPolylineManager.java diff --git a/android/src/main/java/com/airbnb/android/react/maps/AirMapUrlTile.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapUrlTile.java similarity index 100% rename from android/src/main/java/com/airbnb/android/react/maps/AirMapUrlTile.java rename to lib/android/src/main/java/com/airbnb/android/react/maps/AirMapUrlTile.java diff --git a/android/src/main/java/com/airbnb/android/react/maps/AirMapUrlTileManager.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapUrlTileManager.java similarity index 100% rename from android/src/main/java/com/airbnb/android/react/maps/AirMapUrlTileManager.java rename to lib/android/src/main/java/com/airbnb/android/react/maps/AirMapUrlTileManager.java diff --git a/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java similarity index 100% rename from android/src/main/java/com/airbnb/android/react/maps/AirMapView.java rename to lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java diff --git a/android/src/main/java/com/airbnb/android/react/maps/LatLngBoundsUtils.java b/lib/android/src/main/java/com/airbnb/android/react/maps/LatLngBoundsUtils.java similarity index 100% rename from android/src/main/java/com/airbnb/android/react/maps/LatLngBoundsUtils.java rename to lib/android/src/main/java/com/airbnb/android/react/maps/LatLngBoundsUtils.java diff --git a/android/src/main/java/com/airbnb/android/react/maps/MapsPackage.java b/lib/android/src/main/java/com/airbnb/android/react/maps/MapsPackage.java similarity index 100% rename from android/src/main/java/com/airbnb/android/react/maps/MapsPackage.java rename to lib/android/src/main/java/com/airbnb/android/react/maps/MapsPackage.java diff --git a/android/src/main/java/com/airbnb/android/react/maps/RegionChangeEvent.java b/lib/android/src/main/java/com/airbnb/android/react/maps/RegionChangeEvent.java similarity index 100% rename from android/src/main/java/com/airbnb/android/react/maps/RegionChangeEvent.java rename to lib/android/src/main/java/com/airbnb/android/react/maps/RegionChangeEvent.java diff --git a/android/src/main/java/com/airbnb/android/react/maps/SizeReportingShadowNode.java b/lib/android/src/main/java/com/airbnb/android/react/maps/SizeReportingShadowNode.java similarity index 100% rename from android/src/main/java/com/airbnb/android/react/maps/SizeReportingShadowNode.java rename to lib/android/src/main/java/com/airbnb/android/react/maps/SizeReportingShadowNode.java diff --git a/components/AnimatedRegion.js b/lib/components/AnimatedRegion.js similarity index 100% rename from components/AnimatedRegion.js rename to lib/components/AnimatedRegion.js diff --git a/components/MapCallout.js b/lib/components/MapCallout.js similarity index 100% rename from components/MapCallout.js rename to lib/components/MapCallout.js diff --git a/components/MapCircle.js b/lib/components/MapCircle.js similarity index 100% rename from components/MapCircle.js rename to lib/components/MapCircle.js diff --git a/components/MapMarker.js b/lib/components/MapMarker.js similarity index 100% rename from components/MapMarker.js rename to lib/components/MapMarker.js diff --git a/components/MapPolygon.js b/lib/components/MapPolygon.js similarity index 100% rename from components/MapPolygon.js rename to lib/components/MapPolygon.js diff --git a/components/MapPolyline.js b/lib/components/MapPolyline.js similarity index 100% rename from components/MapPolyline.js rename to lib/components/MapPolyline.js diff --git a/components/MapUrlTile.js b/lib/components/MapUrlTile.js similarity index 100% rename from components/MapUrlTile.js rename to lib/components/MapUrlTile.js diff --git a/components/MapView.js b/lib/components/MapView.js similarity index 100% rename from components/MapView.js rename to lib/components/MapView.js diff --git a/components/ProviderConstants.js b/lib/components/ProviderConstants.js similarity index 100% rename from components/ProviderConstants.js rename to lib/components/ProviderConstants.js diff --git a/components/decorateMapComponent.js b/lib/components/decorateMapComponent.js similarity index 100% rename from components/decorateMapComponent.js rename to lib/components/decorateMapComponent.js diff --git a/ios/AirGoogleMaps/AIRGMSMarker.h b/lib/ios/AirGoogleMaps/AIRGMSMarker.h similarity index 100% rename from ios/AirGoogleMaps/AIRGMSMarker.h rename to lib/ios/AirGoogleMaps/AIRGMSMarker.h diff --git a/ios/AirGoogleMaps/AIRGMSMarker.m b/lib/ios/AirGoogleMaps/AIRGMSMarker.m similarity index 100% rename from ios/AirGoogleMaps/AIRGMSMarker.m rename to lib/ios/AirGoogleMaps/AIRGMSMarker.m diff --git a/ios/AirGoogleMaps/AIRGMSPolygon.h b/lib/ios/AirGoogleMaps/AIRGMSPolygon.h similarity index 100% rename from ios/AirGoogleMaps/AIRGMSPolygon.h rename to lib/ios/AirGoogleMaps/AIRGMSPolygon.h diff --git a/ios/AirGoogleMaps/AIRGMSPolygon.m b/lib/ios/AirGoogleMaps/AIRGMSPolygon.m similarity index 100% rename from ios/AirGoogleMaps/AIRGMSPolygon.m rename to lib/ios/AirGoogleMaps/AIRGMSPolygon.m diff --git a/ios/AirGoogleMaps/AIRGoogleMap.h b/lib/ios/AirGoogleMaps/AIRGoogleMap.h similarity index 100% rename from ios/AirGoogleMaps/AIRGoogleMap.h rename to lib/ios/AirGoogleMaps/AIRGoogleMap.h diff --git a/ios/AirGoogleMaps/AIRGoogleMap.m b/lib/ios/AirGoogleMaps/AIRGoogleMap.m similarity index 100% rename from ios/AirGoogleMaps/AIRGoogleMap.m rename to lib/ios/AirGoogleMaps/AIRGoogleMap.m diff --git a/ios/AirGoogleMaps/AIRGoogleMapCallout.h b/lib/ios/AirGoogleMaps/AIRGoogleMapCallout.h similarity index 100% rename from ios/AirGoogleMaps/AIRGoogleMapCallout.h rename to lib/ios/AirGoogleMaps/AIRGoogleMapCallout.h diff --git a/ios/AirGoogleMaps/AIRGoogleMapCallout.m b/lib/ios/AirGoogleMaps/AIRGoogleMapCallout.m similarity index 100% rename from ios/AirGoogleMaps/AIRGoogleMapCallout.m rename to lib/ios/AirGoogleMaps/AIRGoogleMapCallout.m diff --git a/ios/AirGoogleMaps/AIRGoogleMapCalloutManager.h b/lib/ios/AirGoogleMaps/AIRGoogleMapCalloutManager.h similarity index 100% rename from ios/AirGoogleMaps/AIRGoogleMapCalloutManager.h rename to lib/ios/AirGoogleMaps/AIRGoogleMapCalloutManager.h diff --git a/ios/AirGoogleMaps/AIRGoogleMapCalloutManager.m b/lib/ios/AirGoogleMaps/AIRGoogleMapCalloutManager.m similarity index 100% rename from ios/AirGoogleMaps/AIRGoogleMapCalloutManager.m rename to lib/ios/AirGoogleMaps/AIRGoogleMapCalloutManager.m diff --git a/ios/AirGoogleMaps/AIRGoogleMapCircle.h b/lib/ios/AirGoogleMaps/AIRGoogleMapCircle.h similarity index 100% rename from ios/AirGoogleMaps/AIRGoogleMapCircle.h rename to lib/ios/AirGoogleMaps/AIRGoogleMapCircle.h diff --git a/ios/AirGoogleMaps/AIRGoogleMapCircle.m b/lib/ios/AirGoogleMaps/AIRGoogleMapCircle.m similarity index 100% rename from ios/AirGoogleMaps/AIRGoogleMapCircle.m rename to lib/ios/AirGoogleMaps/AIRGoogleMapCircle.m diff --git a/ios/AirGoogleMaps/AIRGoogleMapCircleManager.h b/lib/ios/AirGoogleMaps/AIRGoogleMapCircleManager.h similarity index 100% rename from ios/AirGoogleMaps/AIRGoogleMapCircleManager.h rename to lib/ios/AirGoogleMaps/AIRGoogleMapCircleManager.h diff --git a/ios/AirGoogleMaps/AIRGoogleMapCircleManager.m b/lib/ios/AirGoogleMaps/AIRGoogleMapCircleManager.m similarity index 100% rename from ios/AirGoogleMaps/AIRGoogleMapCircleManager.m rename to lib/ios/AirGoogleMaps/AIRGoogleMapCircleManager.m diff --git a/ios/AirGoogleMaps/AIRGoogleMapManager.h b/lib/ios/AirGoogleMaps/AIRGoogleMapManager.h similarity index 100% rename from ios/AirGoogleMaps/AIRGoogleMapManager.h rename to lib/ios/AirGoogleMaps/AIRGoogleMapManager.h diff --git a/ios/AirGoogleMaps/AIRGoogleMapManager.m b/lib/ios/AirGoogleMaps/AIRGoogleMapManager.m similarity index 100% rename from ios/AirGoogleMaps/AIRGoogleMapManager.m rename to lib/ios/AirGoogleMaps/AIRGoogleMapManager.m diff --git a/ios/AirGoogleMaps/AIRGoogleMapMarker.h b/lib/ios/AirGoogleMaps/AIRGoogleMapMarker.h similarity index 100% rename from ios/AirGoogleMaps/AIRGoogleMapMarker.h rename to lib/ios/AirGoogleMaps/AIRGoogleMapMarker.h diff --git a/ios/AirGoogleMaps/AIRGoogleMapMarker.m b/lib/ios/AirGoogleMaps/AIRGoogleMapMarker.m similarity index 100% rename from ios/AirGoogleMaps/AIRGoogleMapMarker.m rename to lib/ios/AirGoogleMaps/AIRGoogleMapMarker.m diff --git a/ios/AirGoogleMaps/AIRGoogleMapMarkerManager.h b/lib/ios/AirGoogleMaps/AIRGoogleMapMarkerManager.h similarity index 100% rename from ios/AirGoogleMaps/AIRGoogleMapMarkerManager.h rename to lib/ios/AirGoogleMaps/AIRGoogleMapMarkerManager.h diff --git a/ios/AirGoogleMaps/AIRGoogleMapMarkerManager.m b/lib/ios/AirGoogleMaps/AIRGoogleMapMarkerManager.m similarity index 100% rename from ios/AirGoogleMaps/AIRGoogleMapMarkerManager.m rename to lib/ios/AirGoogleMaps/AIRGoogleMapMarkerManager.m diff --git a/ios/AirGoogleMaps/AIRGoogleMapPolygon.h b/lib/ios/AirGoogleMaps/AIRGoogleMapPolygon.h similarity index 100% rename from ios/AirGoogleMaps/AIRGoogleMapPolygon.h rename to lib/ios/AirGoogleMaps/AIRGoogleMapPolygon.h diff --git a/ios/AirGoogleMaps/AIRGoogleMapPolygon.m b/lib/ios/AirGoogleMaps/AIRGoogleMapPolygon.m similarity index 100% rename from ios/AirGoogleMaps/AIRGoogleMapPolygon.m rename to lib/ios/AirGoogleMaps/AIRGoogleMapPolygon.m diff --git a/ios/AirGoogleMaps/AIRGoogleMapPolygonManager.h b/lib/ios/AirGoogleMaps/AIRGoogleMapPolygonManager.h similarity index 100% rename from ios/AirGoogleMaps/AIRGoogleMapPolygonManager.h rename to lib/ios/AirGoogleMaps/AIRGoogleMapPolygonManager.h diff --git a/ios/AirGoogleMaps/AIRGoogleMapPolygonManager.m b/lib/ios/AirGoogleMaps/AIRGoogleMapPolygonManager.m similarity index 100% rename from ios/AirGoogleMaps/AIRGoogleMapPolygonManager.m rename to lib/ios/AirGoogleMaps/AIRGoogleMapPolygonManager.m diff --git a/ios/AirGoogleMaps/AIRGoogleMapPolyline.h b/lib/ios/AirGoogleMaps/AIRGoogleMapPolyline.h similarity index 100% rename from ios/AirGoogleMaps/AIRGoogleMapPolyline.h rename to lib/ios/AirGoogleMaps/AIRGoogleMapPolyline.h diff --git a/ios/AirGoogleMaps/AIRGoogleMapPolyline.m b/lib/ios/AirGoogleMaps/AIRGoogleMapPolyline.m similarity index 100% rename from ios/AirGoogleMaps/AIRGoogleMapPolyline.m rename to lib/ios/AirGoogleMaps/AIRGoogleMapPolyline.m diff --git a/ios/AirGoogleMaps/AIRGoogleMapPolylineManager.h b/lib/ios/AirGoogleMaps/AIRGoogleMapPolylineManager.h similarity index 100% rename from ios/AirGoogleMaps/AIRGoogleMapPolylineManager.h rename to lib/ios/AirGoogleMaps/AIRGoogleMapPolylineManager.h diff --git a/ios/AirGoogleMaps/AIRGoogleMapPolylineManager.m b/lib/ios/AirGoogleMaps/AIRGoogleMapPolylineManager.m similarity index 100% rename from ios/AirGoogleMaps/AIRGoogleMapPolylineManager.m rename to lib/ios/AirGoogleMaps/AIRGoogleMapPolylineManager.m diff --git a/ios/AirGoogleMaps/AIRGoogleMapURLTileManager.m b/lib/ios/AirGoogleMaps/AIRGoogleMapURLTileManager.m similarity index 100% rename from ios/AirGoogleMaps/AIRGoogleMapURLTileManager.m rename to lib/ios/AirGoogleMaps/AIRGoogleMapURLTileManager.m diff --git a/ios/AirGoogleMaps/AIRGoogleMapUrlTile.h b/lib/ios/AirGoogleMaps/AIRGoogleMapUrlTile.h similarity index 100% rename from ios/AirGoogleMaps/AIRGoogleMapUrlTile.h rename to lib/ios/AirGoogleMaps/AIRGoogleMapUrlTile.h diff --git a/ios/AirGoogleMaps/AIRGoogleMapUrlTile.m b/lib/ios/AirGoogleMaps/AIRGoogleMapUrlTile.m similarity index 100% rename from ios/AirGoogleMaps/AIRGoogleMapUrlTile.m rename to lib/ios/AirGoogleMaps/AIRGoogleMapUrlTile.m diff --git a/ios/AirGoogleMaps/AIRGoogleMapUrlTileManager.h b/lib/ios/AirGoogleMaps/AIRGoogleMapUrlTileManager.h similarity index 100% rename from ios/AirGoogleMaps/AIRGoogleMapUrlTileManager.h rename to lib/ios/AirGoogleMaps/AIRGoogleMapUrlTileManager.h diff --git a/ios/AirGoogleMaps/DummyView.h b/lib/ios/AirGoogleMaps/DummyView.h similarity index 100% rename from ios/AirGoogleMaps/DummyView.h rename to lib/ios/AirGoogleMaps/DummyView.h diff --git a/ios/AirGoogleMaps/DummyView.m b/lib/ios/AirGoogleMaps/DummyView.m similarity index 100% rename from ios/AirGoogleMaps/DummyView.m rename to lib/ios/AirGoogleMaps/DummyView.m diff --git a/ios/AirGoogleMaps/RCTConvert+GMSMapViewType.h b/lib/ios/AirGoogleMaps/RCTConvert+GMSMapViewType.h similarity index 100% rename from ios/AirGoogleMaps/RCTConvert+GMSMapViewType.h rename to lib/ios/AirGoogleMaps/RCTConvert+GMSMapViewType.h diff --git a/ios/AirGoogleMaps/RCTConvert+GMSMapViewType.m b/lib/ios/AirGoogleMaps/RCTConvert+GMSMapViewType.m similarity index 100% rename from ios/AirGoogleMaps/RCTConvert+GMSMapViewType.m rename to lib/ios/AirGoogleMaps/RCTConvert+GMSMapViewType.m diff --git a/ios/AirMaps.xcodeproj/project.pbxproj b/lib/ios/AirMaps.xcodeproj/project.pbxproj similarity index 100% rename from ios/AirMaps.xcodeproj/project.pbxproj rename to lib/ios/AirMaps.xcodeproj/project.pbxproj diff --git a/ios/AirMaps/AIRMap.h b/lib/ios/AirMaps/AIRMap.h similarity index 100% rename from ios/AirMaps/AIRMap.h rename to lib/ios/AirMaps/AIRMap.h diff --git a/ios/AirMaps/AIRMap.m b/lib/ios/AirMaps/AIRMap.m similarity index 100% rename from ios/AirMaps/AIRMap.m rename to lib/ios/AirMaps/AIRMap.m diff --git a/ios/AirMaps/AIRMapCallout.h b/lib/ios/AirMaps/AIRMapCallout.h similarity index 100% rename from ios/AirMaps/AIRMapCallout.h rename to lib/ios/AirMaps/AIRMapCallout.h diff --git a/ios/AirMaps/AIRMapCallout.m b/lib/ios/AirMaps/AIRMapCallout.m similarity index 100% rename from ios/AirMaps/AIRMapCallout.m rename to lib/ios/AirMaps/AIRMapCallout.m diff --git a/ios/AirMaps/AIRMapCalloutManager.h b/lib/ios/AirMaps/AIRMapCalloutManager.h similarity index 100% rename from ios/AirMaps/AIRMapCalloutManager.h rename to lib/ios/AirMaps/AIRMapCalloutManager.h diff --git a/ios/AirMaps/AIRMapCalloutManager.m b/lib/ios/AirMaps/AIRMapCalloutManager.m similarity index 100% rename from ios/AirMaps/AIRMapCalloutManager.m rename to lib/ios/AirMaps/AIRMapCalloutManager.m diff --git a/ios/AirMaps/AIRMapCircle.h b/lib/ios/AirMaps/AIRMapCircle.h similarity index 100% rename from ios/AirMaps/AIRMapCircle.h rename to lib/ios/AirMaps/AIRMapCircle.h diff --git a/ios/AirMaps/AIRMapCircle.m b/lib/ios/AirMaps/AIRMapCircle.m similarity index 100% rename from ios/AirMaps/AIRMapCircle.m rename to lib/ios/AirMaps/AIRMapCircle.m diff --git a/ios/AirMaps/AIRMapCircleManager.h b/lib/ios/AirMaps/AIRMapCircleManager.h similarity index 100% rename from ios/AirMaps/AIRMapCircleManager.h rename to lib/ios/AirMaps/AIRMapCircleManager.h diff --git a/ios/AirMaps/AIRMapCircleManager.m b/lib/ios/AirMaps/AIRMapCircleManager.m similarity index 100% rename from ios/AirMaps/AIRMapCircleManager.m rename to lib/ios/AirMaps/AIRMapCircleManager.m diff --git a/ios/AirMaps/AIRMapCoordinate.h b/lib/ios/AirMaps/AIRMapCoordinate.h similarity index 100% rename from ios/AirMaps/AIRMapCoordinate.h rename to lib/ios/AirMaps/AIRMapCoordinate.h diff --git a/ios/AirMaps/AIRMapCoordinate.m b/lib/ios/AirMaps/AIRMapCoordinate.m similarity index 100% rename from ios/AirMaps/AIRMapCoordinate.m rename to lib/ios/AirMaps/AIRMapCoordinate.m diff --git a/ios/AirMaps/AIRMapManager.h b/lib/ios/AirMaps/AIRMapManager.h similarity index 100% rename from ios/AirMaps/AIRMapManager.h rename to lib/ios/AirMaps/AIRMapManager.h diff --git a/ios/AirMaps/AIRMapManager.m b/lib/ios/AirMaps/AIRMapManager.m similarity index 100% rename from ios/AirMaps/AIRMapManager.m rename to lib/ios/AirMaps/AIRMapManager.m diff --git a/ios/AirMaps/AIRMapMarker.h b/lib/ios/AirMaps/AIRMapMarker.h similarity index 100% rename from ios/AirMaps/AIRMapMarker.h rename to lib/ios/AirMaps/AIRMapMarker.h diff --git a/ios/AirMaps/AIRMapMarker.m b/lib/ios/AirMaps/AIRMapMarker.m similarity index 100% rename from ios/AirMaps/AIRMapMarker.m rename to lib/ios/AirMaps/AIRMapMarker.m diff --git a/ios/AirMaps/AIRMapMarkerManager.h b/lib/ios/AirMaps/AIRMapMarkerManager.h similarity index 100% rename from ios/AirMaps/AIRMapMarkerManager.h rename to lib/ios/AirMaps/AIRMapMarkerManager.h diff --git a/ios/AirMaps/AIRMapMarkerManager.m b/lib/ios/AirMaps/AIRMapMarkerManager.m similarity index 100% rename from ios/AirMaps/AIRMapMarkerManager.m rename to lib/ios/AirMaps/AIRMapMarkerManager.m diff --git a/ios/AirMaps/AIRMapPolygon.h b/lib/ios/AirMaps/AIRMapPolygon.h similarity index 100% rename from ios/AirMaps/AIRMapPolygon.h rename to lib/ios/AirMaps/AIRMapPolygon.h diff --git a/ios/AirMaps/AIRMapPolygon.m b/lib/ios/AirMaps/AIRMapPolygon.m similarity index 100% rename from ios/AirMaps/AIRMapPolygon.m rename to lib/ios/AirMaps/AIRMapPolygon.m diff --git a/ios/AirMaps/AIRMapPolygonManager.h b/lib/ios/AirMaps/AIRMapPolygonManager.h similarity index 100% rename from ios/AirMaps/AIRMapPolygonManager.h rename to lib/ios/AirMaps/AIRMapPolygonManager.h diff --git a/ios/AirMaps/AIRMapPolygonManager.m b/lib/ios/AirMaps/AIRMapPolygonManager.m similarity index 100% rename from ios/AirMaps/AIRMapPolygonManager.m rename to lib/ios/AirMaps/AIRMapPolygonManager.m diff --git a/ios/AirMaps/AIRMapPolyline.h b/lib/ios/AirMaps/AIRMapPolyline.h similarity index 100% rename from ios/AirMaps/AIRMapPolyline.h rename to lib/ios/AirMaps/AIRMapPolyline.h diff --git a/ios/AirMaps/AIRMapPolyline.m b/lib/ios/AirMaps/AIRMapPolyline.m similarity index 100% rename from ios/AirMaps/AIRMapPolyline.m rename to lib/ios/AirMaps/AIRMapPolyline.m diff --git a/ios/AirMaps/AIRMapPolylineManager.h b/lib/ios/AirMaps/AIRMapPolylineManager.h similarity index 100% rename from ios/AirMaps/AIRMapPolylineManager.h rename to lib/ios/AirMaps/AIRMapPolylineManager.h diff --git a/ios/AirMaps/AIRMapPolylineManager.m b/lib/ios/AirMaps/AIRMapPolylineManager.m similarity index 100% rename from ios/AirMaps/AIRMapPolylineManager.m rename to lib/ios/AirMaps/AIRMapPolylineManager.m diff --git a/ios/AirMaps/AIRMapSnapshot.h b/lib/ios/AirMaps/AIRMapSnapshot.h similarity index 100% rename from ios/AirMaps/AIRMapSnapshot.h rename to lib/ios/AirMaps/AIRMapSnapshot.h diff --git a/ios/AirMaps/AIRMapUrlTile.h b/lib/ios/AirMaps/AIRMapUrlTile.h similarity index 100% rename from ios/AirMaps/AIRMapUrlTile.h rename to lib/ios/AirMaps/AIRMapUrlTile.h diff --git a/ios/AirMaps/AIRMapUrlTile.m b/lib/ios/AirMaps/AIRMapUrlTile.m similarity index 100% rename from ios/AirMaps/AIRMapUrlTile.m rename to lib/ios/AirMaps/AIRMapUrlTile.m diff --git a/ios/AirMaps/AIRMapUrlTileManager.h b/lib/ios/AirMaps/AIRMapUrlTileManager.h similarity index 100% rename from ios/AirMaps/AIRMapUrlTileManager.h rename to lib/ios/AirMaps/AIRMapUrlTileManager.h diff --git a/ios/AirMaps/AIRMapUrlTileManager.m b/lib/ios/AirMaps/AIRMapUrlTileManager.m similarity index 100% rename from ios/AirMaps/AIRMapUrlTileManager.m rename to lib/ios/AirMaps/AIRMapUrlTileManager.m diff --git a/ios/AirMaps/Callout/SMCalloutView.h b/lib/ios/AirMaps/Callout/SMCalloutView.h similarity index 100% rename from ios/AirMaps/Callout/SMCalloutView.h rename to lib/ios/AirMaps/Callout/SMCalloutView.h diff --git a/ios/AirMaps/Callout/SMCalloutView.m b/lib/ios/AirMaps/Callout/SMCalloutView.m similarity index 100% rename from ios/AirMaps/Callout/SMCalloutView.m rename to lib/ios/AirMaps/Callout/SMCalloutView.m diff --git a/ios/AirMaps/RCTConvert+MapKit.h b/lib/ios/AirMaps/RCTConvert+MapKit.h similarity index 100% rename from ios/AirMaps/RCTConvert+MapKit.h rename to lib/ios/AirMaps/RCTConvert+MapKit.h diff --git a/ios/AirMaps/RCTConvert+MapKit.m b/lib/ios/AirMaps/RCTConvert+MapKit.m similarity index 100% rename from ios/AirMaps/RCTConvert+MapKit.m rename to lib/ios/AirMaps/RCTConvert+MapKit.m diff --git a/package.json b/package.json index 42a006cea..70224da44 100644 --- a/package.json +++ b/package.json @@ -5,8 +5,17 @@ "author": "Leland Richardson ", "version": "0.13.1", "scripts": { - "start": "react-native start", - "lint": "eslint .", + "start": "node node_modules/react-native/local-cli/cli.js start", + "run:packager": "./node_modules/react-native/packager/packager.sh", + "run:ios": "react-native run-ios --project-path ./example/ios", + "start:android": "adb shell am start -n com.airbnb.android.react.maps.example/.MainActivity", + "run:android": "./gradlew installDebug && npm run start:android", + "lint": "eslint ./", + "build": "npm run build:js && npm run build:android && npm run build:ios", + "build:js": "exit 0", + "build:ios": "bundle install --binstubs ./examples/ios && bundle exec pod install --project-directory=./example/ios/", + "build:android": "./gradlew :react-native-maps:assembleDebug", + "ci": "npm run lint", "preversion": "./scripts/update-version.js" }, "repository": { @@ -28,12 +37,19 @@ }, "devDependencies": { "babel-eslint": "^6.1.2", + "babel-plugin-module-resolver": "^2.3.0", + "babel-preset-airbnb": "^1.1.1", + "babel-preset-react-native": "1.9.0", "eslint": "^3.3.1", "eslint-config-airbnb": "^10.0.1", "eslint-plugin-import": "^1.14.0", "eslint-plugin-jsx-a11y": "^2.1.0", "eslint-plugin-prefer-object-spread": "^1.1.0", - "eslint-plugin-react": "^6.1.2" + "eslint-plugin-react": "^6.1.2", + "gitbook-cli": "^2.3.0", + "lodash": "^4.17.2", + "react": "~15.4.1", + "react-native": "^0.42.0" }, "rnpm": { "android": { diff --git a/react-native-google-maps.podspec b/react-native-google-maps.podspec index 6f6b28703..632da81d5 100644 --- a/react-native-google-maps.podspec +++ b/react-native-google-maps.podspec @@ -1,6 +1,10 @@ +require 'json' + +package = JSON.parse(File.read(File.join(__dir__, 'package.json'))) + Pod::Spec.new do |s| s.name = "react-native-google-maps" - s.version = "0.13.0" + s.version = package['version'] s.summary = "React Native Mapview component for iOS + Android" s.authors = { "intelligibabble" => "leland.m.richardson@gmail.com" } @@ -9,7 +13,7 @@ Pod::Spec.new do |s| s.platform = :ios, "8.0" s.source = { :git => "https://github.com/airbnb/react-native-maps.git" } - s.source_files = "ios/AirGoogleMaps/**/*.{h,m}" + s.source_files = "lib/ios/AirGoogleMaps/**/*.{h,m}" s.dependency 'React' s.dependency 'GoogleMaps', '2.1.1' diff --git a/react-native-maps.podspec b/react-native-maps.podspec index 601e4eb71..387265989 100644 --- a/react-native-maps.podspec +++ b/react-native-maps.podspec @@ -1,6 +1,10 @@ +require 'json' + +package = JSON.parse(File.read(File.join(__dir__, 'package.json'))) + Pod::Spec.new do |s| s.name = "react-native-maps" - s.version = "0.13.0" + s.version = package['version'] s.summary = "React Native Mapview component for iOS + Android" s.authors = { "intelligibabble" => "leland.m.richardson@gmail.com" } @@ -9,7 +13,7 @@ Pod::Spec.new do |s| s.platform = :ios, "8.0" s.source = { :git => "https://github.com/airbnb/react-native-maps.git" } - s.source_files = "ios/AirMaps/**/*.{h,m}" + s.source_files = "lib/ios/AirMaps/**/*.{h,m}" s.dependency 'React' end diff --git a/rn-cli.config.js b/rn-cli.config.js new file mode 100644 index 000000000..d58725ef3 --- /dev/null +++ b/rn-cli.config.js @@ -0,0 +1,11 @@ +const config = { + /** + * Returns a regular expression for modules that should be ignored by the + * packager on a given platform. + */ + getBlacklistRE() { + return /_book\//; + }, +}; + +module.exports = config; diff --git a/scripts/update-version.js b/scripts/update-version.js index f8f840ea7..232cda449 100755 --- a/scripts/update-version.js +++ b/scripts/update-version.js @@ -5,8 +5,8 @@ * reference to the current package version: * * - android/gradle.properties - * - react-native-maps.podspec - * - react-native-google-maps.podspec + * x react-native-maps.podspec // <-- this is now dynamic + * x react-native-google-maps.podspec // <-- this is now dynamic * * And `git add`s them. */ @@ -16,8 +16,6 @@ const pkg = require('../package.json'); const filesToUpdate = [ 'android/gradle.properties', - 'react-native-maps.podspec', - 'react-native-google-maps.podspec', ]; function doExec(cmdString) { diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 000000000..4196dd53b --- /dev/null +++ b/settings.gradle @@ -0,0 +1,7 @@ +rootProject.name = 'react-native-maps' + +include ":example-android" +project(":example-android").projectDir = file("./example/android/app") + +include ":react-native-maps-lib" +project(":react-native-maps-lib").projectDir = file("./lib/android") From a7426a84d7791918bd1777437aeeeb401b512fc1 Mon Sep 17 00:00:00 2001 From: Leland Richardson Date: Sun, 26 Mar 2017 16:20:27 -0700 Subject: [PATCH 0235/1148] Add android only note to showsIndoorLevelPicker --- docs/mapview.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/mapview.md b/docs/mapview.md index f242f636b..8e73a0773 100644 --- a/docs/mapview.md +++ b/docs/mapview.md @@ -20,7 +20,7 @@ | `showsBuildings` | `Boolean` | `true` | A Boolean indicating whether the map displays extruded building information. | `showsTraffic` | `Boolean` | `true` | A Boolean value indicating whether the map displays traffic information. | `showsIndoors` | `Boolean` | `true` | A Boolean indicating whether indoor maps should be enabled. -| `showsIndoorLevelPicker` | `Boolean` | `false` | A Boolean indicating whether indoor level picker should be enabled. +| `showsIndoorLevelPicker` | `Boolean` | `false` | A Boolean indicating whether indoor level picker should be enabled. **Note:** Android only. | `zoomEnabled` | `Boolean` | `true` | If `false` the user won't be able to pinch/zoom the map. | `rotateEnabled` | `Boolean` | `true` | If `false` the user won't be able to pinch/rotate the map. | `scrollEnabled` | `Boolean` | `true` | If `false` the user won't be able to change the map region being displayed. From f92b6e5e6b5c322374fcbfabf0c9b6c06ed25144 Mon Sep 17 00:00:00 2001 From: Leland Richardson Date: Sun, 26 Mar 2017 16:59:52 -0700 Subject: [PATCH 0236/1148] Address PR feedback from #1130 --- .../android/app/src/main/AndroidManifest.xml | 1 + lib/android/src/main/AndroidManifest.xml | 1 + .../airbnb/android/react/maps/AirMapView.java | 21 ++++++++++++------- 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/example/android/app/src/main/AndroidManifest.xml b/example/android/app/src/main/AndroidManifest.xml index 2742d5793..b111eef4a 100644 --- a/example/android/app/src/main/AndroidManifest.xml +++ b/example/android/app/src/main/AndroidManifest.xml @@ -1,6 +1,7 @@ + + diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java index 0f4fb45d8..0c8604f26 100644 --- a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java @@ -1,6 +1,5 @@ package com.airbnb.android.react.maps; -import android.content.Context; import android.content.pm.PackageManager; import android.content.res.ColorStateList; import android.graphics.Bitmap; @@ -21,7 +20,6 @@ import android.widget.RelativeLayout; import com.facebook.react.bridge.LifecycleEventListener; -import com.facebook.react.bridge.ReactContext; import com.facebook.react.bridge.ReadableArray; import com.facebook.react.bridge.ReadableMap; import com.facebook.react.bridge.WritableMap; @@ -142,6 +140,9 @@ public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, @Override public void onMapReady(final GoogleMap map) { + if (destroyed) { + return; + } this.map = map; this.map.setInfoWindowAdapter(this); this.map.setOnMarkerDragListener(this); @@ -298,22 +299,26 @@ private boolean hasPermissions() { checkSelfPermission(getContext(), PERMISSIONS[1]) == PackageManager.PERMISSION_GRANTED; } + + /* onDestroy is final method so I can't override it. */ public synchronized void doDestroy() { + if (destroyed) { + return; + } + destroyed = true; + if (lifecycleListener != null && context != null) { context.removeLifecycleEventListener(lifecycleListener); lifecycleListener = null; } - if(!paused) { + if (!paused) { onPause(); + paused = true; } - if (!destroyed) { - onDestroy(); - destroyed = true; - } - + onDestroy(); } public void setRegion(ReadableMap region) { From 254eb1f2a72b037245d1218f201309068b969fc7 Mon Sep 17 00:00:00 2001 From: Leland Richardson Date: Sun, 26 Mar 2017 22:42:28 -0700 Subject: [PATCH 0237/1148] Upgrade GMS dependencies to 10.2.0 --- lib/android/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/android/build.gradle b/lib/android/build.gradle index 062f040ca..85cb5b4d2 100644 --- a/lib/android/build.gradle +++ b/lib/android/build.gradle @@ -35,6 +35,6 @@ android { dependencies { provided "com.facebook.react:react-native:+" - compile "com.google.android.gms:play-services-base:10.0.1" - compile "com.google.android.gms:play-services-maps:10.0.1" + compile "com.google.android.gms:play-services-base:10.2.0" + compile "com.google.android.gms:play-services-maps:10.2.0" } From 4926f5b53fac8e1ab9aaf877e81048e262dee8aa Mon Sep 17 00:00:00 2001 From: Janic Duplessis Date: Mon, 27 Mar 2017 18:24:24 -0400 Subject: [PATCH 0238/1148] Rename MapKit category to avoid conflicts with the one in RN --- lib/ios/AirGoogleMaps/AIRGoogleMap.h | 2 +- lib/ios/AirGoogleMaps/AIRGoogleMap.m | 2 +- lib/ios/AirGoogleMaps/AIRGoogleMapManager.m | 2 +- lib/ios/AirGoogleMaps/AIRGoogleMapMarkerManager.m | 2 +- lib/ios/AirGoogleMaps/AIRGoogleMapPolygonManager.m | 2 +- lib/ios/AirGoogleMaps/AIRGoogleMapPolylineManager.m | 2 +- lib/ios/AirMaps/AIRMap.h | 2 +- lib/ios/AirMaps/AIRMapCircle.h | 2 +- lib/ios/AirMaps/AIRMapManager.m | 2 +- lib/ios/AirMaps/AIRMapMarker.h | 2 +- lib/ios/AirMaps/AIRMapPolygon.h | 2 +- lib/ios/AirMaps/AIRMapPolygonManager.m | 2 +- lib/ios/AirMaps/AIRMapPolyline.h | 2 +- lib/ios/AirMaps/AIRMapPolylineManager.m | 2 +- lib/ios/AirMaps/AIRMapUrlTile.h | 2 +- lib/ios/AirMaps/{RCTConvert+MapKit.h => RCTConvert+AirMap.h} | 2 +- lib/ios/AirMaps/{RCTConvert+MapKit.m => RCTConvert+AirMap.m} | 4 ++-- 17 files changed, 18 insertions(+), 18 deletions(-) rename lib/ios/AirMaps/{RCTConvert+MapKit.h => RCTConvert+AirMap.h} (91%) rename lib/ios/AirMaps/{RCTConvert+MapKit.m => RCTConvert+AirMap.m} (95%) diff --git a/lib/ios/AirGoogleMaps/AIRGoogleMap.h b/lib/ios/AirGoogleMaps/AIRGoogleMap.h index 8006a804e..9e6ae8b79 100644 --- a/lib/ios/AirGoogleMaps/AIRGoogleMap.h +++ b/lib/ios/AirGoogleMaps/AIRGoogleMap.h @@ -10,7 +10,7 @@ #import #import #import "AIRGMSMarker.h" -#import "RCTConvert+MapKit.h" +#import "RCTConvert+AirMap.h" @interface AIRGoogleMap : GMSMapView diff --git a/lib/ios/AirGoogleMaps/AIRGoogleMap.m b/lib/ios/AirGoogleMaps/AIRGoogleMap.m index 8f51c26e7..ca15da04e 100644 --- a/lib/ios/AirGoogleMaps/AIRGoogleMap.m +++ b/lib/ios/AirGoogleMaps/AIRGoogleMap.m @@ -14,7 +14,7 @@ #import #import #import -#import "RCTConvert+MapKit.h" +#import "RCTConvert+AirMap.h" id regionAsJSON(MKCoordinateRegion region) { return @{ diff --git a/lib/ios/AirGoogleMaps/AIRGoogleMapManager.m b/lib/ios/AirGoogleMaps/AIRGoogleMapManager.m index 6e81c7e9b..785d58d4d 100644 --- a/lib/ios/AirGoogleMaps/AIRGoogleMapManager.m +++ b/lib/ios/AirGoogleMaps/AIRGoogleMapManager.m @@ -23,7 +23,7 @@ #import "AIRMapCircle.h" #import "SMCalloutView.h" #import "AIRGoogleMapMarker.h" -#import "RCTConvert+MapKit.h" +#import "RCTConvert+AirMap.h" #import diff --git a/lib/ios/AirGoogleMaps/AIRGoogleMapMarkerManager.m b/lib/ios/AirGoogleMaps/AIRGoogleMapMarkerManager.m index ac2e44347..8be4ba53e 100644 --- a/lib/ios/AirGoogleMaps/AIRGoogleMapMarkerManager.m +++ b/lib/ios/AirGoogleMaps/AIRGoogleMapMarkerManager.m @@ -9,7 +9,7 @@ #import "AIRGoogleMapMarker.h" #import #import -#import "RCTConvert+MapKit.h" +#import "RCTConvert+AirMap.h" @implementation AIRGoogleMapMarkerManager diff --git a/lib/ios/AirGoogleMaps/AIRGoogleMapPolygonManager.m b/lib/ios/AirGoogleMaps/AIRGoogleMapPolygonManager.m index 0dd8d54a0..59e239627 100644 --- a/lib/ios/AirGoogleMaps/AIRGoogleMapPolygonManager.m +++ b/lib/ios/AirGoogleMaps/AIRGoogleMapPolygonManager.m @@ -11,7 +11,7 @@ #import #import #import -#import "RCTConvert+MapKit.h" +#import "RCTConvert+AirMap.h" #import "AIRGoogleMapPolygon.h" @interface AIRGoogleMapPolygonManager() diff --git a/lib/ios/AirGoogleMaps/AIRGoogleMapPolylineManager.m b/lib/ios/AirGoogleMaps/AIRGoogleMapPolylineManager.m index 5fca4e902..acad1631b 100644 --- a/lib/ios/AirGoogleMaps/AIRGoogleMapPolylineManager.m +++ b/lib/ios/AirGoogleMaps/AIRGoogleMapPolylineManager.m @@ -12,7 +12,7 @@ #import #import #import -#import "RCTConvert+MapKit.h" +#import "RCTConvert+AirMap.h" #import "AIRGoogleMapPolyline.h" @interface AIRGoogleMapPolylineManager() diff --git a/lib/ios/AirMaps/AIRMap.h b/lib/ios/AirMaps/AIRMap.h index b74163cb9..18c9a0bc0 100644 --- a/lib/ios/AirMaps/AIRMap.h +++ b/lib/ios/AirMaps/AIRMap.h @@ -12,7 +12,7 @@ #import #import "SMCalloutView.h" -#import "RCTConvert+MapKit.h" +#import "RCTConvert+AirMap.h" extern const CLLocationDegrees AIRMapDefaultSpan; extern const NSTimeInterval AIRMapRegionChangeObserveInterval; diff --git a/lib/ios/AirMaps/AIRMapCircle.h b/lib/ios/AirMaps/AIRMapCircle.h index 7d7160e85..83a70f297 100644 --- a/lib/ios/AirMaps/AIRMapCircle.h +++ b/lib/ios/AirMaps/AIRMapCircle.h @@ -13,7 +13,7 @@ #import "AIRMapCoordinate.h" #import "AIRMap.h" -#import "RCTConvert+MapKit.h" +#import "RCTConvert+AirMap.h" @interface AIRMapCircle: MKAnnotationView diff --git a/lib/ios/AirMaps/AIRMapManager.m b/lib/ios/AirMaps/AIRMapManager.m index 1e2c3f5ac..619142bd6 100644 --- a/lib/ios/AirMaps/AIRMapManager.m +++ b/lib/ios/AirMaps/AIRMapManager.m @@ -24,7 +24,7 @@ #import "SMCalloutView.h" #import "AIRMapUrlTile.h" #import "AIRMapSnapshot.h" -#import "RCTConvert+MapKit.h" +#import "RCTConvert+AirMap.h" #import diff --git a/lib/ios/AirMaps/AIRMapMarker.h b/lib/ios/AirMaps/AIRMapMarker.h index bbcabf506..0613544a9 100644 --- a/lib/ios/AirMaps/AIRMapMarker.h +++ b/lib/ios/AirMaps/AIRMapMarker.h @@ -16,7 +16,7 @@ #import #import "AIRMap.h" #import "SMCalloutView.h" -#import "RCTConvert+MapKit.h" +#import "RCTConvert+AirMap.h" @class RCTBridge; diff --git a/lib/ios/AirMaps/AIRMapPolygon.h b/lib/ios/AirMaps/AIRMapPolygon.h index 15def9100..611d942e7 100644 --- a/lib/ios/AirMaps/AIRMapPolygon.h +++ b/lib/ios/AirMaps/AIRMapPolygon.h @@ -12,7 +12,7 @@ #import #import "AIRMapCoordinate.h" #import "AIRMap.h" -#import "RCTConvert+MapKit.h" +#import "RCTConvert+AirMap.h" diff --git a/lib/ios/AirMaps/AIRMapPolygonManager.m b/lib/ios/AirMaps/AIRMapPolygonManager.m index e9be4936a..543644e82 100644 --- a/lib/ios/AirMaps/AIRMapPolygonManager.m +++ b/lib/ios/AirMaps/AIRMapPolygonManager.m @@ -15,7 +15,7 @@ #import #import #import -#import "RCTConvert+MapKit.h" +#import "RCTConvert+AirMap.h" #import "AIRMapMarker.h" #import "AIRMapPolygon.h" diff --git a/lib/ios/AirMaps/AIRMapPolyline.h b/lib/ios/AirMaps/AIRMapPolyline.h index 6fb5feadc..6311c3248 100644 --- a/lib/ios/AirMaps/AIRMapPolyline.h +++ b/lib/ios/AirMaps/AIRMapPolyline.h @@ -12,7 +12,7 @@ #import #import "AIRMapCoordinate.h" #import "AIRMap.h" -#import "RCTConvert+MapKit.h" +#import "RCTConvert+AirMap.h" @interface AIRMapPolyline: MKAnnotationView diff --git a/lib/ios/AirMaps/AIRMapPolylineManager.m b/lib/ios/AirMaps/AIRMapPolylineManager.m index d00a9efac..e064b7c4b 100644 --- a/lib/ios/AirMaps/AIRMapPolylineManager.m +++ b/lib/ios/AirMaps/AIRMapPolylineManager.m @@ -15,7 +15,7 @@ #import #import #import -#import "RCTConvert+MapKit.h" +#import "RCTConvert+AirMap.h" #import "AIRMapMarker.h" #import "AIRMapPolyline.h" diff --git a/lib/ios/AirMaps/AIRMapUrlTile.h b/lib/ios/AirMaps/AIRMapUrlTile.h index a33be61d1..49963d3ee 100644 --- a/lib/ios/AirMaps/AIRMapUrlTile.h +++ b/lib/ios/AirMaps/AIRMapUrlTile.h @@ -14,7 +14,7 @@ #import #import "AIRMapCoordinate.h" #import "AIRMap.h" -#import "RCTConvert+MapKit.h" +#import "RCTConvert+AirMap.h" @interface AIRMapUrlTile : MKAnnotationView diff --git a/lib/ios/AirMaps/RCTConvert+MapKit.h b/lib/ios/AirMaps/RCTConvert+AirMap.h similarity index 91% rename from lib/ios/AirMaps/RCTConvert+MapKit.h rename to lib/ios/AirMaps/RCTConvert+AirMap.h index 28f60bf96..fc1059d91 100644 --- a/lib/ios/AirMaps/RCTConvert+MapKit.h +++ b/lib/ios/AirMaps/RCTConvert+AirMap.h @@ -7,7 +7,7 @@ #import #import -@interface RCTConvert (MapKit) +@interface RCTConvert (AirMap) + (MKCoordinateSpan)MKCoordinateSpan:(id)json; + (MKCoordinateRegion)MKCoordinateRegion:(id)json; diff --git a/lib/ios/AirMaps/RCTConvert+MapKit.m b/lib/ios/AirMaps/RCTConvert+AirMap.m similarity index 95% rename from lib/ios/AirMaps/RCTConvert+MapKit.m rename to lib/ios/AirMaps/RCTConvert+AirMap.m index 2e3b11602..cfdbb17ce 100644 --- a/lib/ios/AirMaps/RCTConvert+MapKit.m +++ b/lib/ios/AirMaps/RCTConvert+AirMap.m @@ -3,12 +3,12 @@ // Copyright (c) 2015 Facebook. All rights reserved. // -#import "RCTConvert+MapKit.h" +#import "RCTConvert+AirMap.h" #import #import "AIRMapCoordinate.h" -@implementation RCTConvert (MapKit) +@implementation RCTConvert (AirMap) + (MKCoordinateSpan)MKCoordinateSpan:(id)json { From 6553f68010f25c2237c60968be586a827bf2d3e6 Mon Sep 17 00:00:00 2001 From: Leland Richardson Date: Wed, 29 Mar 2017 16:45:44 -0700 Subject: [PATCH 0239/1148] Add postinstall script to disable modules for airgmaps --- example/ios/Podfile | 11 +++++++++++ example/ios/Podfile.lock | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/example/ios/Podfile b/example/ios/Podfile index ec73199a4..6cff9aae8 100644 --- a/example/ios/Podfile +++ b/example/ios/Podfile @@ -26,3 +26,14 @@ target 'AirMapsExplorer' do pod 'react-native-google-maps', path: '../../' # <~~ if you need GoogleMaps support on iOS end + + +post_install do |installer| + installer.pods_project.targets.each do |target| + if target.name == "react-native-google-maps" + target.build_configurations.each do |config| + config.build_settings['CLANG_ENABLE_MODULES'] = 'No' + end + end + end +end diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index 60339f2b0..ff6774aa2 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -74,6 +74,6 @@ SPEC CHECKSUMS: react-native-maps: 326ddbaaea8f6044b1817fb028c40950c71cc38a Yoga: 86ce777665c8259b94ef8dbea76b84634237f4ea -PODFILE CHECKSUM: 206f5482deac191368c01dd654d14fbd3e5d6b8f +PODFILE CHECKSUM: 222d08e48f834b6a3de650b72786105af7a9d331 COCOAPODS: 1.2.0 From bf5f0a3f5ba51e8f5044f6f72680d71a677e7c26 Mon Sep 17 00:00:00 2001 From: Leland Richardson Date: Tue, 4 Apr 2017 18:19:39 -0700 Subject: [PATCH 0240/1148] Fix getResources() null crash in mapview --- .../airbnb/android/react/maps/AirMapView.java | 33 ++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java index 0c8604f26..772627e4a 100644 --- a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java @@ -1,5 +1,7 @@ package com.airbnb.android.react.maps; +import android.app.Activity; +import android.content.Context; import android.content.pm.PackageManager; import android.content.res.ColorStateList; import android.graphics.Bitmap; @@ -85,9 +87,38 @@ public class AirMapView extends MapView implements GoogleMap.InfoWindowAdapter, private final ThemedReactContext context; private final EventDispatcher eventDispatcher; + private static boolean contextHasBug(Context context) { + return context == null || + context.getResources() == null || + context.getResources().getConfiguration() == null; + } + + // We do this to fix this bug: + // https://github.com/airbnb/react-native-maps/issues/271 + // + // which conflicts with another bug regarding the passed in context: + // https://github.com/airbnb/react-native-maps/issues/1147 + // + // Doing this allows us to avoid both bugs. + private static Context getNonBuggyContext(ThemedReactContext reactContext) { + Context superContext = reactContext; + + if (contextHasBug(superContext)) { + // we have the bug! let's try to find a better context to use + if (!contextHasBug(reactContext.getCurrentActivity())) { + superContext = reactContext.getCurrentActivity(); + } else if (!contextHasBug(reactContext.getApplicationContext())) { + superContext = reactContext.getApplicationContext(); + } else { + // ¯\_(ツ)_/¯ + } + } + return superContext; + } + public AirMapView(ThemedReactContext reactContext, AirMapManager manager, GoogleMapOptions googleMapOptions) { - super(reactContext, googleMapOptions); + super(getNonBuggyContext(reactContext), googleMapOptions); this.manager = manager; this.context = reactContext; From 4849de52b2af70225c8bf3393fc3452f186acd07 Mon Sep 17 00:00:00 2001 From: Leland Richardson Date: Tue, 4 Apr 2017 18:41:01 -0700 Subject: [PATCH 0241/1148] v0.14.0 --- CHANGELOG.md | 43 +++++++++++++++++++++++++++++++++++ lib/android/gradle.properties | 2 +- package.json | 2 +- 3 files changed, 45 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a6e3ab5c3..5c13e5ba0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,48 @@ # Change Log +## 0.14.0 (April 4, 2017) + +## Enhancements + +* Restructure project #1164 + +* Add showsIndoorLevelPicker -> setIndoorLevelPickerEnabled to MapView #1019 +[#1188](https://github.com/airbnb/react-native-maps/pull/1188) + +* iOS - Added onPress support for Polygons on Google Maps +[#1024](https://github.com/airbnb/react-native-maps/pull/1024) + +* Add customized user location annotation text +[#1049](https://github.com/airbnb/react-native-maps/pull/1049) + +* iOS - Google Maps - Add `showsMyLocationButton` support +[#1157](https://github.com/airbnb/react-native-maps/pull/1157) + + +## Patches + +* Fix getResources() null crash in mapview +[#1188](https://github.com/airbnb/react-native-maps/pull/1188) + +* Rename MapKit category to avoid conflicts with the one in RN +[#1172](https://github.com/airbnb/react-native-maps/pull/1172) + +* Upgrade GMS dependencies to 10.2.0 +[#1169](https://github.com/airbnb/react-native-maps/pull/1169) + +* fix multiple-instance memory leak +[#1130](https://github.com/airbnb/react-native-maps/pull/1130) + +* fix onSelected event for markers with custom view +[#1079](https://github.com/airbnb/react-native-maps/pull/1079) + +* Crash in our App fix +[#1096](https://github.com/airbnb/react-native-maps/pull/1096) + +* Use local RCTConvert+MapKit instead of the one in React Native +[#1138](https://github.com/airbnb/react-native-maps/pull/1138) + + ## 0.13.1 (March 21, 2017) diff --git a/lib/android/gradle.properties b/lib/android/gradle.properties index cfe4fd7d4..9a87aa52e 100644 --- a/lib/android/gradle.properties +++ b/lib/android/gradle.properties @@ -1,5 +1,5 @@ VERSION_CODE=4 -VERSION_NAME=0.13.1 +VERSION_NAME=0.14.0 GROUP=com.airbnb.android POM_DESCRIPTION=React Native Map view component for Android diff --git a/package.json b/package.json index 70224da44..9bbc2e1dd 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "description": "React Native Mapview component for iOS + Android", "main": "index.js", "author": "Leland Richardson ", - "version": "0.13.1", + "version": "0.14.0", "scripts": { "start": "node node_modules/react-native/local-cli/cli.js start", "run:packager": "./node_modules/react-native/packager/packager.sh", From 4b861c949a079a393f48a485943d3a506a151ac0 Mon Sep 17 00:00:00 2001 From: Rob Hogan Date: Thu, 4 May 2017 20:23:41 +0100 Subject: [PATCH 0242/1148] pbxproj: RCTConvert+MapKit -> RCTConvert+AirMap (#1195) --- lib/ios/AirMaps.xcodeproj/project.pbxproj | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/ios/AirMaps.xcodeproj/project.pbxproj b/lib/ios/AirMaps.xcodeproj/project.pbxproj index 39b1256e2..ac641aff7 100644 --- a/lib/ios/AirMaps.xcodeproj/project.pbxproj +++ b/lib/ios/AirMaps.xcodeproj/project.pbxproj @@ -21,7 +21,7 @@ 1125B2E51C4AD3DA007D0023 /* AIRMapPolyline.m in Sources */ = {isa = PBXBuildFile; fileRef = 1125B2D41C4AD3DA007D0023 /* AIRMapPolyline.m */; }; 1125B2E61C4AD3DA007D0023 /* AIRMapPolylineManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 1125B2D61C4AD3DA007D0023 /* AIRMapPolylineManager.m */; }; 1125B2F21C4AD445007D0023 /* SMCalloutView.m in Sources */ = {isa = PBXBuildFile; fileRef = 1125B2F11C4AD445007D0023 /* SMCalloutView.m */; }; - 19DABC7F1E7C9D3C00F41150 /* RCTConvert+MapKit.m in Sources */ = {isa = PBXBuildFile; fileRef = 19DABC7E1E7C9D3C00F41150 /* RCTConvert+MapKit.m */; }; + 19DABC7F1E7C9D3C00F41150 /* RCTConvert+AirMap.m in Sources */ = {isa = PBXBuildFile; fileRef = 19DABC7E1E7C9D3C00F41150 /* RCTConvert+AirMap.m */; }; DA6C26381C9E2AFE0035349F /* AIRMapUrlTile.m in Sources */ = {isa = PBXBuildFile; fileRef = DA6C26371C9E2AFE0035349F /* AIRMapUrlTile.m */; }; DA6C263E1C9E324A0035349F /* AIRMapUrlTileManager.m in Sources */ = {isa = PBXBuildFile; fileRef = DA6C263D1C9E324A0035349F /* AIRMapUrlTileManager.m */; }; /* End PBXBuildFile section */ @@ -68,8 +68,8 @@ 1125B2F01C4AD445007D0023 /* SMCalloutView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SMCalloutView.h; path = AirMaps/Callout/SMCalloutView.h; sourceTree = SOURCE_ROOT; }; 1125B2F11C4AD445007D0023 /* SMCalloutView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SMCalloutView.m; path = AirMaps/Callout/SMCalloutView.m; sourceTree = SOURCE_ROOT; }; 11FA5C511C4A1296003AC2EE /* libAirMaps.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libAirMaps.a; sourceTree = BUILT_PRODUCTS_DIR; }; - 19DABC7D1E7C9D3C00F41150 /* RCTConvert+MapKit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "RCTConvert+MapKit.h"; sourceTree = ""; }; - 19DABC7E1E7C9D3C00F41150 /* RCTConvert+MapKit.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "RCTConvert+MapKit.m"; sourceTree = ""; }; + 19DABC7D1E7C9D3C00F41150 /* RCTConvert+AirMap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "RCTConvert+AirMap.h"; sourceTree = ""; }; + 19DABC7E1E7C9D3C00F41150 /* RCTConvert+AirMap.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "RCTConvert+AirMap.m"; sourceTree = ""; }; DA6C26361C9E2AFE0035349F /* AIRMapUrlTile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRMapUrlTile.h; sourceTree = ""; }; DA6C26371C9E2AFE0035349F /* AIRMapUrlTile.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRMapUrlTile.m; sourceTree = ""; }; DA6C263C1C9E324A0035349F /* AIRMapUrlTileManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRMapUrlTileManager.h; sourceTree = ""; }; @@ -134,8 +134,8 @@ 1125B2D61C4AD3DA007D0023 /* AIRMapPolylineManager.m */, 1125B2F01C4AD445007D0023 /* SMCalloutView.h */, 1125B2F11C4AD445007D0023 /* SMCalloutView.m */, - 19DABC7D1E7C9D3C00F41150 /* RCTConvert+MapKit.h */, - 19DABC7E1E7C9D3C00F41150 /* RCTConvert+MapKit.m */, + 19DABC7D1E7C9D3C00F41150 /* RCTConvert+AirMap.h */, + 19DABC7E1E7C9D3C00F41150 /* RCTConvert+AirMap.m */, DA6C26361C9E2AFE0035349F /* AIRMapUrlTile.h */, DA6C26371C9E2AFE0035349F /* AIRMapUrlTile.m */, DA6C263C1C9E324A0035349F /* AIRMapUrlTileManager.h */, @@ -206,7 +206,7 @@ 1125B2E01C4AD3DA007D0023 /* AIRMapManager.m in Sources */, 1125B2E61C4AD3DA007D0023 /* AIRMapPolylineManager.m in Sources */, 1125B2DD1C4AD3DA007D0023 /* AIRMapCircle.m in Sources */, - 19DABC7F1E7C9D3C00F41150 /* RCTConvert+MapKit.m in Sources */, + 19DABC7F1E7C9D3C00F41150 /* RCTConvert+AirMap.m in Sources */, 1125B2E51C4AD3DA007D0023 /* AIRMapPolyline.m in Sources */, DA6C263E1C9E324A0035349F /* AIRMapUrlTileManager.m in Sources */, 1125B2DA1C4AD3DA007D0023 /* AIRMap.m in Sources */, From fe906e51511fb70d6087411f4af25f7754c1d160 Mon Sep 17 00:00:00 2001 From: Samuel ROZE Date: Thu, 4 May 2017 15:24:47 -0400 Subject: [PATCH 0243/1148] Add the `lib` folder in the docs (#1293) --- docs/installation.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/installation.md b/docs/installation.md index d3b6c331c..c2e1dc488 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -25,9 +25,9 @@ react-native link react-native-maps (If you do not need `GoogleMaps` support for iOS, then you can probably completely skip this step.) 1. Open your project in Xcode workspace 1. If you need `GoogleMaps` support also - - Drag this folder `node_modules/react-native-maps/ios/AirGoogleMaps/` into your project, and choose `Create groups` in the popup window. + - Drag this folder `node_modules/react-native-maps/lib/ios/AirGoogleMaps/` into your project, and choose `Create groups` in the popup window. - In `AppDelegate.m`, add `@import GoogleMaps;` before `@implementation AppDelegate`. In `- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions`, add `[GMSServices provideAPIKey:@"YOUR_GOOGLE_MAP_API_KEY"];` - - In your project's `Build Settings` > `Header Search Paths`, double click the value field. In the popup, add `$(SRCROOT)/../node_modules/react-native-maps/ios/AirMaps` and change `non-recursive` to `recursive`. (Dragging the folder `node_modules/react-native-maps/ios/AirMaps/` into your project introduces duplicate symbols. We should not do it.) + - In your project's `Build Settings` > `Header Search Paths`, double click the value field. In the popup, add `$(SRCROOT)/../node_modules/react-native-maps/lib/ios/AirMaps` and change `non-recursive` to `recursive`. (Dragging the folder `node_modules/react-native-maps/lib/ios/AirMaps/` into your project introduces duplicate symbols. We should not do it.) Note: We recommend using a version of React Native >= .40. Newer versions (>= .40) require `package.json` to be set to `"react-native-maps": "^0.13.0"`, while older versions require `"react-native-maps": "^0.12.4"`. From 78a38cd67aef57b8da8e9a63848be87a5cfa6bb1 Mon Sep 17 00:00:00 2001 From: Todd Williams Date: Thu, 4 May 2017 12:25:56 -0700 Subject: [PATCH 0244/1148] Update path in android installation (#1249) I was having trouble compiling the android version but updating the project directory resolved it for me. --- docs/installation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/installation.md b/docs/installation.md index c2e1dc488..31c69cf43 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -98,7 +98,7 @@ After your `Podfile` is setup properly, run `pod install`. ```groovy ... include ':react-native-maps' - project(':react-native-maps').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-maps/android') + project(':react-native-maps').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-maps/lib/android') ``` 1. Specify your Google Maps API Key: From 1478c04b228c3381b82c6e9738962c6ef872dc22 Mon Sep 17 00:00:00 2001 From: Sam Corcos Date: Thu, 4 May 2017 12:27:23 -0700 Subject: [PATCH 0245/1148] Update docs to specify how to access event data (#1178) resolves #1136 --- docs/mapview.md | 8 +++++--- docs/marker.md | 2 ++ 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/docs/mapview.md b/docs/mapview.md index 8e73a0773..3df5640c3 100644 --- a/docs/mapview.md +++ b/docs/mapview.md @@ -9,7 +9,7 @@ | `initialRegion` | `Region` | | The initial region to be displayed by the map. Use this prop instead of `region` only if you don't want to control the viewport of the map besides the initial region.

Changing this prop after the component has mounted will not result in a region change.

This is similar to the `initialValue` prop of a text input. | `liteMode` | `Boolean` | `false` | Enable lite mode. **Note**: Android only. | `mapType` | `String` | `"standard"` | The map type to be displayed.

- standard: standard road map (default)
- satellite: satellite view
- hybrid: satellite view with roads and points of interest overlayed
- terrain: (Android only) topographic view -| `customMapStyle` | `Array` | | Adds custom styling to the map component. See [README](https://github.com/airbnb/react-native-maps#customizing-the-map-style) for more information. +| `customMapStyle` | `Array` | | Adds custom styling to the map component. See [README](https://github.com/airbnb/react-native-maps#customizing-the-map-style) for more information. | `showsUserLocation` | `Boolean` | `false` | If `true` the app will ask for the user's location. **NOTE**: You need to add `NSLocationWhenInUseUsageDescription` key in Info.plist to enable geolocation, otherwise it is going to *fail silently*! | `userLocationAnnotationTitle` | `String` | | The title of the annotation for current user location. This only works if `showsUserLocation` is true. There is a default value `My Location` set by MapView. **Note**: iOS only. | `followsUserLocation` | `Boolean` | `false` | If `true` the map will focus on the user's location. This only works if `showsUserLocation` is true and the user has shared their location. **Note**: iOS only. @@ -36,6 +36,8 @@ ## Events +To access event data, you will need to use `e.nativeEvent`. For example, `onPress={e => console.log(e.nativeEvent)}` will log the entire event object to your console. + | Event Name | Returns | Notes |---|---|---| | `onRegionChange` | `Region` | Callback that is called continuously when the region changes, such as when a user is dragging the map. @@ -59,9 +61,9 @@ |---|---|---| | `animateToRegion` | `region: Region`, `duration: Number` | | `animateToCoordinate` | `coordinate: LatLng`, `duration: Number` | -| `fitToElements` | `animated: Boolean` | +| `fitToElements` | `animated: Boolean` | | `fitToSuppliedMarkers` | `markerIDs: String[]`, `animated: Boolean` | If you need to use this in `ComponentDidMount`, make sure you put it in a timeout or it will cause performance problems. -| `fitToCoordinates` | `coordinates: Array, options: { edgePadding: EdgePadding, animated: Boolean }` | If called in `ComponentDidMount` in android, it will cause an exception. It is recommended to call it from the MapView `onLayout` event. +| `fitToCoordinates` | `coordinates: Array, options: { edgePadding: EdgePadding, animated: Boolean }` | If called in `ComponentDidMount` in android, it will cause an exception. It is recommended to call it from the MapView `onLayout` event. diff --git a/docs/marker.md b/docs/marker.md index 4246befc3..16ad49f40 100644 --- a/docs/marker.md +++ b/docs/marker.md @@ -20,6 +20,8 @@ ## Events +To access event data, you will need to use `e.nativeEvent`. For example, `onPress={e => console.log(e.nativeEvent)}` will log the entire event object to your console. + | Event Name | Returns | Notes |---|---|---| | `onPress` | `{ coordinate: LatLng, position: Point }` | Callback that is called when the user presses on the marker From e4a657e568f8beb15cfd715aa49795e24df7c627 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Pomyka=C5=82a?= Date: Thu, 4 May 2017 21:27:56 +0200 Subject: [PATCH 0246/1148] Update installation.md (#1179) --- docs/installation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/installation.md b/docs/installation.md index 31c69cf43..4edb9bfb1 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -203,7 +203,7 @@ Enter the name of the API key and create it. 1. Clean the cache : ``` watchman watch-del-all - npm cache clean + npm clean cache ``` 1. When starting emulator, make sure you have enabled `Wipe user data`. From 36a36917e4897c934b5bfe9cbaf1a63f87637e8e Mon Sep 17 00:00:00 2001 From: Yang Li Date: Fri, 5 May 2017 03:29:06 +0800 Subject: [PATCH 0247/1148] Add babelrc to npmignore (#1246) --- .npmignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.npmignore b/.npmignore index 33a9488b1..4ce7bc58b 100644 --- a/.npmignore +++ b/.npmignore @@ -1 +1,2 @@ example +.babelrc From 0eb1933e665348a315fbe2756ae962f112d96e75 Mon Sep 17 00:00:00 2001 From: Nathan Broadbent Date: Fri, 5 May 2017 02:29:36 +0700 Subject: [PATCH 0248/1148] Fixed path in `android/settings.gradle` (#1230) From 8f6d866c7b0dbd1b1373b2d821c4149373806677 Mon Sep 17 00:00:00 2001 From: Aaron Leonard Date: Thu, 4 May 2017 12:29:51 -0700 Subject: [PATCH 0249/1148] Update installation.md (#1226) Update the paths to the `android` and `ios` folders to match the new structure --- docs/installation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/installation.md b/docs/installation.md index 4edb9bfb1..49cf6d447 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -52,7 +52,7 @@ After your `Podfile` is setup properly, run `pod install`. >This was already done for you if you ran "react-native link" 1. Open your project in Xcode, right click on `Libraries` and click `Add - Files to "Your Project Name"` Look under `node_modules/react-native-maps/ios` and add `AIRMaps.xcodeproj`. + Files to "Your Project Name"` Look under `node_modules/react-native-maps/lib/ios` and add `AIRMaps.xcodeproj`. 1. Add `libAIRMaps.a` to `Build Phases -> Link Binary With Libraries. 1. Click on `AIRMaps.xcodeproj` in `Libraries` and go the `Build Settings` tab. Double click the text to the right of `Header Search From 88a732fc518fcc0a5a58d03fff56de9761bc04a1 Mon Sep 17 00:00:00 2001 From: Golam Rabbani Date: Fri, 5 May 2017 01:31:29 +0600 Subject: [PATCH 0250/1148] small typo fixed (#1211) --- docs/installation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/installation.md b/docs/installation.md index 49cf6d447..27614b6ff 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -213,7 +213,7 @@ Enter the name of the API key and create it. 1. If you encounter `com.android.dex.DexException: Multiple dex files define Landroid/support/v7/appcompat/R$anim`, then clear build folder. ``` cd android - gradlew clean + ./gradlew clean cd .. ``` From 1bbdcb7a2c10d55b0fc0944038fa18840b93c107 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adrian=20Caba=C5=82a?= Date: Thu, 4 May 2017 21:40:22 +0200 Subject: [PATCH 0251/1148] fixing code snippet (#1196) the path to project dir is no longer up-to-date From 0dcdebdfe20c292bcf6d66401afda1d559ee6f09 Mon Sep 17 00:00:00 2001 From: Felipe Lima Date: Mon, 8 May 2017 11:27:07 -0700 Subject: [PATCH 0252/1148] v0.15.0 (#1305) * Prepare for v0.15 release * Add changelog * Fix link to PR --- CHANGELOG.md | 5 +++++ build.gradle | 2 +- gradle/wrapper/gradle-wrapper.properties | 4 ++-- lib/android/build.gradle | 4 ++-- lib/android/gradle.properties | 2 +- package.json | 2 +- 6 files changed, 12 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5c13e5ba0..0af766a02 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Change Log +## 0.15.0 (May 8, 2017) + +* iOS: [#1195]((https://github.com/airbnb/react-native-maps/pull/1195) Rename project file to fix iOS build error +* Android: Update Google Play Services to version `10.2.4` + ## 0.14.0 (April 4, 2017) ## Enhancements diff --git a/build.gradle b/build.gradle index f89d2c594..8a3e2453e 100644 --- a/build.gradle +++ b/build.gradle @@ -5,7 +5,7 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:2.3.0' + classpath 'com.android.tools.build:gradle:2.3.1' } } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 3b6c26cf7..c21e471fc 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Thu Mar 02 17:03:11 PST 2017 +#Mon May 08 11:03:28 PDT 2017 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-3.5-all.zip diff --git a/lib/android/build.gradle b/lib/android/build.gradle index 85cb5b4d2..434e63e72 100644 --- a/lib/android/build.gradle +++ b/lib/android/build.gradle @@ -35,6 +35,6 @@ android { dependencies { provided "com.facebook.react:react-native:+" - compile "com.google.android.gms:play-services-base:10.2.0" - compile "com.google.android.gms:play-services-maps:10.2.0" + compile "com.google.android.gms:play-services-base:10.2.4" + compile "com.google.android.gms:play-services-maps:10.2.4" } diff --git a/lib/android/gradle.properties b/lib/android/gradle.properties index 9a87aa52e..2d7a31b06 100644 --- a/lib/android/gradle.properties +++ b/lib/android/gradle.properties @@ -1,5 +1,5 @@ VERSION_CODE=4 -VERSION_NAME=0.14.0 +VERSION_NAME=0.15.0 GROUP=com.airbnb.android POM_DESCRIPTION=React Native Map view component for Android diff --git a/package.json b/package.json index 9bbc2e1dd..de8063b3b 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "description": "React Native Mapview component for iOS + Android", "main": "index.js", "author": "Leland Richardson ", - "version": "0.14.0", + "version": "0.15.0", "scripts": { "start": "node node_modules/react-native/local-cli/cli.js start", "run:packager": "./node_modules/react-native/packager/packager.sh", From 7bba6f939f425865cf917fc3b65fdf63533dcbd1 Mon Sep 17 00:00:00 2001 From: frmdstryr Date: Thu, 11 May 2017 12:45:49 -0400 Subject: [PATCH 0253/1148] Fix overlay issues in Android introduced in 0.13.1 (#1311) * Update AirMapView.java * Update AirMapManager.java * Update AirMapView.java --- .../airbnb/android/react/maps/AirMapManager.java | 2 +- .../com/airbnb/android/react/maps/AirMapView.java | 15 +++++++++------ 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java index 3ac1f4de7..b6a975b77 100644 --- a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java @@ -59,7 +59,7 @@ public String getName() { @Override protected AirMapView createViewInstance(ThemedReactContext context) { - return new AirMapView(context, this, googleMapOptions); + return new AirMapView(context, this.appContext, this, googleMapOptions); } private void emitMapError(ThemedReactContext context, String message, String type) { diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java index 772627e4a..3225bf1ff 100644 --- a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java @@ -22,6 +22,7 @@ import android.widget.RelativeLayout; import com.facebook.react.bridge.LifecycleEventListener; +import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReadableArray; import com.facebook.react.bridge.ReadableMap; import com.facebook.react.bridge.WritableMap; @@ -100,10 +101,12 @@ private static boolean contextHasBug(Context context) { // https://github.com/airbnb/react-native-maps/issues/1147 // // Doing this allows us to avoid both bugs. - private static Context getNonBuggyContext(ThemedReactContext reactContext) { + private static Context getNonBuggyContext(ThemedReactContext reactContext, + ReactApplicationContext appContext) { Context superContext = reactContext; - - if (contextHasBug(superContext)) { + if (!contextHasBug(appContext.getCurrentActivity())) { + superContext = appContext.getCurrentActivity(); + } else if (contextHasBug(superContext)) { // we have the bug! let's try to find a better context to use if (!contextHasBug(reactContext.getCurrentActivity())) { superContext = reactContext.getCurrentActivity(); @@ -116,9 +119,9 @@ private static Context getNonBuggyContext(ThemedReactContext reactContext) { return superContext; } - public AirMapView(ThemedReactContext reactContext, AirMapManager manager, - GoogleMapOptions googleMapOptions) { - super(getNonBuggyContext(reactContext), googleMapOptions); + public AirMapView(ThemedReactContext reactContext, ReactApplicationContext appContext, AirMapManager manager, + GoogleMapOptions googleMapOptions) { + super(getNonBuggyContext(reactContext, appContext), googleMapOptions); this.manager = manager; this.context = reactContext; From 65d27913bbae2570c7e7b3dc28a55c8bfdd09d99 Mon Sep 17 00:00:00 2001 From: Ulydev Date: Thu, 11 May 2017 18:47:03 +0200 Subject: [PATCH 0254/1148] Update license date (#1316) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 41139a4a0..13d793926 100644 --- a/README.md +++ b/README.md @@ -494,7 +494,7 @@ Good: License -------- - Copyright (c) 2015 Airbnb + Copyright (c) 2017 Airbnb Licensed under the The MIT License (MIT) (the "License"); you may not use this file except in compliance with the License. From ca7eee1b59182ea02fd0f92b1cbbdc9bff7b9b8c Mon Sep 17 00:00:00 2001 From: Christopher Dro Date: Thu, 11 May 2017 09:48:21 -0700 Subject: [PATCH 0255/1148] [rnpm] Fix sourceDir for Android (#1313) Overlooked this change closing out a few PR's last week. Follow up for #1200 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index de8063b3b..766c2a967 100644 --- a/package.json +++ b/package.json @@ -53,7 +53,7 @@ }, "rnpm": { "android": { - "sourceDir": "./android" + "sourceDir": "./lib/android" } } } From 535f599c5d823f5f6cfe9d1c78f147371156dcce Mon Sep 17 00:00:00 2001 From: Guilherme Pontes Date: Fri, 19 May 2017 18:45:48 +0200 Subject: [PATCH 0256/1148] [iOS] Added onPress support for Polyline on Google Maps (#1194) --- example/examples/EventListener.js | 1 + lib/components/MapPolyline.js | 5 +++++ lib/ios/AirGoogleMaps/AIRGMSPolyline.h | 16 ++++++++++++++++ lib/ios/AirGoogleMaps/AIRGMSPolyline.m | 11 +++++++++++ lib/ios/AirGoogleMaps/AIRGoogleMap.h | 1 + lib/ios/AirGoogleMaps/AIRGoogleMap.m | 10 ++++++++++ lib/ios/AirGoogleMaps/AIRGoogleMapPolyline.h | 9 ++++++++- lib/ios/AirGoogleMaps/AIRGoogleMapPolyline.m | 17 ++++++++++++++--- .../AirGoogleMaps/AIRGoogleMapPolylineManager.m | 3 +++ lib/ios/AirMaps.xcodeproj/project.pbxproj | 6 ++++++ 10 files changed, 75 insertions(+), 4 deletions(-) create mode 100644 lib/ios/AirGoogleMaps/AIRGMSPolyline.h create mode 100644 lib/ios/AirGoogleMaps/AIRGMSPolyline.m diff --git a/example/examples/EventListener.js b/example/examples/EventListener.js index 005894a0d..c8d3e937f 100644 --- a/example/examples/EventListener.js +++ b/example/examples/EventListener.js @@ -145,6 +145,7 @@ class EventListener extends React.Component { +#import "UIView+React.h" + +@class AIRGoogleMapPolyline; + +@interface AIRGMSPolyline : GMSPolyline +@property (nonatomic, strong) NSString *identifier; +@property (nonatomic, copy) RCTBubblingEventBlock onPress; +@end diff --git a/lib/ios/AirGoogleMaps/AIRGMSPolyline.m b/lib/ios/AirGoogleMaps/AIRGMSPolyline.m new file mode 100644 index 000000000..86e7ac055 --- /dev/null +++ b/lib/ios/AirGoogleMaps/AIRGMSPolyline.m @@ -0,0 +1,11 @@ +// +// AIRGMSPolyline.m +// AirMaps +// +// Created by Guilherme Pontes 04/05/2017. +// + +#import "AIRGMSPolyline.h" + +@implementation AIRGMSPolyline +@end diff --git a/lib/ios/AirGoogleMaps/AIRGoogleMap.h b/lib/ios/AirGoogleMaps/AIRGoogleMap.h index 9e6ae8b79..0e9554eb6 100644 --- a/lib/ios/AirGoogleMaps/AIRGoogleMap.h +++ b/lib/ios/AirGoogleMaps/AIRGoogleMap.h @@ -41,6 +41,7 @@ @property (nonatomic, assign) BOOL showsMyLocationButton; - (BOOL)didTapMarker:(GMSMarker *)marker; +- (void)didTapPolyline:(GMSPolyline *)polyline; - (void)didTapPolygon:(GMSPolygon *)polygon; - (void)didTapAtCoordinate:(CLLocationCoordinate2D)coordinate; - (void)didLongPressAtCoordinate:(CLLocationCoordinate2D)coordinate; diff --git a/lib/ios/AirGoogleMaps/AIRGoogleMap.m b/lib/ios/AirGoogleMaps/AIRGoogleMap.m index ca15da04e..ef73067b6 100644 --- a/lib/ios/AirGoogleMaps/AIRGoogleMap.m +++ b/lib/ios/AirGoogleMaps/AIRGoogleMap.m @@ -170,6 +170,16 @@ - (BOOL)didTapMarker:(GMSMarker *)marker { return NO; } +- (void)didTapPolyline:(GMSOverlay *)polyline { + AIRGMSPolyline *airPolyline = (AIRGMSPolyline *)polyline; + + id event = @{@"action": @"polyline-press", + @"id": airPolyline.identifier ?: @"unknown", + }; + + if (airPolyline.onPress) airPolyline.onPress(event); +} + - (void)didTapPolygon:(GMSOverlay *)polygon { AIRGMSPolygon *airPolygon = (AIRGMSPolygon *)polygon; diff --git a/lib/ios/AirGoogleMaps/AIRGoogleMapPolyline.h b/lib/ios/AirGoogleMaps/AIRGoogleMapPolyline.h index b127567a5..adebc40d6 100644 --- a/lib/ios/AirGoogleMaps/AIRGoogleMapPolyline.h +++ b/lib/ios/AirGoogleMaps/AIRGoogleMapPolyline.h @@ -5,18 +5,25 @@ // #import #import +#import +#import "AIRGMSPolyline.h" #import "AIRMapCoordinate.h" #import "AIRGoogleMapMarker.h" @interface AIRGoogleMapPolyline : UIView -@property (nonatomic, strong) GMSPolyline* polyline; +@property (nonatomic, weak) RCTBridge *bridge; +@property (nonatomic, strong) NSString *identifier; +@property (nonatomic, strong) AIRGMSPolyline *polyline; @property (nonatomic, strong) NSArray *coordinates; +@property (nonatomic, copy) RCTBubblingEventBlock onPress; + @property (nonatomic, strong) UIColor *strokeColor; @property (nonatomic, assign) double strokeWidth; @property (nonatomic, assign) UIColor *fillColor; @property (nonatomic, assign) BOOL geodesic; @property (nonatomic, assign) NSString *title; @property (nonatomic, assign) int zIndex; +@property (nonatomic, assign) BOOL tappable; @end diff --git a/lib/ios/AirGoogleMaps/AIRGoogleMapPolyline.m b/lib/ios/AirGoogleMaps/AIRGoogleMapPolyline.m index 009d90bfb..881f17be6 100644 --- a/lib/ios/AirGoogleMaps/AIRGoogleMapPolyline.m +++ b/lib/ios/AirGoogleMaps/AIRGoogleMapPolyline.m @@ -5,6 +5,7 @@ // #import #import "AIRGoogleMapPolyline.h" +#import "AIRGMSPolyline.h" #import "AIRMapCoordinate.h" #import "AIRGoogleMapMarker.h" #import "AIRGoogleMapMarkerManager.h" @@ -16,7 +17,7 @@ @implementation AIRGoogleMapPolyline - (instancetype)init { if (self = [super init]) { - _polyline = [[GMSPolyline alloc] init]; + _polyline = [[AIRGMSPolyline alloc] init]; } return self; } @@ -24,13 +25,13 @@ - (instancetype)init -(void)setCoordinates:(NSArray *)coordinates { _coordinates = coordinates; - + GMSMutablePath *path = [GMSMutablePath path]; for(int i = 0; i < coordinates.count; i++) { [path addCoordinate:coordinates[i].coordinate]; } - + _polyline.path = path; } @@ -70,4 +71,14 @@ -(void) setZIndex:(int)zIndex _polyline.zIndex = zIndex; } +-(void)setTappable:(BOOL)tappable +{ + _tappable = tappable; + _polyline.tappable = tappable; +} + +- (void)setOnPress:(RCTBubblingEventBlock)onPress { + _polyline.onPress = onPress; +} + @end diff --git a/lib/ios/AirGoogleMaps/AIRGoogleMapPolylineManager.m b/lib/ios/AirGoogleMaps/AIRGoogleMapPolylineManager.m index acad1631b..a7515c207 100644 --- a/lib/ios/AirGoogleMaps/AIRGoogleMapPolylineManager.m +++ b/lib/ios/AirGoogleMaps/AIRGoogleMapPolylineManager.m @@ -26,6 +26,7 @@ @implementation AIRGoogleMapPolylineManager - (UIView *)view { AIRGoogleMapPolyline *polyline = [AIRGoogleMapPolyline new]; + polyline.bridge = self.bridge; return polyline; } @@ -35,5 +36,7 @@ - (UIView *)view RCT_EXPORT_VIEW_PROPERTY(strokeWidth, double) RCT_EXPORT_VIEW_PROPERTY(geodesic, BOOL) RCT_EXPORT_VIEW_PROPERTY(zIndex, int) +RCT_EXPORT_VIEW_PROPERTY(tappable, BOOL) +RCT_EXPORT_VIEW_PROPERTY(onPress, RCTBubblingEventBlock) @end diff --git a/lib/ios/AirMaps.xcodeproj/project.pbxproj b/lib/ios/AirMaps.xcodeproj/project.pbxproj index ac641aff7..19a7213ff 100644 --- a/lib/ios/AirMaps.xcodeproj/project.pbxproj +++ b/lib/ios/AirMaps.xcodeproj/project.pbxproj @@ -22,6 +22,7 @@ 1125B2E61C4AD3DA007D0023 /* AIRMapPolylineManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 1125B2D61C4AD3DA007D0023 /* AIRMapPolylineManager.m */; }; 1125B2F21C4AD445007D0023 /* SMCalloutView.m in Sources */ = {isa = PBXBuildFile; fileRef = 1125B2F11C4AD445007D0023 /* SMCalloutView.m */; }; 19DABC7F1E7C9D3C00F41150 /* RCTConvert+AirMap.m in Sources */ = {isa = PBXBuildFile; fileRef = 19DABC7E1E7C9D3C00F41150 /* RCTConvert+AirMap.m */; }; + 9B0F3F7C1E9526A30001804F /* AIRGMSPolyline.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B0F3F7B1E9526A30001804F /* AIRGMSPolyline.m */; }; DA6C26381C9E2AFE0035349F /* AIRMapUrlTile.m in Sources */ = {isa = PBXBuildFile; fileRef = DA6C26371C9E2AFE0035349F /* AIRMapUrlTile.m */; }; DA6C263E1C9E324A0035349F /* AIRMapUrlTileManager.m in Sources */ = {isa = PBXBuildFile; fileRef = DA6C263D1C9E324A0035349F /* AIRMapUrlTileManager.m */; }; /* End PBXBuildFile section */ @@ -70,6 +71,8 @@ 11FA5C511C4A1296003AC2EE /* libAirMaps.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libAirMaps.a; sourceTree = BUILT_PRODUCTS_DIR; }; 19DABC7D1E7C9D3C00F41150 /* RCTConvert+AirMap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "RCTConvert+AirMap.h"; sourceTree = ""; }; 19DABC7E1E7C9D3C00F41150 /* RCTConvert+AirMap.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "RCTConvert+AirMap.m"; sourceTree = ""; }; + 9B0F3F7A1E9526460001804F /* AIRGMSPolyline.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AIRGMSPolyline.h; sourceTree = ""; }; + 9B0F3F7B1E9526A30001804F /* AIRGMSPolyline.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRGMSPolyline.m; sourceTree = ""; }; DA6C26361C9E2AFE0035349F /* AIRMapUrlTile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRMapUrlTile.h; sourceTree = ""; }; DA6C26371C9E2AFE0035349F /* AIRMapUrlTile.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRMapUrlTile.m; sourceTree = ""; }; DA6C263C1C9E324A0035349F /* AIRMapUrlTileManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRMapUrlTileManager.h; sourceTree = ""; }; @@ -140,6 +143,8 @@ DA6C26371C9E2AFE0035349F /* AIRMapUrlTile.m */, DA6C263C1C9E324A0035349F /* AIRMapUrlTileManager.h */, DA6C263D1C9E324A0035349F /* AIRMapUrlTileManager.m */, + 9B0F3F7A1E9526460001804F /* AIRGMSPolyline.h */, + 9B0F3F7B1E9526A30001804F /* AIRGMSPolyline.m */, ); path = AirMaps; sourceTree = ""; @@ -202,6 +207,7 @@ files = ( 1125B2E31C4AD3DA007D0023 /* AIRMapPolygon.m in Sources */, 1125B2E41C4AD3DA007D0023 /* AIRMapPolygonManager.m in Sources */, + 9B0F3F7C1E9526A30001804F /* AIRGMSPolyline.m in Sources */, 1125B2DB1C4AD3DA007D0023 /* AIRMapCallout.m in Sources */, 1125B2E01C4AD3DA007D0023 /* AIRMapManager.m in Sources */, 1125B2E61C4AD3DA007D0023 /* AIRMapPolylineManager.m in Sources */, From 76fa0b491effabcd861e4dc2f0cc0a7a76a9c6c8 Mon Sep 17 00:00:00 2001 From: Helge Silset Date: Fri, 19 May 2017 18:46:07 +0200 Subject: [PATCH 0257/1148] Update README: Use callback in `ref` attribute (#1345) `this.refs`/string as ref is deprecated. --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 13d793926..49d65ac72 100644 --- a/README.md +++ b/README.md @@ -405,7 +405,7 @@ getInitialState() { takeSnapshot () { // 'takeSnapshot' takes a config object with the // following options - const snapshot = this.refs.map.takeSnapshot({ + const snapshot = this.map.takeSnapshot({ width: 300, // optional, when omitted the view-width is used height: 300, // optional, when omitted the view-height is used region: {..}, // iOS only, optional region to render @@ -421,7 +421,7 @@ takeSnapshot () { render() { return ( - + { this.map = map }}> From 9676c9cf2ae049bf01a39cc8f4219566858d28e3 Mon Sep 17 00:00:00 2001 From: Taminder Bariana Date: Fri, 19 May 2017 09:47:09 -0700 Subject: [PATCH 0258/1148] Fixing reference to AirMapsExplorer in installation docs (#1328) --- docs/installation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/installation.md b/docs/installation.md index 27614b6ff..12842d7c6 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -21,7 +21,7 @@ react-native link react-native-maps ### Option 1: CocoaPods - Same as the included AirMapsExplorer example -1. Setup your `Podfile` like the included [example/ios/Podfile](../example/ios/Podfile), replace all references to `AirMapExplorer` with your project name, and then run `pod install`. +1. Setup your `Podfile` like the included [example/ios/Podfile](../example/ios/Podfile), replace all references to `AirMapsExplorer` with your project name, and then run `pod install`. (If you do not need `GoogleMaps` support for iOS, then you can probably completely skip this step.) 1. Open your project in Xcode workspace 1. If you need `GoogleMaps` support also From 4ee7277ebf5c90c53c2d7d591f8f484ef2cd6d02 Mon Sep 17 00:00:00 2001 From: Yann Pringault Date: Fri, 19 May 2017 18:47:51 +0200 Subject: [PATCH 0259/1148] Add Marker rotation for Google Maps on iOS (#1326) --- docs/marker.md | 2 +- lib/ios/AirGoogleMaps/AIRGoogleMapMarker.h | 1 + lib/ios/AirGoogleMaps/AIRGoogleMapMarker.m | 8 ++++++++ lib/ios/AirGoogleMaps/AIRGoogleMapMarkerManager.m | 1 + 4 files changed, 11 insertions(+), 1 deletion(-) diff --git a/docs/marker.md b/docs/marker.md index 16ad49f40..4214e4d6e 100644 --- a/docs/marker.md +++ b/docs/marker.md @@ -15,7 +15,7 @@ | `calloutAnchor` | `Point` | | Specifies the point in the marker image at which to anchor the callout when it is displayed. This is specified in the same coordinate system as the anchor. See the `anchor` prop for more details.

The default is the top middle of the image.

For ios, see the `calloutOffset` prop. | `flat` | `Boolean` | | Sets whether this marker should be flat against the map true or a billboard facing the camera false. | `identifier` | `String` | | An identifier used to reference this marker at a later date. -| `rotation` | `Float` | | A float number indicating marker's rotation angle. +| `rotation` | `Float` | | A float number indicating marker's rotation angle, in degrees. | `draggable` | `` | | This is a non-value based prop. Adding this allows the marker to be draggable (re-positioned). ## Events diff --git a/lib/ios/AirGoogleMaps/AIRGoogleMapMarker.h b/lib/ios/AirGoogleMaps/AIRGoogleMapMarker.h index 36190e7cb..298884f7d 100644 --- a/lib/ios/AirGoogleMaps/AIRGoogleMapMarker.h +++ b/lib/ios/AirGoogleMaps/AIRGoogleMapMarker.h @@ -17,6 +17,7 @@ @property (nonatomic, strong) AIRGoogleMapCallout *calloutView; @property (nonatomic, strong) NSString *identifier; @property (nonatomic, assign) CLLocationCoordinate2D coordinate; +@property (nonatomic, assign) CLLocationDegrees rotation; @property (nonatomic, strong) AIRGMSMarker* realMarker; @property (nonatomic, copy) RCTBubblingEventBlock onPress; @property (nonatomic, copy) RCTDirectEventBlock onDragStart; diff --git a/lib/ios/AirGoogleMaps/AIRGoogleMapMarker.m b/lib/ios/AirGoogleMaps/AIRGoogleMapMarker.m index 2c6080e9e..c41be55bb 100644 --- a/lib/ios/AirGoogleMaps/AIRGoogleMapMarker.m +++ b/lib/ios/AirGoogleMaps/AIRGoogleMapMarker.m @@ -157,6 +157,14 @@ - (CLLocationCoordinate2D)coordinate { return _realMarker.position; } +- (void)setRotation:(CLLocationDegrees)rotation { + _realMarker.rotation = rotation; +} + +- (CLLocationDegrees)rotation { + return _realMarker.rotation; +} + - (void)setIdentifier:(NSString *)identifier { _realMarker.identifier = identifier; } diff --git a/lib/ios/AirGoogleMaps/AIRGoogleMapMarkerManager.m b/lib/ios/AirGoogleMaps/AIRGoogleMapMarkerManager.m index 8be4ba53e..b5572bf9d 100644 --- a/lib/ios/AirGoogleMaps/AIRGoogleMapMarkerManager.m +++ b/lib/ios/AirGoogleMaps/AIRGoogleMapMarkerManager.m @@ -28,6 +28,7 @@ - (UIView *)view RCT_EXPORT_VIEW_PROPERTY(identifier, NSString) RCT_EXPORT_VIEW_PROPERTY(coordinate, CLLocationCoordinate2D) +RCT_EXPORT_VIEW_PROPERTY(rotation, CLLocationDegrees) RCT_EXPORT_VIEW_PROPERTY(onPress, RCTBubblingEventBlock) RCT_REMAP_VIEW_PROPERTY(image, imageSrc, NSString) RCT_EXPORT_VIEW_PROPERTY(title, NSString) From 08127b40b68127c697fbb8491fd3a7225eed38ae Mon Sep 17 00:00:00 2001 From: yosimasu Date: Sat, 20 May 2017 00:48:07 +0800 Subject: [PATCH 0260/1148] fix compile error in rn version >= 0.40 (#1341) --- lib/ios/AirGoogleMaps/AIRGMSPolygon.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ios/AirGoogleMaps/AIRGMSPolygon.h b/lib/ios/AirGoogleMaps/AIRGMSPolygon.h index 3466b3691..d41c87d5e 100644 --- a/lib/ios/AirGoogleMaps/AIRGMSPolygon.h +++ b/lib/ios/AirGoogleMaps/AIRGMSPolygon.h @@ -6,7 +6,7 @@ // #import -#import "UIView+React.h" +#import @class AIRGoogleMapPolygon; From 0aac50daa0bddecd5e932a324228191d9d02c3e6 Mon Sep 17 00:00:00 2001 From: Christopher Dro Date: Fri, 19 May 2017 13:39:21 -0700 Subject: [PATCH 0261/1148] v0.15.1 (#1347) --- CHANGELOG.md | 10 +++++++++- lib/android/gradle.properties | 2 +- package.json | 2 +- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0af766a02..109ce6357 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,16 @@ # Change Log +## 0.15.1 (May 19, 2017) + +* iOS: [#1341](https://github.com/airbnb/react-native-maps/pull/1341) Fix compile error in rn version >= 0.40 +* iOS: [#1194](https://github.com/airbnb/react-native-maps/pull/1194) Add onPress support for Google Maps Polyline +* iOS: [#1326](https://github.com/airbnb/react-native-maps/pull/1326) Add Marker rotation for Google Maps on iOS +* Android: [#1311](https://github.com/airbnb/react-native-maps/pull/1311) Fix overlay issue +* Common [#1313](https://github.com/airbnb/react-native-maps/pull/1313) Fix Android sourceDir for react-native-link + ## 0.15.0 (May 8, 2017) -* iOS: [#1195]((https://github.com/airbnb/react-native-maps/pull/1195) Rename project file to fix iOS build error +* iOS: [#1195](https://github.com/airbnb/react-native-maps/pull/1195) Rename project file to fix iOS build error * Android: Update Google Play Services to version `10.2.4` ## 0.14.0 (April 4, 2017) diff --git a/lib/android/gradle.properties b/lib/android/gradle.properties index 2d7a31b06..ee320ef1f 100644 --- a/lib/android/gradle.properties +++ b/lib/android/gradle.properties @@ -1,5 +1,5 @@ VERSION_CODE=4 -VERSION_NAME=0.15.0 +VERSION_NAME=0.15.1 GROUP=com.airbnb.android POM_DESCRIPTION=React Native Map view component for Android diff --git a/package.json b/package.json index 766c2a967..a188fad59 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "description": "React Native Mapview component for iOS + Android", "main": "index.js", "author": "Leland Richardson ", - "version": "0.15.0", + "version": "0.15.1", "scripts": { "start": "node node_modules/react-native/local-cli/cli.js start", "run:packager": "./node_modules/react-native/packager/packager.sh", From 8b94984e5192c8083134e434e9740c204b62fcb2 Mon Sep 17 00:00:00 2001 From: Anton Petrov Date: Sat, 20 May 2017 18:46:32 +0300 Subject: [PATCH 0262/1148] Remove AIRGMSPolyline.h and AIRGMSPolyline.m references from AirMaps.xcodeproj (#1351) --- lib/ios/AirMaps.xcodeproj/project.pbxproj | 6 ------ 1 file changed, 6 deletions(-) diff --git a/lib/ios/AirMaps.xcodeproj/project.pbxproj b/lib/ios/AirMaps.xcodeproj/project.pbxproj index 19a7213ff..ac641aff7 100644 --- a/lib/ios/AirMaps.xcodeproj/project.pbxproj +++ b/lib/ios/AirMaps.xcodeproj/project.pbxproj @@ -22,7 +22,6 @@ 1125B2E61C4AD3DA007D0023 /* AIRMapPolylineManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 1125B2D61C4AD3DA007D0023 /* AIRMapPolylineManager.m */; }; 1125B2F21C4AD445007D0023 /* SMCalloutView.m in Sources */ = {isa = PBXBuildFile; fileRef = 1125B2F11C4AD445007D0023 /* SMCalloutView.m */; }; 19DABC7F1E7C9D3C00F41150 /* RCTConvert+AirMap.m in Sources */ = {isa = PBXBuildFile; fileRef = 19DABC7E1E7C9D3C00F41150 /* RCTConvert+AirMap.m */; }; - 9B0F3F7C1E9526A30001804F /* AIRGMSPolyline.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B0F3F7B1E9526A30001804F /* AIRGMSPolyline.m */; }; DA6C26381C9E2AFE0035349F /* AIRMapUrlTile.m in Sources */ = {isa = PBXBuildFile; fileRef = DA6C26371C9E2AFE0035349F /* AIRMapUrlTile.m */; }; DA6C263E1C9E324A0035349F /* AIRMapUrlTileManager.m in Sources */ = {isa = PBXBuildFile; fileRef = DA6C263D1C9E324A0035349F /* AIRMapUrlTileManager.m */; }; /* End PBXBuildFile section */ @@ -71,8 +70,6 @@ 11FA5C511C4A1296003AC2EE /* libAirMaps.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libAirMaps.a; sourceTree = BUILT_PRODUCTS_DIR; }; 19DABC7D1E7C9D3C00F41150 /* RCTConvert+AirMap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "RCTConvert+AirMap.h"; sourceTree = ""; }; 19DABC7E1E7C9D3C00F41150 /* RCTConvert+AirMap.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "RCTConvert+AirMap.m"; sourceTree = ""; }; - 9B0F3F7A1E9526460001804F /* AIRGMSPolyline.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AIRGMSPolyline.h; sourceTree = ""; }; - 9B0F3F7B1E9526A30001804F /* AIRGMSPolyline.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRGMSPolyline.m; sourceTree = ""; }; DA6C26361C9E2AFE0035349F /* AIRMapUrlTile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRMapUrlTile.h; sourceTree = ""; }; DA6C26371C9E2AFE0035349F /* AIRMapUrlTile.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRMapUrlTile.m; sourceTree = ""; }; DA6C263C1C9E324A0035349F /* AIRMapUrlTileManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRMapUrlTileManager.h; sourceTree = ""; }; @@ -143,8 +140,6 @@ DA6C26371C9E2AFE0035349F /* AIRMapUrlTile.m */, DA6C263C1C9E324A0035349F /* AIRMapUrlTileManager.h */, DA6C263D1C9E324A0035349F /* AIRMapUrlTileManager.m */, - 9B0F3F7A1E9526460001804F /* AIRGMSPolyline.h */, - 9B0F3F7B1E9526A30001804F /* AIRGMSPolyline.m */, ); path = AirMaps; sourceTree = ""; @@ -207,7 +202,6 @@ files = ( 1125B2E31C4AD3DA007D0023 /* AIRMapPolygon.m in Sources */, 1125B2E41C4AD3DA007D0023 /* AIRMapPolygonManager.m in Sources */, - 9B0F3F7C1E9526A30001804F /* AIRGMSPolyline.m in Sources */, 1125B2DB1C4AD3DA007D0023 /* AIRMapCallout.m in Sources */, 1125B2E01C4AD3DA007D0023 /* AIRMapManager.m in Sources */, 1125B2E61C4AD3DA007D0023 /* AIRMapPolylineManager.m in Sources */, From 8893578ca6197d0c0a3cacf5aea9c78bfb0a4b99 Mon Sep 17 00:00:00 2001 From: Christopher Dro Date: Sat, 20 May 2017 09:13:35 -0700 Subject: [PATCH 0263/1148] v0.15.2 (#1352) --- CHANGELOG.md | 4 ++++ lib/android/gradle.properties | 2 +- package.json | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 109ce6357..5968b7e7b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Change Log +## 0.15.2 (May 20, 2017) + +* iOS: [#1351](https://github.com/airbnb/react-native-maps/pull/1351) Fix file references + ## 0.15.1 (May 19, 2017) * iOS: [#1341](https://github.com/airbnb/react-native-maps/pull/1341) Fix compile error in rn version >= 0.40 diff --git a/lib/android/gradle.properties b/lib/android/gradle.properties index ee320ef1f..65c67798d 100644 --- a/lib/android/gradle.properties +++ b/lib/android/gradle.properties @@ -1,5 +1,5 @@ VERSION_CODE=4 -VERSION_NAME=0.15.1 +VERSION_NAME=0.15.2 GROUP=com.airbnb.android POM_DESCRIPTION=React Native Map view component for Android diff --git a/package.json b/package.json index a188fad59..30ffc43e8 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "description": "React Native Mapview component for iOS + Android", "main": "index.js", "author": "Leland Richardson ", - "version": "0.15.1", + "version": "0.15.2", "scripts": { "start": "node node_modules/react-native/local-cli/cli.js start", "run:packager": "./node_modules/react-native/packager/packager.sh", From fa2b6c274b6432a13e20018a3591e092f9cac411 Mon Sep 17 00:00:00 2001 From: Ryan Guest Date: Thu, 1 Jun 2017 07:32:50 -0700 Subject: [PATCH 0264/1148] Fix a couple typos (#1375) --- README.md | 2 +- .../main/java/com/airbnb/android/react/maps/AirMapModule.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 49d65ac72..91b22377b 100644 --- a/README.md +++ b/README.md @@ -207,7 +207,7 @@ Then add the AirGoogleMaps directory: https://github.com/airbnb/react-native-maps/blob/1e71a21f39e7b88554852951f773c731c94680c9/docs/installation.md#ios -An unoffical step-by-step guide is also available at https://gist.github.com/heron2014/e60fa003e9b117ce80d56bb1d5bfe9e0 +An unofficial step-by-step guide is also available at https://gist.github.com/heron2014/e60fa003e9b117ce80d56bb1d5bfe9e0 ## Examples diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapModule.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapModule.java index 2cd1ba686..80746a0f1 100644 --- a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapModule.java +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapModule.java @@ -86,7 +86,7 @@ public void execute (NativeViewHierarchyManager nvhm) { view.map.snapshot(new GoogleMap.SnapshotReadyCallback() { public void onSnapshotReady(@Nullable Bitmap snapshot) { - // Convert image to requested width/height if neccesary + // Convert image to requested width/height if necessary if (snapshot == null) { promise.reject("Failed to generate bitmap, snapshot = null"); return; From d62f5ef5ae4edb065643dc1e675753b134e085e2 Mon Sep 17 00:00:00 2001 From: skylabvn Date: Thu, 1 Jun 2017 21:34:27 +0700 Subject: [PATCH 0265/1148] Fix import header for React Native 0.44.2 (#1362) --- lib/ios/AirGoogleMaps/AIRGMSPolyline.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ios/AirGoogleMaps/AIRGMSPolyline.h b/lib/ios/AirGoogleMaps/AIRGMSPolyline.h index 64a3afb99..d7ee19783 100644 --- a/lib/ios/AirGoogleMaps/AIRGMSPolyline.h +++ b/lib/ios/AirGoogleMaps/AIRGMSPolyline.h @@ -6,7 +6,7 @@ // #import -#import "UIView+React.h" +#import @class AIRGoogleMapPolyline; From f6cfb362975b6fef24b07afb897d2659622d2d78 Mon Sep 17 00:00:00 2001 From: Thomas Bouder Date: Thu, 1 Jun 2017 19:47:47 +0200 Subject: [PATCH 0266/1148] Update from View.propTypes to ViewPropTypes to match RN v0.44.0 (#1323) * Upd from View.propTypes to ViewPropTypes * Rm View component --- lib/components/MapCallout.js | 4 ++-- lib/components/MapCircle.js | 4 ++-- lib/components/MapMarker.js | 4 ++-- lib/components/MapPolygon.js | 4 ++-- lib/components/MapPolyline.js | 4 ++-- lib/components/MapUrlTile.js | 4 ++-- lib/components/MapView.js | 6 +++--- 7 files changed, 15 insertions(+), 15 deletions(-) diff --git a/lib/components/MapCallout.js b/lib/components/MapCallout.js index cf4bb9cef..8989df40c 100644 --- a/lib/components/MapCallout.js +++ b/lib/components/MapCallout.js @@ -1,7 +1,7 @@ import React, { PropTypes } from 'react'; import { - View, StyleSheet, + ViewPropTypes, } from 'react-native'; import decorateMapComponent, { SUPPORTED, @@ -9,7 +9,7 @@ import decorateMapComponent, { } from './decorateMapComponent'; const propTypes = { - ...View.propTypes, + ...ViewPropTypes, tooltip: PropTypes.bool, onPress: PropTypes.func, }; diff --git a/lib/components/MapCircle.js b/lib/components/MapCircle.js index aab1ba8f1..a3371ca60 100644 --- a/lib/components/MapCircle.js +++ b/lib/components/MapCircle.js @@ -1,6 +1,6 @@ import React, { PropTypes } from 'react'; import { - View, + ViewPropTypes, } from 'react-native'; import decorateMapComponent, { USES_DEFAULT_IMPLEMENTATION, @@ -8,7 +8,7 @@ import decorateMapComponent, { } from './decorateMapComponent'; const propTypes = { - ...View.propTypes, + ...ViewPropTypes, /** * The coordinate of the center of the circle diff --git a/lib/components/MapMarker.js b/lib/components/MapMarker.js index be54e42db..0589979fa 100644 --- a/lib/components/MapMarker.js +++ b/lib/components/MapMarker.js @@ -1,11 +1,11 @@ import React, { PropTypes } from 'react'; import { - View, StyleSheet, Platform, NativeModules, Animated, findNodeHandle, + ViewPropTypes, } from 'react-native'; import resolveAssetSource from 'react-native/Libraries/Image/resolveAssetSource'; @@ -22,7 +22,7 @@ const viewConfig = { }; const propTypes = { - ...View.propTypes, + ...ViewPropTypes, // TODO(lmr): get rid of these? identifier: PropTypes.string, diff --git a/lib/components/MapPolygon.js b/lib/components/MapPolygon.js index 6901979db..f88648fca 100644 --- a/lib/components/MapPolygon.js +++ b/lib/components/MapPolygon.js @@ -1,6 +1,6 @@ import React, { PropTypes } from 'react'; import { - View, + ViewPropTypes, } from 'react-native'; import decorateMapComponent, { USES_DEFAULT_IMPLEMENTATION, @@ -8,7 +8,7 @@ import decorateMapComponent, { } from './decorateMapComponent'; const propTypes = { - ...View.propTypes, + ...ViewPropTypes, /** * An array of coordinates to describe the polygon diff --git a/lib/components/MapPolyline.js b/lib/components/MapPolyline.js index aa79f096b..b2ecdffc1 100644 --- a/lib/components/MapPolyline.js +++ b/lib/components/MapPolyline.js @@ -1,6 +1,6 @@ import React, { PropTypes } from 'react'; import { - View, + ViewPropTypes, } from 'react-native'; import decorateMapComponent, { USES_DEFAULT_IMPLEMENTATION, @@ -8,7 +8,7 @@ import decorateMapComponent, { } from './decorateMapComponent'; const propTypes = { - ...View.propTypes, + ...ViewPropTypes, /** * An array of coordinates to describe the polygon diff --git a/lib/components/MapUrlTile.js b/lib/components/MapUrlTile.js index cf2770334..bb1d26552 100644 --- a/lib/components/MapUrlTile.js +++ b/lib/components/MapUrlTile.js @@ -1,7 +1,7 @@ import React, { PropTypes } from 'react'; import { - View, + ViewPropTypes, } from 'react-native'; import decorateMapComponent, { @@ -10,7 +10,7 @@ import decorateMapComponent, { } from './decorateMapComponent'; const propTypes = { - ...View.propTypes, + ...ViewPropTypes, /** * The url template of the tile server. The patterns {x} {y} {z} will be replaced at runtime diff --git a/lib/components/MapView.js b/lib/components/MapView.js index f25003b84..0d8bf5450 100644 --- a/lib/components/MapView.js +++ b/lib/components/MapView.js @@ -2,12 +2,12 @@ import React, { PropTypes } from 'react'; import { EdgeInsetsPropType, Platform, - View, Animated, requireNativeComponent, NativeModules, ColorPropType, findNodeHandle, + ViewPropTypes, } from 'react-native'; import MapMarker from './MapMarker'; import MapPolyline from './MapPolyline'; @@ -45,7 +45,7 @@ const viewConfig = { }; const propTypes = { - ...View.propTypes, + ...ViewPropTypes, /** * When provider is "google", we will use GoogleMaps. * Any value other than "google" will default to using @@ -59,7 +59,7 @@ const propTypes = { * Used to style and layout the `MapView`. See `StyleSheet.js` and * `ViewStylePropTypes.js` for more info. */ - style: View.propTypes.style, + style: ViewPropTypes.style, /** * A json object that describes the style of the map. This is transformed to a string From 0c925244cf138905ca0a6d67894f0761c73eb28e Mon Sep 17 00:00:00 2001 From: Ryan Kaskel Date: Thu, 15 Jun 2017 17:34:23 +0100 Subject: [PATCH 0267/1148] [iOS - Google Maps] Fix animateToCoordinate and animateToRegion (#1115) * Add animateToCoordinate to Google Maps on iOS * Add animate to random coordinate button in example app * Fix animateToRegion duration for Google Maps on iOS --- example/examples/DisplayLatLng.js | 36 ++++++++++++++++----- lib/ios/AirGoogleMaps/AIRGoogleMapManager.m | 30 ++++++++++++++--- 2 files changed, 54 insertions(+), 12 deletions(-) diff --git a/example/examples/DisplayLatLng.js b/example/examples/DisplayLatLng.js index 573617d41..aa2dde2ac 100644 --- a/example/examples/DisplayLatLng.js +++ b/example/examples/DisplayLatLng.js @@ -43,15 +43,25 @@ class DisplayLatLng extends React.Component { this.map.animateToRegion(this.randomRegion()); } - randomRegion() { - const { region } = this.state; + animateRandomCoordinate() { + this.map.animateToCoordinate(this.randomCoordinate()); + } + + randomCoordinate() { + const region = this.state.region; return { - ...this.state.region, latitude: region.latitude + ((Math.random() - 0.5) * (region.latitudeDelta / 2)), longitude: region.longitude + ((Math.random() - 0.5) * (region.longitudeDelta / 2)), }; } + randomRegion() { + return { + ...this.state.region, + ...this.randomCoordinate(), + }; + } + render() { return ( @@ -74,13 +84,19 @@ class DisplayLatLng extends React.Component { onPress={() => this.jumpRandom()} style={[styles.bubble, styles.button]} > - Jump + Jump
this.animateRandom()} style={[styles.bubble, styles.button]} > - Animate + Animate (Region) + + this.animateRandomCoordinate()} + style={[styles.bubble, styles.button]} + > + Animate (Coordinate)
@@ -112,16 +128,20 @@ const styles = StyleSheet.create({ alignItems: 'stretch', }, button: { - width: 80, - paddingHorizontal: 12, + width: 100, + paddingHorizontal: 8, alignItems: 'center', - marginHorizontal: 10, + justifyContent: 'center', + marginHorizontal: 5, }, buttonContainer: { flexDirection: 'row', marginVertical: 20, backgroundColor: 'transparent', }, + buttonText: { + textAlign: 'center', + }, }); module.exports = DisplayLatLng; diff --git a/lib/ios/AirGoogleMaps/AIRGoogleMapManager.m b/lib/ios/AirGoogleMaps/AIRGoogleMapManager.m index 785d58d4d..6a3b92e90 100644 --- a/lib/ios/AirGoogleMaps/AIRGoogleMapManager.m +++ b/lib/ios/AirGoogleMaps/AIRGoogleMapManager.m @@ -26,6 +26,7 @@ #import "RCTConvert+AirMap.h" #import +#import static NSString *const RCTMapViewKey = @"MapView"; @@ -75,10 +76,31 @@ - (UIView *)view if (![view isKindOfClass:[AIRGoogleMap class]]) { RCTLogError(@"Invalid view returned from registry, expecting AIRGoogleMap, got: %@", view); } else { - [AIRGoogleMap animateWithDuration:duration/1000 animations:^{ - GMSCameraPosition* camera = [AIRGoogleMap makeGMSCameraPositionFromMap:(AIRGoogleMap *)view andMKCoordinateRegion:region]; - [(AIRGoogleMap *)view animateToCameraPosition:camera]; - }]; + // Core Animation must be used to control the animation's duration + // See http://stackoverflow.com/a/15663039/171744 + [CATransaction begin]; + [CATransaction setAnimationDuration:duration/1000]; + AIRGoogleMap *mapView = (AIRGoogleMap *)view; + GMSCameraPosition *camera = [AIRGoogleMap makeGMSCameraPositionFromMap:mapView andMKCoordinateRegion:region]; + [mapView animateToCameraPosition:camera]; + [CATransaction commit]; + } + }]; +} + +RCT_EXPORT_METHOD(animateToCoordinate:(nonnull NSNumber *)reactTag + withRegion:(CLLocationCoordinate2D)latlng + withDuration:(CGFloat)duration) +{ + [self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary *viewRegistry) { + id view = viewRegistry[reactTag]; + if (![view isKindOfClass:[AIRGoogleMap class]]) { + RCTLogError(@"Invalid view returned from registry, expecting AIRGoogleMap, got: %@", view); + } else { + [CATransaction begin]; + [CATransaction setAnimationDuration:duration/1000]; + [(AIRGoogleMap *)view animateToLocation:latlng]; + [CATransaction commit]; } }]; } From 8f30c8a209fadf473ce4661779eef24d74c2220a Mon Sep 17 00:00:00 2001 From: Chaitanya Bhagvan Date: Sat, 17 Jun 2017 23:48:30 +0530 Subject: [PATCH 0268/1148] Fixes google map null pointer exception (#1403) AirMapView doDestroy is called before LifecycleEventListener onHostPause. This fixes https://github.com/airbnb/react-native-maps/issues/1358 --- .../main/java/com/airbnb/android/react/maps/AirMapView.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java index 3225bf1ff..725270ac6 100644 --- a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java @@ -314,7 +314,9 @@ public void onHostPause() { map.setMyLocationEnabled(false); } synchronized (AirMapView.this) { - AirMapView.this.onPause(); + if(!destroyed) { + AirMapView.this.onPause(); + } paused = true; } } From d2b7b380c26c433244f5ea633dfec8914dde910b Mon Sep 17 00:00:00 2001 From: Felipe Lima Date: Tue, 20 Jun 2017 13:25:22 -0700 Subject: [PATCH 0269/1148] [Android] Code cleanup step I - reformatting (#1415) * Reformat code to match code style settings * Example app reformatting --- .idea/codeStyleSettings.xml | 265 +++ build.gradle | 2 +- example/android/app/build.gradle | 6 +- .../react/maps/example/MainActivity.java | 18 +- gradle/wrapper/gradle-wrapper.properties | 2 +- lib/android/build.gradle | 2 +- .../android/react/maps/AirMapCallout.java | 24 +- .../react/maps/AirMapCalloutManager.java | 80 +- .../android/react/maps/AirMapCircle.java | 150 +- .../react/maps/AirMapCircleManager.java | 88 +- .../android/react/maps/AirMapFeature.java | 12 +- .../android/react/maps/AirMapLiteManager.java | 18 +- .../android/react/maps/AirMapManager.java | 548 +++--- .../android/react/maps/AirMapMarker.java | 758 ++++---- .../react/maps/AirMapMarkerManager.java | 350 ++-- .../android/react/maps/AirMapModule.java | 207 ++- .../android/react/maps/AirMapPolygon.java | 162 +- .../react/maps/AirMapPolygonManager.java | 104 +- .../android/react/maps/AirMapPolyline.java | 146 +- .../react/maps/AirMapPolylineManager.java | 96 +- .../android/react/maps/AirMapUrlTile.java | 141 +- .../react/maps/AirMapUrlTileManager.java | 64 +- .../airbnb/android/react/maps/AirMapView.java | 1537 +++++++++-------- .../android/react/maps/LatLngBoundsUtils.java | 80 +- .../android/react/maps/MapsPackage.java | 74 +- .../android/react/maps/RegionChangeEvent.java | 72 +- .../react/maps/SizeReportingShadowNode.java | 16 +- 27 files changed, 2644 insertions(+), 2378 deletions(-) create mode 100644 .idea/codeStyleSettings.xml diff --git a/.idea/codeStyleSettings.xml b/.idea/codeStyleSettings.xml new file mode 100644 index 000000000..b6cfecda9 --- /dev/null +++ b/.idea/codeStyleSettings.xml @@ -0,0 +1,265 @@ + + + + + + \ No newline at end of file diff --git a/build.gradle b/build.gradle index 8a3e2453e..588e5cb99 100644 --- a/build.gradle +++ b/build.gradle @@ -5,7 +5,7 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:2.3.1' + classpath 'com.android.tools.build:gradle:2.3.2' } } diff --git a/example/android/app/build.gradle b/example/android/app/build.gradle index c5bdebe4c..7c63b3b43 100644 --- a/example/android/app/build.gradle +++ b/example/android/app/build.gradle @@ -85,7 +85,7 @@ def enableProguardInReleaseBuilds = false android { compileSdkVersion 25 - buildToolsVersion "25.0.2" + buildToolsVersion "25.0.3" defaultConfig { applicationId "com.airbnb.android.react.maps.example" @@ -128,7 +128,7 @@ android { dependencies { compile 'com.facebook.react:react-native:0.42.+' - compile 'com.android.support:appcompat-v7:25.1.1' - compile 'com.android.support:support-annotations:25.1.1' + compile 'com.android.support:appcompat-v7:25.3.0' + compile 'com.android.support:support-annotations:25.3.0' compile project(':react-native-maps-lib') } diff --git a/example/android/app/src/main/java/com/airbnb/android/react/maps/example/MainActivity.java b/example/android/app/src/main/java/com/airbnb/android/react/maps/example/MainActivity.java index eec2349a4..12149c20e 100644 --- a/example/android/app/src/main/java/com/airbnb/android/react/maps/example/MainActivity.java +++ b/example/android/app/src/main/java/com/airbnb/android/react/maps/example/MainActivity.java @@ -4,14 +4,12 @@ public class MainActivity extends ReactActivity { - - /** - * Returns the name of the main component registered from JavaScript. - * This is used to schedule rendering of the component. - */ - @Override - protected String getMainComponentName() { - return "AirMapsExplorer"; - } - + /** + * Returns the name of the main component registered from JavaScript. + * This is used to schedule rendering of the component. + */ + @Override + protected String getMainComponentName() { + return "AirMapsExplorer"; + } } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index c21e471fc..e5fa88cc4 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-3.5-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-4.0-all.zip diff --git a/lib/android/build.gradle b/lib/android/build.gradle index 434e63e72..326ab4bfa 100644 --- a/lib/android/build.gradle +++ b/lib/android/build.gradle @@ -3,7 +3,7 @@ apply from: 'gradle-maven-push.gradle' android { compileSdkVersion 25 - buildToolsVersion "25.0.2" + buildToolsVersion "25.0.3" defaultConfig { minSdkVersion 16 diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapCallout.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapCallout.java index c434c9c12..6f96e15da 100644 --- a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapCallout.java +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapCallout.java @@ -5,19 +5,19 @@ import com.facebook.react.views.view.ReactViewGroup; public class AirMapCallout extends ReactViewGroup { - private boolean tooltip = false; - public int width; - public int height; + private boolean tooltip = false; + public int width; + public int height; - public AirMapCallout(Context context) { - super(context); - } + public AirMapCallout(Context context) { + super(context); + } - public void setTooltip(boolean tooltip) { - this.tooltip = tooltip; - } + public void setTooltip(boolean tooltip) { + this.tooltip = tooltip; + } - public boolean getTooltip() { - return this.tooltip; - } + public boolean getTooltip() { + return this.tooltip; + } } diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapCalloutManager.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapCalloutManager.java index 359e6847b..b63ea29ff 100644 --- a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapCalloutManager.java +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapCalloutManager.java @@ -12,45 +12,45 @@ public class AirMapCalloutManager extends ViewGroupManager { - @Override - public String getName() { - return "AIRMapCallout"; - } - - @Override - public AirMapCallout createViewInstance(ThemedReactContext context) { - return new AirMapCallout(context); - } - - @ReactProp(name = "tooltip", defaultBoolean = false) - public void setTooltip(AirMapCallout view, boolean tooltip) { - view.setTooltip(tooltip); - } - - @Override - @Nullable - public Map getExportedCustomDirectEventTypeConstants() { - return MapBuilder.of("onPress", MapBuilder.of("registrationName", "onPress")); - } - - @Override - public LayoutShadowNode createShadowNodeInstance() { - // we use a custom shadow node that emits the width/height of the view - // after layout with the updateExtraData method. Without this, we can't generate - // a bitmap of the appropriate width/height of the rendered view. - return new SizeReportingShadowNode(); - } - - @Override - public void updateExtraData(AirMapCallout view, Object extraData) { - // This method is called from the shadow node with the width/height of the rendered - // marker view. - //noinspection unchecked - Map data = (Map) extraData; - float width = data.get("width"); - float height = data.get("height"); - view.width = (int) width; - view.height = (int) height; - } + @Override + public String getName() { + return "AIRMapCallout"; + } + + @Override + public AirMapCallout createViewInstance(ThemedReactContext context) { + return new AirMapCallout(context); + } + + @ReactProp(name = "tooltip", defaultBoolean = false) + public void setTooltip(AirMapCallout view, boolean tooltip) { + view.setTooltip(tooltip); + } + + @Override + @Nullable + public Map getExportedCustomDirectEventTypeConstants() { + return MapBuilder.of("onPress", MapBuilder.of("registrationName", "onPress")); + } + + @Override + public LayoutShadowNode createShadowNodeInstance() { + // we use a custom shadow node that emits the width/height of the view + // after layout with the updateExtraData method. Without this, we can't generate + // a bitmap of the appropriate width/height of the rendered view. + return new SizeReportingShadowNode(); + } + + @Override + public void updateExtraData(AirMapCallout view, Object extraData) { + // This method is called from the shadow node with the width/height of the rendered + // marker view. + //noinspection unchecked + Map data = (Map) extraData; + float width = data.get("width"); + float height = data.get("height"); + view.width = (int) width; + view.height = (int) height; + } } diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapCircle.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapCircle.java index e428b04f6..a70d9146a 100644 --- a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapCircle.java +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapCircle.java @@ -9,92 +9,92 @@ public class AirMapCircle extends AirMapFeature { - private CircleOptions circleOptions; - private Circle circle; - - private LatLng center; - private double radius; - private int strokeColor; - private int fillColor; - private float strokeWidth; - private float zIndex; - - public AirMapCircle(Context context) { - super(context); + private CircleOptions circleOptions; + private Circle circle; + + private LatLng center; + private double radius; + private int strokeColor; + private int fillColor; + private float strokeWidth; + private float zIndex; + + public AirMapCircle(Context context) { + super(context); + } + + public void setCenter(LatLng center) { + this.center = center; + if (circle != null) { + circle.setCenter(this.center); } + } - public void setCenter(LatLng center) { - this.center = center; - if (circle != null) { - circle.setCenter(this.center); - } + public void setRadius(double radius) { + this.radius = radius; + if (circle != null) { + circle.setRadius(this.radius); } + } - public void setRadius(double radius) { - this.radius = radius; - if (circle != null) { - circle.setRadius(this.radius); - } + public void setFillColor(int color) { + this.fillColor = color; + if (circle != null) { + circle.setFillColor(color); } + } - public void setFillColor(int color) { - this.fillColor = color; - if (circle != null) { - circle.setFillColor(color); - } + public void setStrokeColor(int color) { + this.strokeColor = color; + if (circle != null) { + circle.setStrokeColor(color); } + } - public void setStrokeColor(int color) { - this.strokeColor = color; - if (circle != null) { - circle.setStrokeColor(color); - } + public void setStrokeWidth(float width) { + this.strokeWidth = width; + if (circle != null) { + circle.setStrokeWidth(width); } + } - public void setStrokeWidth(float width) { - this.strokeWidth = width; - if (circle != null) { - circle.setStrokeWidth(width); - } + public void setZIndex(float zIndex) { + this.zIndex = zIndex; + if (circle != null) { + circle.setZIndex(zIndex); } + } - public void setZIndex(float zIndex) { - this.zIndex = zIndex; - if (circle != null) { - circle.setZIndex(zIndex); - } - } - - public CircleOptions getCircleOptions() { - if (circleOptions == null) { - circleOptions = createCircleOptions(); - } - return circleOptions; - } - - private CircleOptions createCircleOptions() { - CircleOptions options = new CircleOptions(); - options.center(center); - options.radius(radius); - options.fillColor(fillColor); - options.strokeColor(strokeColor); - options.strokeWidth(strokeWidth); - options.zIndex(zIndex); - return options; - } - - @Override - public Object getFeature() { - return circle; - } - - @Override - public void addToMap(GoogleMap map) { - circle = map.addCircle(getCircleOptions()); - } - - @Override - public void removeFromMap(GoogleMap map) { - circle.remove(); + public CircleOptions getCircleOptions() { + if (circleOptions == null) { + circleOptions = createCircleOptions(); } + return circleOptions; + } + + private CircleOptions createCircleOptions() { + CircleOptions options = new CircleOptions(); + options.center(center); + options.radius(radius); + options.fillColor(fillColor); + options.strokeColor(strokeColor); + options.strokeWidth(strokeWidth); + options.zIndex(zIndex); + return options; + } + + @Override + public Object getFeature() { + return circle; + } + + @Override + public void addToMap(GoogleMap map) { + circle = map.addCircle(getCircleOptions()); + } + + @Override + public void removeFromMap(GoogleMap map) { + circle.remove(); + } } diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapCircleManager.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapCircleManager.java index c0eaf8f14..c8eabf2d1 100644 --- a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapCircleManager.java +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapCircleManager.java @@ -14,59 +14,59 @@ import com.google.android.gms.maps.model.LatLng; public class AirMapCircleManager extends ViewGroupManager { - private final DisplayMetrics metrics; + private final DisplayMetrics metrics; - public AirMapCircleManager(ReactApplicationContext reactContext) { - super(); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { - metrics = new DisplayMetrics(); - ((WindowManager) reactContext.getSystemService(Context.WINDOW_SERVICE)) - .getDefaultDisplay() - .getRealMetrics(metrics); - } else { - metrics = reactContext.getResources().getDisplayMetrics(); - } + public AirMapCircleManager(ReactApplicationContext reactContext) { + super(); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { + metrics = new DisplayMetrics(); + ((WindowManager) reactContext.getSystemService(Context.WINDOW_SERVICE)) + .getDefaultDisplay() + .getRealMetrics(metrics); + } else { + metrics = reactContext.getResources().getDisplayMetrics(); } + } - @Override - public String getName() { - return "AIRMapCircle"; - } + @Override + public String getName() { + return "AIRMapCircle"; + } - @Override - public AirMapCircle createViewInstance(ThemedReactContext context) { - return new AirMapCircle(context); - } + @Override + public AirMapCircle createViewInstance(ThemedReactContext context) { + return new AirMapCircle(context); + } - @ReactProp(name = "center") - public void setCenter(AirMapCircle view, ReadableMap center) { - view.setCenter(new LatLng(center.getDouble("latitude"), center.getDouble("longitude"))); - } + @ReactProp(name = "center") + public void setCenter(AirMapCircle view, ReadableMap center) { + view.setCenter(new LatLng(center.getDouble("latitude"), center.getDouble("longitude"))); + } - @ReactProp(name = "radius", defaultDouble = 0) - public void setRadius(AirMapCircle view, double radius) { - view.setRadius(radius); - } + @ReactProp(name = "radius", defaultDouble = 0) + public void setRadius(AirMapCircle view, double radius) { + view.setRadius(radius); + } - @ReactProp(name = "strokeWidth", defaultFloat = 1f) - public void setStrokeWidth(AirMapCircle view, float widthInPoints) { - float widthInScreenPx = metrics.density * widthInPoints; // done for parity with iOS - view.setStrokeWidth(widthInScreenPx); - } + @ReactProp(name = "strokeWidth", defaultFloat = 1f) + public void setStrokeWidth(AirMapCircle view, float widthInPoints) { + float widthInScreenPx = metrics.density * widthInPoints; // done for parity with iOS + view.setStrokeWidth(widthInScreenPx); + } - @ReactProp(name = "fillColor", defaultInt = Color.RED, customType = "Color") - public void setFillColor(AirMapCircle view, int color) { - view.setFillColor(color); - } + @ReactProp(name = "fillColor", defaultInt = Color.RED, customType = "Color") + public void setFillColor(AirMapCircle view, int color) { + view.setFillColor(color); + } - @ReactProp(name = "strokeColor", defaultInt = Color.RED, customType = "Color") - public void setStrokeColor(AirMapCircle view, int color) { - view.setStrokeColor(color); - } + @ReactProp(name = "strokeColor", defaultInt = Color.RED, customType = "Color") + public void setStrokeColor(AirMapCircle view, int color) { + view.setStrokeColor(color); + } - @ReactProp(name = "zIndex", defaultFloat = 1.0f) - public void setZIndex(AirMapCircle view, float zIndex) { - view.setZIndex(zIndex); - } + @ReactProp(name = "zIndex", defaultFloat = 1.0f) + public void setZIndex(AirMapCircle view, float zIndex) { + view.setZIndex(zIndex); + } } diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapFeature.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapFeature.java index 1c15ade5f..70484c1a4 100644 --- a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapFeature.java +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapFeature.java @@ -6,13 +6,13 @@ import com.google.android.gms.maps.GoogleMap; public abstract class AirMapFeature extends ReactViewGroup { - public AirMapFeature(Context context) { - super(context); - } + public AirMapFeature(Context context) { + super(context); + } - public abstract void addToMap(GoogleMap map); + public abstract void addToMap(GoogleMap map); - public abstract void removeFromMap(GoogleMap map); + public abstract void removeFromMap(GoogleMap map); - public abstract Object getFeature(); + public abstract Object getFeature(); } diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapLiteManager.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapLiteManager.java index 62495c5e4..619e36435 100644 --- a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapLiteManager.java +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapLiteManager.java @@ -5,16 +5,16 @@ public class AirMapLiteManager extends AirMapManager { - private static final String REACT_CLASS = "AIRMapLite"; + private static final String REACT_CLASS = "AIRMapLite"; - @Override - public String getName() { - return REACT_CLASS; - } + @Override + public String getName() { + return REACT_CLASS; + } - public AirMapLiteManager(ReactApplicationContext context) { - super(context); - this.googleMapOptions = new GoogleMapOptions().liteMode(true); - } + public AirMapLiteManager(ReactApplicationContext context) { + super(context); + this.googleMapOptions = new GoogleMapOptions().liteMode(true); + } } diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java index b6a975b77..404f6a127 100644 --- a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java @@ -4,7 +4,6 @@ import com.facebook.react.bridge.Arguments; import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.ReactContext; import com.facebook.react.bridge.ReadableArray; import com.facebook.react.bridge.ReadableMap; import com.facebook.react.bridge.WritableMap; @@ -17,7 +16,6 @@ import com.facebook.react.uimanager.events.RCTEventEmitter; import com.google.android.gms.maps.GoogleMap; import com.google.android.gms.maps.GoogleMapOptions; -import com.google.android.gms.maps.MapsInitializer; import com.google.android.gms.maps.model.LatLng; import com.google.android.gms.maps.model.LatLngBounds; import com.google.android.gms.maps.model.MapStyleOptions; @@ -28,280 +26,280 @@ public class AirMapManager extends ViewGroupManager { - private static final String REACT_CLASS = "AIRMap"; - private static final int ANIMATE_TO_REGION = 1; - private static final int ANIMATE_TO_COORDINATE = 2; - private static final int FIT_TO_ELEMENTS = 3; - private static final int FIT_TO_SUPPLIED_MARKERS = 4; - private static final int FIT_TO_COORDINATES = 5; - - private final Map MAP_TYPES = MapBuilder.of( - "standard", GoogleMap.MAP_TYPE_NORMAL, - "satellite", GoogleMap.MAP_TYPE_SATELLITE, - "hybrid", GoogleMap.MAP_TYPE_HYBRID, - "terrain", GoogleMap.MAP_TYPE_TERRAIN, - "none", GoogleMap.MAP_TYPE_NONE - ); - - private final ReactApplicationContext appContext; - - protected GoogleMapOptions googleMapOptions; - - public AirMapManager(ReactApplicationContext context) { - this.appContext = context; - this.googleMapOptions = new GoogleMapOptions(); - } - - @Override - public String getName() { - return REACT_CLASS; - } - - @Override - protected AirMapView createViewInstance(ThemedReactContext context) { - return new AirMapView(context, this.appContext, this, googleMapOptions); - } - - private void emitMapError(ThemedReactContext context, String message, String type) { - WritableMap error = Arguments.createMap(); - error.putString("message", message); - error.putString("type", type); - - context - .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class) - .emit("onError", error); - } - - @ReactProp(name = "region") - public void setRegion(AirMapView view, ReadableMap region) { - view.setRegion(region); - } - - @ReactProp(name = "mapType") - public void setMapType(AirMapView view, @Nullable String mapType) { - int typeId = MAP_TYPES.get(mapType); - view.map.setMapType(typeId); - } - - @ReactProp(name = "customMapStyleString") - public void setMapStyle(AirMapView view, @Nullable String customMapStyleString) { - view.map.setMapStyle(new MapStyleOptions(customMapStyleString)); - } - - @ReactProp(name = "showsUserLocation", defaultBoolean = false) - public void setShowsUserLocation(AirMapView view, boolean showUserLocation) { - view.setShowsUserLocation(showUserLocation); - } - - @ReactProp(name = "showsMyLocationButton", defaultBoolean = true) - public void setShowsMyLocationButton(AirMapView view, boolean showMyLocationButton) { - view.setShowsMyLocationButton(showMyLocationButton); - } - - @ReactProp(name = "toolbarEnabled", defaultBoolean = true) - public void setToolbarEnabled(AirMapView view, boolean toolbarEnabled) { - view.setToolbarEnabled(toolbarEnabled); - } - - // This is a private prop to improve performance of panDrag by disabling it when the callback is not set - @ReactProp(name = "handlePanDrag", defaultBoolean = false) - public void setHandlePanDrag(AirMapView view, boolean handlePanDrag) { - view.setHandlePanDrag(handlePanDrag); - } - - @ReactProp(name = "showsTraffic", defaultBoolean = false) - public void setShowTraffic(AirMapView view, boolean showTraffic) { - view.map.setTrafficEnabled(showTraffic); - } - - @ReactProp(name = "showsBuildings", defaultBoolean = false) - public void setShowBuildings(AirMapView view, boolean showBuildings) { - view.map.setBuildingsEnabled(showBuildings); - } - - @ReactProp(name = "showsIndoors", defaultBoolean = false) - public void setShowIndoors(AirMapView view, boolean showIndoors) { - view.map.setIndoorEnabled(showIndoors); - } - - @ReactProp(name = "showsIndoorLevelPicker", defaultBoolean = false) - public void setShowsIndoorLevelPicker(AirMapView view, boolean showsIndoorLevelPicker) { - view.map.getUiSettings().setIndoorLevelPickerEnabled(showsIndoorLevelPicker); - } - - @ReactProp(name = "showsCompass", defaultBoolean = false) - public void setShowsCompass(AirMapView view, boolean showsCompass) { - view.map.getUiSettings().setCompassEnabled(showsCompass); - } - - @ReactProp(name = "scrollEnabled", defaultBoolean = false) - public void setScrollEnabled(AirMapView view, boolean scrollEnabled) { - view.map.getUiSettings().setScrollGesturesEnabled(scrollEnabled); - } - - @ReactProp(name = "zoomEnabled", defaultBoolean = false) - public void setZoomEnabled(AirMapView view, boolean zoomEnabled) { - view.map.getUiSettings().setZoomGesturesEnabled(zoomEnabled); - } - - @ReactProp(name = "rotateEnabled", defaultBoolean = false) - public void setRotateEnabled(AirMapView view, boolean rotateEnabled) { - view.map.getUiSettings().setRotateGesturesEnabled(rotateEnabled); - } - - @ReactProp(name = "cacheEnabled", defaultBoolean = false) - public void setCacheEnabled(AirMapView view, boolean cacheEnabled) { - view.setCacheEnabled(cacheEnabled); - } - - @ReactProp(name = "loadingEnabled", defaultBoolean = false) - public void setLoadingEnabled(AirMapView view, boolean loadingEnabled) { - view.enableMapLoading(loadingEnabled); - } - - @ReactProp(name = "moveOnMarkerPress", defaultBoolean = true) - public void setMoveOnMarkerPress(AirMapView view, boolean moveOnPress) { - view.setMoveOnMarkerPress(moveOnPress); - } - - @ReactProp(name = "loadingBackgroundColor", customType = "Color") - public void setLoadingBackgroundColor(AirMapView view, @Nullable Integer loadingBackgroundColor) { - view.setLoadingBackgroundColor(loadingBackgroundColor); - } - - @ReactProp(name = "loadingIndicatorColor", customType = "Color") - public void setLoadingIndicatorColor(AirMapView view, @Nullable Integer loadingIndicatorColor) { - view.setLoadingIndicatorColor(loadingIndicatorColor); - } - - @ReactProp(name = "pitchEnabled", defaultBoolean = false) - public void setPitchEnabled(AirMapView view, boolean pitchEnabled) { - view.map.getUiSettings().setTiltGesturesEnabled(pitchEnabled); - } - - @Override - public void receiveCommand(AirMapView view, int commandId, @Nullable ReadableArray args) { - Integer duration; - Double lat; - Double lng; - Double lngDelta; - Double latDelta; - ReadableMap region; - - switch (commandId) { - case ANIMATE_TO_REGION: - region = args.getMap(0); - duration = args.getInt(1); - lng = region.getDouble("longitude"); - lat = region.getDouble("latitude"); - lngDelta = region.getDouble("longitudeDelta"); - latDelta = region.getDouble("latitudeDelta"); - LatLngBounds bounds = new LatLngBounds( - new LatLng(lat - latDelta / 2, lng - lngDelta / 2), // southwest - new LatLng(lat + latDelta / 2, lng + lngDelta / 2) // northeast - ); - view.animateToRegion(bounds, duration); - break; - - case ANIMATE_TO_COORDINATE: - region = args.getMap(0); - duration = args.getInt(1); - lng = region.getDouble("longitude"); - lat = region.getDouble("latitude"); - view.animateToCoordinate(new LatLng(lat, lng), duration); - break; - - case FIT_TO_ELEMENTS: - view.fitToElements(args.getBoolean(0)); - break; - - case FIT_TO_SUPPLIED_MARKERS: - view.fitToSuppliedMarkers(args.getArray(0), args.getBoolean(1)); - break; - case FIT_TO_COORDINATES: - view.fitToCoordinates(args.getArray(0), args.getMap(1), args.getBoolean(2)); - break; - } - } - - @Override - @Nullable - public Map getExportedCustomDirectEventTypeConstants() { - Map> map = MapBuilder.of( - "onMapReady", MapBuilder.of("registrationName", "onMapReady"), - "onPress", MapBuilder.of("registrationName", "onPress"), - "onLongPress", MapBuilder.of("registrationName", "onLongPress"), - "onMarkerPress", MapBuilder.of("registrationName", "onMarkerPress"), - "onMarkerSelect", MapBuilder.of("registrationName", "onMarkerSelect"), - "onMarkerDeselect", MapBuilder.of("registrationName", "onMarkerDeselect"), - "onCalloutPress", MapBuilder.of("registrationName", "onCalloutPress") - ); - - map.putAll(MapBuilder.of( - "onMarkerDragStart", MapBuilder.of("registrationName", "onMarkerDragStart"), - "onMarkerDrag", MapBuilder.of("registrationName", "onMarkerDrag"), - "onMarkerDragEnd", MapBuilder.of("registrationName", "onMarkerDragEnd"), - "onPanDrag", MapBuilder.of("registrationName", "onPanDrag") - )); - - return map; - } - - @Override - @Nullable - public Map getCommandsMap() { - return MapBuilder.of( - "animateToRegion", ANIMATE_TO_REGION, - "animateToCoordinate", ANIMATE_TO_COORDINATE, - "fitToElements", FIT_TO_ELEMENTS, - "fitToSuppliedMarkers", FIT_TO_SUPPLIED_MARKERS, - "fitToCoordinates", FIT_TO_COORDINATES + private static final String REACT_CLASS = "AIRMap"; + private static final int ANIMATE_TO_REGION = 1; + private static final int ANIMATE_TO_COORDINATE = 2; + private static final int FIT_TO_ELEMENTS = 3; + private static final int FIT_TO_SUPPLIED_MARKERS = 4; + private static final int FIT_TO_COORDINATES = 5; + + private final Map MAP_TYPES = MapBuilder.of( + "standard", GoogleMap.MAP_TYPE_NORMAL, + "satellite", GoogleMap.MAP_TYPE_SATELLITE, + "hybrid", GoogleMap.MAP_TYPE_HYBRID, + "terrain", GoogleMap.MAP_TYPE_TERRAIN, + "none", GoogleMap.MAP_TYPE_NONE + ); + + private final ReactApplicationContext appContext; + + protected GoogleMapOptions googleMapOptions; + + public AirMapManager(ReactApplicationContext context) { + this.appContext = context; + this.googleMapOptions = new GoogleMapOptions(); + } + + @Override + public String getName() { + return REACT_CLASS; + } + + @Override + protected AirMapView createViewInstance(ThemedReactContext context) { + return new AirMapView(context, this.appContext, this, googleMapOptions); + } + + private void emitMapError(ThemedReactContext context, String message, String type) { + WritableMap error = Arguments.createMap(); + error.putString("message", message); + error.putString("type", type); + + context + .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class) + .emit("onError", error); + } + + @ReactProp(name = "region") + public void setRegion(AirMapView view, ReadableMap region) { + view.setRegion(region); + } + + @ReactProp(name = "mapType") + public void setMapType(AirMapView view, @Nullable String mapType) { + int typeId = MAP_TYPES.get(mapType); + view.map.setMapType(typeId); + } + + @ReactProp(name = "customMapStyleString") + public void setMapStyle(AirMapView view, @Nullable String customMapStyleString) { + view.map.setMapStyle(new MapStyleOptions(customMapStyleString)); + } + + @ReactProp(name = "showsUserLocation", defaultBoolean = false) + public void setShowsUserLocation(AirMapView view, boolean showUserLocation) { + view.setShowsUserLocation(showUserLocation); + } + + @ReactProp(name = "showsMyLocationButton", defaultBoolean = true) + public void setShowsMyLocationButton(AirMapView view, boolean showMyLocationButton) { + view.setShowsMyLocationButton(showMyLocationButton); + } + + @ReactProp(name = "toolbarEnabled", defaultBoolean = true) + public void setToolbarEnabled(AirMapView view, boolean toolbarEnabled) { + view.setToolbarEnabled(toolbarEnabled); + } + + // This is a private prop to improve performance of panDrag by disabling it when the callback + // is not set + @ReactProp(name = "handlePanDrag", defaultBoolean = false) + public void setHandlePanDrag(AirMapView view, boolean handlePanDrag) { + view.setHandlePanDrag(handlePanDrag); + } + + @ReactProp(name = "showsTraffic", defaultBoolean = false) + public void setShowTraffic(AirMapView view, boolean showTraffic) { + view.map.setTrafficEnabled(showTraffic); + } + + @ReactProp(name = "showsBuildings", defaultBoolean = false) + public void setShowBuildings(AirMapView view, boolean showBuildings) { + view.map.setBuildingsEnabled(showBuildings); + } + + @ReactProp(name = "showsIndoors", defaultBoolean = false) + public void setShowIndoors(AirMapView view, boolean showIndoors) { + view.map.setIndoorEnabled(showIndoors); + } + + @ReactProp(name = "showsIndoorLevelPicker", defaultBoolean = false) + public void setShowsIndoorLevelPicker(AirMapView view, boolean showsIndoorLevelPicker) { + view.map.getUiSettings().setIndoorLevelPickerEnabled(showsIndoorLevelPicker); + } + + @ReactProp(name = "showsCompass", defaultBoolean = false) + public void setShowsCompass(AirMapView view, boolean showsCompass) { + view.map.getUiSettings().setCompassEnabled(showsCompass); + } + + @ReactProp(name = "scrollEnabled", defaultBoolean = false) + public void setScrollEnabled(AirMapView view, boolean scrollEnabled) { + view.map.getUiSettings().setScrollGesturesEnabled(scrollEnabled); + } + + @ReactProp(name = "zoomEnabled", defaultBoolean = false) + public void setZoomEnabled(AirMapView view, boolean zoomEnabled) { + view.map.getUiSettings().setZoomGesturesEnabled(zoomEnabled); + } + + @ReactProp(name = "rotateEnabled", defaultBoolean = false) + public void setRotateEnabled(AirMapView view, boolean rotateEnabled) { + view.map.getUiSettings().setRotateGesturesEnabled(rotateEnabled); + } + + @ReactProp(name = "cacheEnabled", defaultBoolean = false) + public void setCacheEnabled(AirMapView view, boolean cacheEnabled) { + view.setCacheEnabled(cacheEnabled); + } + + @ReactProp(name = "loadingEnabled", defaultBoolean = false) + public void setLoadingEnabled(AirMapView view, boolean loadingEnabled) { + view.enableMapLoading(loadingEnabled); + } + + @ReactProp(name = "moveOnMarkerPress", defaultBoolean = true) + public void setMoveOnMarkerPress(AirMapView view, boolean moveOnPress) { + view.setMoveOnMarkerPress(moveOnPress); + } + + @ReactProp(name = "loadingBackgroundColor", customType = "Color") + public void setLoadingBackgroundColor(AirMapView view, @Nullable Integer loadingBackgroundColor) { + view.setLoadingBackgroundColor(loadingBackgroundColor); + } + + @ReactProp(name = "loadingIndicatorColor", customType = "Color") + public void setLoadingIndicatorColor(AirMapView view, @Nullable Integer loadingIndicatorColor) { + view.setLoadingIndicatorColor(loadingIndicatorColor); + } + + @ReactProp(name = "pitchEnabled", defaultBoolean = false) + public void setPitchEnabled(AirMapView view, boolean pitchEnabled) { + view.map.getUiSettings().setTiltGesturesEnabled(pitchEnabled); + } + + @Override + public void receiveCommand(AirMapView view, int commandId, @Nullable ReadableArray args) { + Integer duration; + Double lat; + Double lng; + Double lngDelta; + Double latDelta; + ReadableMap region; + + switch (commandId) { + case ANIMATE_TO_REGION: + region = args.getMap(0); + duration = args.getInt(1); + lng = region.getDouble("longitude"); + lat = region.getDouble("latitude"); + lngDelta = region.getDouble("longitudeDelta"); + latDelta = region.getDouble("latitudeDelta"); + LatLngBounds bounds = new LatLngBounds( + new LatLng(lat - latDelta / 2, lng - lngDelta / 2), // southwest + new LatLng(lat + latDelta / 2, lng + lngDelta / 2) // northeast ); - } - - @Override - public LayoutShadowNode createShadowNodeInstance() { - // A custom shadow node is needed in order to pass back the width/height of the map to the - // view manager so that it can start applying camera moves with bounds. - return new SizeReportingShadowNode(); - } - - @Override - public void addView(AirMapView parent, View child, int index) { - parent.addFeature(child, index); - } - - @Override - public int getChildCount(AirMapView view) { - return view.getFeatureCount(); - } - - @Override - public View getChildAt(AirMapView view, int index) { - return view.getFeatureAt(index); - } - - @Override - public void removeViewAt(AirMapView parent, int index) { - parent.removeFeatureAt(index); - } - - @Override - public void updateExtraData(AirMapView view, Object extraData) { - view.updateExtraData(extraData); - } - - void pushEvent(ThemedReactContext context, View view, String name, WritableMap data) { - context.getJSModule(RCTEventEmitter.class) - .receiveEvent(view.getId(), name, data); - } - - + view.animateToRegion(bounds, duration); + break; + + case ANIMATE_TO_COORDINATE: + region = args.getMap(0); + duration = args.getInt(1); + lng = region.getDouble("longitude"); + lat = region.getDouble("latitude"); + view.animateToCoordinate(new LatLng(lat, lng), duration); + break; + + case FIT_TO_ELEMENTS: + view.fitToElements(args.getBoolean(0)); + break; + + case FIT_TO_SUPPLIED_MARKERS: + view.fitToSuppliedMarkers(args.getArray(0), args.getBoolean(1)); + break; + case FIT_TO_COORDINATES: + view.fitToCoordinates(args.getArray(0), args.getMap(1), args.getBoolean(2)); + break; + } + } + + @Override + @Nullable + public Map getExportedCustomDirectEventTypeConstants() { + Map> map = MapBuilder.of( + "onMapReady", MapBuilder.of("registrationName", "onMapReady"), + "onPress", MapBuilder.of("registrationName", "onPress"), + "onLongPress", MapBuilder.of("registrationName", "onLongPress"), + "onMarkerPress", MapBuilder.of("registrationName", "onMarkerPress"), + "onMarkerSelect", MapBuilder.of("registrationName", "onMarkerSelect"), + "onMarkerDeselect", MapBuilder.of("registrationName", "onMarkerDeselect"), + "onCalloutPress", MapBuilder.of("registrationName", "onCalloutPress") + ); - @Override - public void onDropViewInstance(AirMapView view) { - view.doDestroy(); - super.onDropViewInstance(view); - } + map.putAll(MapBuilder.of( + "onMarkerDragStart", MapBuilder.of("registrationName", "onMarkerDragStart"), + "onMarkerDrag", MapBuilder.of("registrationName", "onMarkerDrag"), + "onMarkerDragEnd", MapBuilder.of("registrationName", "onMarkerDragEnd"), + "onPanDrag", MapBuilder.of("registrationName", "onPanDrag") + )); + + return map; + } + + @Override + @Nullable + public Map getCommandsMap() { + return MapBuilder.of( + "animateToRegion", ANIMATE_TO_REGION, + "animateToCoordinate", ANIMATE_TO_COORDINATE, + "fitToElements", FIT_TO_ELEMENTS, + "fitToSuppliedMarkers", FIT_TO_SUPPLIED_MARKERS, + "fitToCoordinates", FIT_TO_COORDINATES + ); + } + + @Override + public LayoutShadowNode createShadowNodeInstance() { + // A custom shadow node is needed in order to pass back the width/height of the map to the + // view manager so that it can start applying camera moves with bounds. + return new SizeReportingShadowNode(); + } + + @Override + public void addView(AirMapView parent, View child, int index) { + parent.addFeature(child, index); + } + + @Override + public int getChildCount(AirMapView view) { + return view.getFeatureCount(); + } + + @Override + public View getChildAt(AirMapView view, int index) { + return view.getFeatureAt(index); + } + + @Override + public void removeViewAt(AirMapView parent, int index) { + parent.removeFeatureAt(index); + } + + @Override + public void updateExtraData(AirMapView view, Object extraData) { + view.updateExtraData(extraData); + } + + void pushEvent(ThemedReactContext context, View view, String name, WritableMap data) { + context.getJSModule(RCTEventEmitter.class) + .receiveEvent(view.getId(), name, data); + } + + + @Override + public void onDropViewInstance(AirMapView view) { + view.doDestroy(); + super.onDropViewInstance(view); + } } diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapMarker.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapMarker.java index 4041d91ac..52c4dcd08 100644 --- a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapMarker.java +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapMarker.java @@ -36,395 +36,395 @@ public class AirMapMarker extends AirMapFeature { - private MarkerOptions markerOptions; - private Marker marker; - private int width; - private int height; - private String identifier; - - private LatLng position; - private String title; - private String snippet; - - private boolean anchorIsSet; - private float anchorX; - private float anchorY; - - private AirMapCallout calloutView; - private View wrappedCalloutView; - private final Context context; - - private float markerHue = 0.0f; // should be between 0 and 360 - private BitmapDescriptor iconBitmapDescriptor; - private Bitmap iconBitmap; - - private float rotation = 0.0f; - private boolean flat = false; - private boolean draggable = false; - private int zIndex = 0; - private float opacity = 1.0f; - - private float calloutAnchorX; - private float calloutAnchorY; - private boolean calloutAnchorIsSet; - - private boolean hasCustomMarkerView = false; - - private final DraweeHolder logoHolder; - private DataSource> dataSource; - private final ControllerListener mLogoControllerListener = - new BaseControllerListener() { - @Override - public void onFinalImageSet( - String id, - @Nullable final ImageInfo imageInfo, - @Nullable Animatable animatable) { - CloseableReference imageReference = null; - try { - imageReference = dataSource.getResult(); - if (imageReference != null) { - CloseableImage image = imageReference.get(); - if (image != null && image instanceof CloseableStaticBitmap) { - CloseableStaticBitmap closeableStaticBitmap = (CloseableStaticBitmap) image; - Bitmap bitmap = closeableStaticBitmap.getUnderlyingBitmap(); - if (bitmap != null) { - bitmap = bitmap.copy(Bitmap.Config.ARGB_8888, true); - iconBitmap = bitmap; - iconBitmapDescriptor = BitmapDescriptorFactory.fromBitmap(bitmap); - } - } - } - } finally { - dataSource.close(); - if (imageReference != null) { - CloseableReference.closeSafely(imageReference); - } - } - update(); + private MarkerOptions markerOptions; + private Marker marker; + private int width; + private int height; + private String identifier; + + private LatLng position; + private String title; + private String snippet; + + private boolean anchorIsSet; + private float anchorX; + private float anchorY; + + private AirMapCallout calloutView; + private View wrappedCalloutView; + private final Context context; + + private float markerHue = 0.0f; // should be between 0 and 360 + private BitmapDescriptor iconBitmapDescriptor; + private Bitmap iconBitmap; + + private float rotation = 0.0f; + private boolean flat = false; + private boolean draggable = false; + private int zIndex = 0; + private float opacity = 1.0f; + + private float calloutAnchorX; + private float calloutAnchorY; + private boolean calloutAnchorIsSet; + + private boolean hasCustomMarkerView = false; + + private final DraweeHolder logoHolder; + private DataSource> dataSource; + private final ControllerListener mLogoControllerListener = + new BaseControllerListener() { + @Override + public void onFinalImageSet( + String id, + @Nullable final ImageInfo imageInfo, + @Nullable Animatable animatable) { + CloseableReference imageReference = null; + try { + imageReference = dataSource.getResult(); + if (imageReference != null) { + CloseableImage image = imageReference.get(); + if (image != null && image instanceof CloseableStaticBitmap) { + CloseableStaticBitmap closeableStaticBitmap = (CloseableStaticBitmap) image; + Bitmap bitmap = closeableStaticBitmap.getUnderlyingBitmap(); + if (bitmap != null) { + bitmap = bitmap.copy(Bitmap.Config.ARGB_8888, true); + iconBitmap = bitmap; + iconBitmapDescriptor = BitmapDescriptorFactory.fromBitmap(bitmap); } - }; - - public AirMapMarker(Context context) { - super(context); - this.context = context; - logoHolder = DraweeHolder.create(createDraweeHierarchy(), context); - logoHolder.onAttach(); - } - - private GenericDraweeHierarchy createDraweeHierarchy() { - return new GenericDraweeHierarchyBuilder(getResources()) - .setActualImageScaleType(ScalingUtils.ScaleType.FIT_CENTER) - .setFadeDuration(0) - .build(); - } - - public void setCoordinate(ReadableMap coordinate) { - position = new LatLng(coordinate.getDouble("latitude"), coordinate.getDouble("longitude")); - if (marker != null) { - marker.setPosition(position); - } - update(); - } - - public void setIdentifier(String identifier) { - this.identifier = identifier; - update(); - } - - public String getIdentifier() { - return this.identifier; - } - - public void setTitle(String title) { - this.title = title; - if (marker != null) { - marker.setTitle(title); - } - update(); - } - - public void setSnippet(String snippet) { - this.snippet = snippet; - if (marker != null) { - marker.setSnippet(snippet); - } - update(); - } - - public void setRotation(float rotation) { - this.rotation = rotation; - if (marker != null) { - marker.setRotation(rotation); - } - update(); - } - - public void setFlat(boolean flat) { - this.flat = flat; - if (marker != null) { - marker.setFlat(flat); - } - update(); - } - - public void setDraggable(boolean draggable) { - this.draggable = draggable; - if (marker != null) { - marker.setDraggable(draggable); - } - update(); - } - - public void setZIndex(int zIndex) { - this.zIndex = zIndex; - if (marker != null) { - marker.setZIndex(zIndex); - } - update(); - } - - public void setOpacity(float opacity) { - this.opacity = opacity; - if (marker != null) { - marker.setAlpha(opacity); - } - update(); - } - - public void setMarkerHue(float markerHue) { - this.markerHue = markerHue; - update(); - } - - public void setAnchor(double x, double y) { - anchorIsSet = true; - anchorX = (float) x; - anchorY = (float) y; - if (marker != null) { - marker.setAnchor(anchorX, anchorY); - } - update(); - } - - public void setCalloutAnchor(double x, double y) { - calloutAnchorIsSet = true; - calloutAnchorX = (float) x; - calloutAnchorY = (float) y; - if (marker != null) { - marker.setInfoWindowAnchor(calloutAnchorX, calloutAnchorY); - } - update(); - } - - public void setImage(String uri) { - if (uri == null) { - iconBitmapDescriptor = null; - update(); - } else if (uri.startsWith("http://") || uri.startsWith("https://") || - uri.startsWith("file://")) { - ImageRequest imageRequest = ImageRequestBuilder - .newBuilderWithSource(Uri.parse(uri)) - .build(); - - ImagePipeline imagePipeline = Fresco.getImagePipeline(); - dataSource = imagePipeline.fetchDecodedImage(imageRequest, this); - DraweeController controller = Fresco.newDraweeControllerBuilder() - .setImageRequest(imageRequest) - .setControllerListener(mLogoControllerListener) - .setOldController(logoHolder.getController()) - .build(); - logoHolder.setController(controller); - } else { - iconBitmapDescriptor = getBitmapDescriptorByName(uri); - update(); - } - } - - public MarkerOptions getMarkerOptions() { - if (markerOptions == null) { - markerOptions = createMarkerOptions(); - } - return markerOptions; - } - - @Override - public void addView(View child, int index) { - super.addView(child, index); - // if children are added, it means we are rendering a custom marker - if (!(child instanceof AirMapCallout)) { - hasCustomMarkerView = true; - } - update(); - } - - @Override - public Object getFeature() { - return marker; - } - - @Override - public void addToMap(GoogleMap map) { - marker = map.addMarker(getMarkerOptions()); - } - - @Override - public void removeFromMap(GoogleMap map) { - marker.remove(); - marker = null; - } - - private BitmapDescriptor getIcon() { - if (hasCustomMarkerView) { - // creating a bitmap from an arbitrary view - if (iconBitmapDescriptor != null) { - Bitmap viewBitmap = createDrawable(); - int width = Math.max(iconBitmap.getWidth(), viewBitmap.getWidth()); - int height = Math.max(iconBitmap.getHeight(), viewBitmap.getHeight()); - Bitmap combinedBitmap = Bitmap.createBitmap(width, height, iconBitmap.getConfig()); - Canvas canvas = new Canvas(combinedBitmap); - canvas.drawBitmap(iconBitmap, 0, 0, null); - canvas.drawBitmap(viewBitmap, 0, 0, null); - return BitmapDescriptorFactory.fromBitmap(combinedBitmap); - } else { - return BitmapDescriptorFactory.fromBitmap(createDrawable()); + } } - } else if (iconBitmapDescriptor != null) { - // use local image as a marker - return iconBitmapDescriptor; - } else { - // render the default marker pin - return BitmapDescriptorFactory.defaultMarker(this.markerHue); - } - } - - private MarkerOptions createMarkerOptions() { - MarkerOptions options = new MarkerOptions().position(position); - if (anchorIsSet) options.anchor(anchorX, anchorY); - if (calloutAnchorIsSet) options.infoWindowAnchor(calloutAnchorX, calloutAnchorY); - options.title(title); - options.snippet(snippet); - options.rotation(rotation); - options.flat(flat); - options.draggable(draggable); - options.zIndex(zIndex); - options.alpha(opacity); - options.icon(getIcon()); - return options; - } - - public void update() { - if (marker == null) { - return; - } - - marker.setIcon(getIcon()); - - if (anchorIsSet) { - marker.setAnchor(anchorX, anchorY); - } else { - marker.setAnchor(0.5f, 1.0f); - } - - if (calloutAnchorIsSet) { - marker.setInfoWindowAnchor(calloutAnchorX, calloutAnchorY); - } else { - marker.setInfoWindowAnchor(0.5f, 0); - } - } - - public void update(int width, int height) { - this.width = width; - this.height = height; - update(); - } - - private Bitmap createDrawable() { - int width = this.width <= 0 ? 100 : this.width; - int height = this.height <= 0 ? 100 : this.height; - this.buildDrawingCache(); - Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); - - Canvas canvas = new Canvas(bitmap); - this.draw(canvas); - - return bitmap; - } - - public void setCalloutView(AirMapCallout view) { - this.calloutView = view; - } - - public AirMapCallout getCalloutView() { - return this.calloutView; - } - - public View getCallout() { - if (this.calloutView == null) return null; - - if (this.wrappedCalloutView == null) { - this.wrapCalloutView(); - } - - if (this.calloutView.getTooltip()) { - return this.wrappedCalloutView; - } else { - return null; - } - } - - public View getInfoContents() { - if (this.calloutView == null) return null; - - if (this.wrappedCalloutView == null) { - this.wrapCalloutView(); - } - - if (this.calloutView.getTooltip()) { - return null; - } else { - return this.wrappedCalloutView; + } finally { + dataSource.close(); + if (imageReference != null) { + CloseableReference.closeSafely(imageReference); + } + } + update(); } + }; + + public AirMapMarker(Context context) { + super(context); + this.context = context; + logoHolder = DraweeHolder.create(createDraweeHierarchy(), context); + logoHolder.onAttach(); + } + + private GenericDraweeHierarchy createDraweeHierarchy() { + return new GenericDraweeHierarchyBuilder(getResources()) + .setActualImageScaleType(ScalingUtils.ScaleType.FIT_CENTER) + .setFadeDuration(0) + .build(); + } + + public void setCoordinate(ReadableMap coordinate) { + position = new LatLng(coordinate.getDouble("latitude"), coordinate.getDouble("longitude")); + if (marker != null) { + marker.setPosition(position); + } + update(); + } + + public void setIdentifier(String identifier) { + this.identifier = identifier; + update(); + } + + public String getIdentifier() { + return this.identifier; + } + + public void setTitle(String title) { + this.title = title; + if (marker != null) { + marker.setTitle(title); + } + update(); + } + + public void setSnippet(String snippet) { + this.snippet = snippet; + if (marker != null) { + marker.setSnippet(snippet); + } + update(); + } + + public void setRotation(float rotation) { + this.rotation = rotation; + if (marker != null) { + marker.setRotation(rotation); + } + update(); + } + + public void setFlat(boolean flat) { + this.flat = flat; + if (marker != null) { + marker.setFlat(flat); + } + update(); + } + + public void setDraggable(boolean draggable) { + this.draggable = draggable; + if (marker != null) { + marker.setDraggable(draggable); + } + update(); + } + + public void setZIndex(int zIndex) { + this.zIndex = zIndex; + if (marker != null) { + marker.setZIndex(zIndex); + } + update(); + } + + public void setOpacity(float opacity) { + this.opacity = opacity; + if (marker != null) { + marker.setAlpha(opacity); + } + update(); + } + + public void setMarkerHue(float markerHue) { + this.markerHue = markerHue; + update(); + } + + public void setAnchor(double x, double y) { + anchorIsSet = true; + anchorX = (float) x; + anchorY = (float) y; + if (marker != null) { + marker.setAnchor(anchorX, anchorY); + } + update(); + } + + public void setCalloutAnchor(double x, double y) { + calloutAnchorIsSet = true; + calloutAnchorX = (float) x; + calloutAnchorY = (float) y; + if (marker != null) { + marker.setInfoWindowAnchor(calloutAnchorX, calloutAnchorY); + } + update(); + } + + public void setImage(String uri) { + if (uri == null) { + iconBitmapDescriptor = null; + update(); + } else if (uri.startsWith("http://") || uri.startsWith("https://") || + uri.startsWith("file://")) { + ImageRequest imageRequest = ImageRequestBuilder + .newBuilderWithSource(Uri.parse(uri)) + .build(); + + ImagePipeline imagePipeline = Fresco.getImagePipeline(); + dataSource = imagePipeline.fetchDecodedImage(imageRequest, this); + DraweeController controller = Fresco.newDraweeControllerBuilder() + .setImageRequest(imageRequest) + .setControllerListener(mLogoControllerListener) + .setOldController(logoHolder.getController()) + .build(); + logoHolder.setController(controller); + } else { + iconBitmapDescriptor = getBitmapDescriptorByName(uri); + update(); + } + } + + public MarkerOptions getMarkerOptions() { + if (markerOptions == null) { + markerOptions = createMarkerOptions(); + } + return markerOptions; + } + + @Override + public void addView(View child, int index) { + super.addView(child, index); + // if children are added, it means we are rendering a custom marker + if (!(child instanceof AirMapCallout)) { + hasCustomMarkerView = true; + } + update(); + } + + @Override + public Object getFeature() { + return marker; + } + + @Override + public void addToMap(GoogleMap map) { + marker = map.addMarker(getMarkerOptions()); + } + + @Override + public void removeFromMap(GoogleMap map) { + marker.remove(); + marker = null; + } + + private BitmapDescriptor getIcon() { + if (hasCustomMarkerView) { + // creating a bitmap from an arbitrary view + if (iconBitmapDescriptor != null) { + Bitmap viewBitmap = createDrawable(); + int width = Math.max(iconBitmap.getWidth(), viewBitmap.getWidth()); + int height = Math.max(iconBitmap.getHeight(), viewBitmap.getHeight()); + Bitmap combinedBitmap = Bitmap.createBitmap(width, height, iconBitmap.getConfig()); + Canvas canvas = new Canvas(combinedBitmap); + canvas.drawBitmap(iconBitmap, 0, 0, null); + canvas.drawBitmap(viewBitmap, 0, 0, null); + return BitmapDescriptorFactory.fromBitmap(combinedBitmap); + } else { + return BitmapDescriptorFactory.fromBitmap(createDrawable()); + } + } else if (iconBitmapDescriptor != null) { + // use local image as a marker + return iconBitmapDescriptor; + } else { + // render the default marker pin + return BitmapDescriptorFactory.defaultMarker(this.markerHue); + } + } + + private MarkerOptions createMarkerOptions() { + MarkerOptions options = new MarkerOptions().position(position); + if (anchorIsSet) options.anchor(anchorX, anchorY); + if (calloutAnchorIsSet) options.infoWindowAnchor(calloutAnchorX, calloutAnchorY); + options.title(title); + options.snippet(snippet); + options.rotation(rotation); + options.flat(flat); + options.draggable(draggable); + options.zIndex(zIndex); + options.alpha(opacity); + options.icon(getIcon()); + return options; + } + + public void update() { + if (marker == null) { + return; + } + + marker.setIcon(getIcon()); + + if (anchorIsSet) { + marker.setAnchor(anchorX, anchorY); + } else { + marker.setAnchor(0.5f, 1.0f); + } + + if (calloutAnchorIsSet) { + marker.setInfoWindowAnchor(calloutAnchorX, calloutAnchorY); + } else { + marker.setInfoWindowAnchor(0.5f, 0); + } + } + + public void update(int width, int height) { + this.width = width; + this.height = height; + update(); + } + + private Bitmap createDrawable() { + int width = this.width <= 0 ? 100 : this.width; + int height = this.height <= 0 ? 100 : this.height; + this.buildDrawingCache(); + Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); + + Canvas canvas = new Canvas(bitmap); + this.draw(canvas); + + return bitmap; + } + + public void setCalloutView(AirMapCallout view) { + this.calloutView = view; + } + + public AirMapCallout getCalloutView() { + return this.calloutView; + } + + public View getCallout() { + if (this.calloutView == null) return null; + + if (this.wrappedCalloutView == null) { + this.wrapCalloutView(); + } + + if (this.calloutView.getTooltip()) { + return this.wrappedCalloutView; + } else { + return null; + } + } + + public View getInfoContents() { + if (this.calloutView == null) return null; + + if (this.wrappedCalloutView == null) { + this.wrapCalloutView(); + } + + if (this.calloutView.getTooltip()) { + return null; + } else { + return this.wrappedCalloutView; + } + } + + private void wrapCalloutView() { + // some hackery is needed to get the arbitrary infowindow view to render centered, and + // with only the width/height that it needs. + if (this.calloutView == null || this.calloutView.getChildCount() == 0) { + return; } - private void wrapCalloutView() { - // some hackery is needed to get the arbitrary infowindow view to render centered, and - // with only the width/height that it needs. - if (this.calloutView == null || this.calloutView.getChildCount() == 0) { - return; - } + LinearLayout LL = new LinearLayout(context); + LL.setOrientation(LinearLayout.VERTICAL); + LL.setLayoutParams(new LinearLayout.LayoutParams( + this.calloutView.width, + this.calloutView.height, + 0f + )); - LinearLayout LL = new LinearLayout(context); - LL.setOrientation(LinearLayout.VERTICAL); - LL.setLayoutParams(new LinearLayout.LayoutParams( - this.calloutView.width, - this.calloutView.height, - 0f - )); + LinearLayout LL2 = new LinearLayout(context); + LL2.setOrientation(LinearLayout.HORIZONTAL); + LL2.setLayoutParams(new LinearLayout.LayoutParams( + this.calloutView.width, + this.calloutView.height, + 0f + )); - LinearLayout LL2 = new LinearLayout(context); - LL2.setOrientation(LinearLayout.HORIZONTAL); - LL2.setLayoutParams(new LinearLayout.LayoutParams( - this.calloutView.width, - this.calloutView.height, - 0f - )); + LL.addView(LL2); + LL2.addView(this.calloutView); - LL.addView(LL2); - LL2.addView(this.calloutView); + this.wrappedCalloutView = LL; + } - this.wrappedCalloutView = LL; - } + private int getDrawableResourceByName(String name) { + return getResources().getIdentifier( + name, + "drawable", + getContext().getPackageName()); + } - private int getDrawableResourceByName(String name) { - return getResources().getIdentifier( - name, - "drawable", - getContext().getPackageName()); - } - - private BitmapDescriptor getBitmapDescriptorByName(String name) { - return BitmapDescriptorFactory.fromResource(getDrawableResourceByName(name)); - } + private BitmapDescriptor getBitmapDescriptorByName(String name) { + return BitmapDescriptorFactory.fromResource(getDrawableResourceByName(name)); + } } diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapMarkerManager.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapMarkerManager.java index e035e1e14..3aef3148c 100644 --- a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapMarkerManager.java +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapMarkerManager.java @@ -19,46 +19,46 @@ public class AirMapMarkerManager extends ViewGroupManager { - private static final int SHOW_INFO_WINDOW = 1; - private static final int HIDE_INFO_WINDOW = 2; - - public AirMapMarkerManager() { - } - - @Override - public String getName() { - return "AIRMapMarker"; - } - - @Override - public AirMapMarker createViewInstance(ThemedReactContext context) { - return new AirMapMarker(context); - } - - @ReactProp(name = "coordinate") - public void setCoordinate(AirMapMarker view, ReadableMap map) { - view.setCoordinate(map); - } - - @ReactProp(name = "title") - public void setTitle(AirMapMarker view, String title) { - view.setTitle(title); - } - - @ReactProp(name = "identifier") - public void setIdentifier(AirMapMarker view, String identifier) { - view.setIdentifier(identifier); - } - - @ReactProp(name = "description") - public void setDescription(AirMapMarker view, String description) { - view.setSnippet(description); - } - - // NOTE(lmr): - // android uses normalized coordinate systems for this, and is provided through the - // `anchor` property and `calloutAnchor` instead. Perhaps some work could be done - // to normalize iOS and android to use just one of the systems. + private static final int SHOW_INFO_WINDOW = 1; + private static final int HIDE_INFO_WINDOW = 2; + + public AirMapMarkerManager() { + } + + @Override + public String getName() { + return "AIRMapMarker"; + } + + @Override + public AirMapMarker createViewInstance(ThemedReactContext context) { + return new AirMapMarker(context); + } + + @ReactProp(name = "coordinate") + public void setCoordinate(AirMapMarker view, ReadableMap map) { + view.setCoordinate(map); + } + + @ReactProp(name = "title") + public void setTitle(AirMapMarker view, String title) { + view.setTitle(title); + } + + @ReactProp(name = "identifier") + public void setIdentifier(AirMapMarker view, String identifier) { + view.setIdentifier(identifier); + } + + @ReactProp(name = "description") + public void setDescription(AirMapMarker view, String description) { + view.setSnippet(description); + } + + // NOTE(lmr): + // android uses normalized coordinate systems for this, and is provided through the + // `anchor` property and `calloutAnchor` instead. Perhaps some work could be done + // to normalize iOS and android to use just one of the systems. // @ReactProp(name = "centerOffset") // public void setCenterOffset(AirMapMarker view, ReadableMap map) { // @@ -69,143 +69,143 @@ public void setDescription(AirMapMarker view, String description) { // // } - @ReactProp(name = "anchor") - public void setAnchor(AirMapMarker view, ReadableMap map) { - // should default to (0.5, 1) (bottom middle) - double x = map != null && map.hasKey("x") ? map.getDouble("x") : 0.5; - double y = map != null && map.hasKey("y") ? map.getDouble("y") : 1.0; - view.setAnchor(x, y); - } - - @ReactProp(name = "calloutAnchor") - public void setCalloutAnchor(AirMapMarker view, ReadableMap map) { - // should default to (0.5, 0) (top middle) - double x = map != null && map.hasKey("x") ? map.getDouble("x") : 0.5; - double y = map != null && map.hasKey("y") ? map.getDouble("y") : 0.0; - view.setCalloutAnchor(x, y); - } - - @ReactProp(name = "image") - public void setImage(AirMapMarker view, @Nullable String source) { - view.setImage(source); - } + @ReactProp(name = "anchor") + public void setAnchor(AirMapMarker view, ReadableMap map) { + // should default to (0.5, 1) (bottom middle) + double x = map != null && map.hasKey("x") ? map.getDouble("x") : 0.5; + double y = map != null && map.hasKey("y") ? map.getDouble("y") : 1.0; + view.setAnchor(x, y); + } + + @ReactProp(name = "calloutAnchor") + public void setCalloutAnchor(AirMapMarker view, ReadableMap map) { + // should default to (0.5, 0) (top middle) + double x = map != null && map.hasKey("x") ? map.getDouble("x") : 0.5; + double y = map != null && map.hasKey("y") ? map.getDouble("y") : 0.0; + view.setCalloutAnchor(x, y); + } + + @ReactProp(name = "image") + public void setImage(AirMapMarker view, @Nullable String source) { + view.setImage(source); + } // public void setImage(AirMapMarker view, ReadableMap image) { // view.setImage(image); // } - @ReactProp(name = "pinColor", defaultInt = Color.RED, customType = "Color") - public void setPinColor(AirMapMarker view, int pinColor) { - float[] hsv = new float[3]; - Color.colorToHSV(pinColor, hsv); - // NOTE: android only supports a hue - view.setMarkerHue(hsv[0]); - } - - @ReactProp(name = "rotation", defaultFloat = 0.0f) - public void setMarkerRotation(AirMapMarker view, float rotation) { - view.setRotation(rotation); - } - - @ReactProp(name = "flat", defaultBoolean = false) - public void setFlat(AirMapMarker view, boolean flat) { - view.setFlat(flat); - } - - @ReactProp(name = "draggable", defaultBoolean = false) - public void setDraggable(AirMapMarker view, boolean draggable) { - view.setDraggable(draggable); - } - - @Override - @ReactProp(name = "zIndex", defaultFloat = 0.0f) - public void setZIndex(AirMapMarker view, float zIndex) { - super.setZIndex(view, zIndex); - int integerZIndex = Math.round(zIndex); - view.setZIndex(integerZIndex); - } - - @Override - @ReactProp(name = "opacity", defaultFloat = 1.0f) - public void setOpacity(AirMapMarker view, float opacity) { - super.setOpacity(view, opacity); - view.setOpacity(opacity); - } - - @Override - public void addView(AirMapMarker parent, View child, int index) { - // if an component is a child, then it is a callout view, NOT part of the - // marker. - if (child instanceof AirMapCallout) { - parent.setCalloutView((AirMapCallout) child); - } else { - super.addView(parent, child, index); - parent.update(); - } - } - - @Override - public void removeViewAt(AirMapMarker parent, int index) { - super.removeViewAt(parent, index); - parent.update(); - } - - @Override - @Nullable - public Map getCommandsMap() { - return MapBuilder.of( - "showCallout", SHOW_INFO_WINDOW, - "hideCallout", HIDE_INFO_WINDOW - ); - } - - @Override - public void receiveCommand(AirMapMarker view, int commandId, @Nullable ReadableArray args) { - switch (commandId) { - case SHOW_INFO_WINDOW: - ((Marker) view.getFeature()).showInfoWindow(); - break; - - case HIDE_INFO_WINDOW: - ((Marker) view.getFeature()).hideInfoWindow(); - break; - } - } - - @Override - @Nullable - public Map getExportedCustomDirectEventTypeConstants() { - Map> map = MapBuilder.of( - "onPress", MapBuilder.of("registrationName", "onPress"), - "onCalloutPress", MapBuilder.of("registrationName", "onCalloutPress"), - "onDragStart", MapBuilder.of("registrationName", "onDragStart"), - "onDrag", MapBuilder.of("registrationName", "onDrag"), - "onDragEnd", MapBuilder.of("registrationName", "onDragEnd") - ); - - map.putAll(MapBuilder.of( - "onDragStart", MapBuilder.of("registrationName", "onDragStart"), - "onDrag", MapBuilder.of("registrationName", "onDrag"), - "onDragEnd", MapBuilder.of("registrationName", "onDragEnd") - )); - - return map; - } - - @Override - public LayoutShadowNode createShadowNodeInstance() { - // we use a custom shadow node that emits the width/height of the view - // after layout with the updateExtraData method. Without this, we can't generate - // a bitmap of the appropriate width/height of the rendered view. - return new SizeReportingShadowNode(); - } - - @Override - public void updateExtraData(AirMapMarker view, Object extraData) { - // This method is called from the shadow node with the width/height of the rendered - // marker view. - HashMap data = (HashMap) extraData; - float width = data.get("width"); - float height = data.get("height"); - view.update((int) width, (int) height); - } + @ReactProp(name = "pinColor", defaultInt = Color.RED, customType = "Color") + public void setPinColor(AirMapMarker view, int pinColor) { + float[] hsv = new float[3]; + Color.colorToHSV(pinColor, hsv); + // NOTE: android only supports a hue + view.setMarkerHue(hsv[0]); + } + + @ReactProp(name = "rotation", defaultFloat = 0.0f) + public void setMarkerRotation(AirMapMarker view, float rotation) { + view.setRotation(rotation); + } + + @ReactProp(name = "flat", defaultBoolean = false) + public void setFlat(AirMapMarker view, boolean flat) { + view.setFlat(flat); + } + + @ReactProp(name = "draggable", defaultBoolean = false) + public void setDraggable(AirMapMarker view, boolean draggable) { + view.setDraggable(draggable); + } + + @Override + @ReactProp(name = "zIndex", defaultFloat = 0.0f) + public void setZIndex(AirMapMarker view, float zIndex) { + super.setZIndex(view, zIndex); + int integerZIndex = Math.round(zIndex); + view.setZIndex(integerZIndex); + } + + @Override + @ReactProp(name = "opacity", defaultFloat = 1.0f) + public void setOpacity(AirMapMarker view, float opacity) { + super.setOpacity(view, opacity); + view.setOpacity(opacity); + } + + @Override + public void addView(AirMapMarker parent, View child, int index) { + // if an component is a child, then it is a callout view, NOT part of the + // marker. + if (child instanceof AirMapCallout) { + parent.setCalloutView((AirMapCallout) child); + } else { + super.addView(parent, child, index); + parent.update(); + } + } + + @Override + public void removeViewAt(AirMapMarker parent, int index) { + super.removeViewAt(parent, index); + parent.update(); + } + + @Override + @Nullable + public Map getCommandsMap() { + return MapBuilder.of( + "showCallout", SHOW_INFO_WINDOW, + "hideCallout", HIDE_INFO_WINDOW + ); + } + + @Override + public void receiveCommand(AirMapMarker view, int commandId, @Nullable ReadableArray args) { + switch (commandId) { + case SHOW_INFO_WINDOW: + ((Marker) view.getFeature()).showInfoWindow(); + break; + + case HIDE_INFO_WINDOW: + ((Marker) view.getFeature()).hideInfoWindow(); + break; + } + } + + @Override + @Nullable + public Map getExportedCustomDirectEventTypeConstants() { + Map> map = MapBuilder.of( + "onPress", MapBuilder.of("registrationName", "onPress"), + "onCalloutPress", MapBuilder.of("registrationName", "onCalloutPress"), + "onDragStart", MapBuilder.of("registrationName", "onDragStart"), + "onDrag", MapBuilder.of("registrationName", "onDrag"), + "onDragEnd", MapBuilder.of("registrationName", "onDragEnd") + ); + + map.putAll(MapBuilder.of( + "onDragStart", MapBuilder.of("registrationName", "onDragStart"), + "onDrag", MapBuilder.of("registrationName", "onDrag"), + "onDragEnd", MapBuilder.of("registrationName", "onDragEnd") + )); + + return map; + } + + @Override + public LayoutShadowNode createShadowNodeInstance() { + // we use a custom shadow node that emits the width/height of the view + // after layout with the updateExtraData method. Without this, we can't generate + // a bitmap of the appropriate width/height of the rendered view. + return new SizeReportingShadowNode(); + } + + @Override + public void updateExtraData(AirMapMarker view, Object extraData) { + // This method is called from the shadow node with the width/height of the rendered + // marker view. + HashMap data = (HashMap) extraData; + float width = data.get("width"); + float height = data.get("height"); + view.update((int) width, (int) height); + } } diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapModule.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapModule.java index 80746a0f1..1a096255e 100644 --- a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapModule.java +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapModule.java @@ -1,128 +1,127 @@ package com.airbnb.android.react.maps; import android.app.Activity; -import android.util.DisplayMetrics; -import android.util.Base64; import android.graphics.Bitmap; import android.net.Uri; -import android.view.View; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.OutputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.Closeable; - -import javax.annotation.Nullable; +import android.util.Base64; +import android.util.DisplayMetrics; +import com.facebook.react.bridge.Promise; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactContextBaseJavaModule; -import com.facebook.react.bridge.ReadableMap; -import com.facebook.react.bridge.Promise; import com.facebook.react.bridge.ReactMethod; -import com.facebook.react.uimanager.UIManagerModule; -import com.facebook.react.uimanager.UIBlock; +import com.facebook.react.bridge.ReadableMap; import com.facebook.react.uimanager.NativeViewHierarchyManager; - +import com.facebook.react.uimanager.UIBlock; +import com.facebook.react.uimanager.UIManagerModule; import com.google.android.gms.maps.GoogleMap; -public class AirMapModule extends ReactContextBaseJavaModule { - - private static final String SNAPSHOT_RESULT_FILE = "file"; - private static final String SNAPSHOT_RESULT_BASE64 = "base64"; - private static final String SNAPSHOT_FORMAT_PNG = "png"; - private static final String SNAPSHOT_FORMAT_JPG = "jpg"; - - public AirMapModule(ReactApplicationContext reactContext) { - super(reactContext); - } +import java.io.ByteArrayOutputStream; +import java.io.Closeable; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; - @Override - public String getName() { - return "AirMapModule"; - } +import javax.annotation.Nullable; - public Activity getActivity() { - return getCurrentActivity(); - } +public class AirMapModule extends ReactContextBaseJavaModule { - public static void closeQuietly(Closeable closeable) { - if (closeable == null) return; - try { - closeable.close(); - } catch (IOException ignored) { - } + private static final String SNAPSHOT_RESULT_FILE = "file"; + private static final String SNAPSHOT_RESULT_BASE64 = "base64"; + private static final String SNAPSHOT_FORMAT_PNG = "png"; + private static final String SNAPSHOT_FORMAT_JPG = "jpg"; + + public AirMapModule(ReactApplicationContext reactContext) { + super(reactContext); + } + + @Override + public String getName() { + return "AirMapModule"; + } + + public Activity getActivity() { + return getCurrentActivity(); + } + + public static void closeQuietly(Closeable closeable) { + if (closeable == null) return; + try { + closeable.close(); + } catch (IOException ignored) { } + } - @ReactMethod - public void takeSnapshot(final int tag, final ReadableMap options, final Promise promise) { + @ReactMethod + public void takeSnapshot(final int tag, final ReadableMap options, final Promise promise) { - // Parse and verity options - final ReactApplicationContext context = getReactApplicationContext(); - final String format = options.hasKey("format") ? options.getString("format") : "png"; - final Bitmap.CompressFormat compressFormat = - format.equals(SNAPSHOT_FORMAT_PNG) ? Bitmap.CompressFormat.PNG : + // Parse and verity options + final ReactApplicationContext context = getReactApplicationContext(); + final String format = options.hasKey("format") ? options.getString("format") : "png"; + final Bitmap.CompressFormat compressFormat = + format.equals(SNAPSHOT_FORMAT_PNG) ? Bitmap.CompressFormat.PNG : format.equals(SNAPSHOT_FORMAT_JPG) ? Bitmap.CompressFormat.JPEG : null; - final double quality = options.hasKey("quality") ? options.getDouble("quality") : 1.0; - final DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics(); - final Integer width = options.hasKey("width") ? (int)(displayMetrics.density * options.getDouble("width")) : 0; - final Integer height = options.hasKey("height") ? (int)(displayMetrics.density * options.getDouble("height")) : 0; - final String result = options.hasKey("result") ? options.getString("result") : "file"; - - // Add UI-block so we can get a valid reference to the map-view - UIManagerModule uiManager = context.getNativeModule(UIManagerModule.class); - uiManager.addUIBlock(new UIBlock() { - public void execute (NativeViewHierarchyManager nvhm) { - AirMapView view = (AirMapView) nvhm.resolveView(tag); - if (view == null) { - promise.reject("AirMapView not found"); - return; - } - if (view.map == null) { - promise.reject("AirMapView.map is not valid"); - return; - } - view.map.snapshot(new GoogleMap.SnapshotReadyCallback() { - public void onSnapshotReady(@Nullable Bitmap snapshot) { + final double quality = options.hasKey("quality") ? options.getDouble("quality") : 1.0; + final DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics(); + final Integer width = + options.hasKey("width") ? (int) (displayMetrics.density * options.getDouble("width")) : 0; + final Integer height = + options.hasKey("height") ? (int) (displayMetrics.density * options.getDouble("height")) : 0; + final String result = options.hasKey("result") ? options.getString("result") : "file"; + + // Add UI-block so we can get a valid reference to the map-view + UIManagerModule uiManager = context.getNativeModule(UIManagerModule.class); + uiManager.addUIBlock(new UIBlock() { + public void execute(NativeViewHierarchyManager nvhm) { + AirMapView view = (AirMapView) nvhm.resolveView(tag); + if (view == null) { + promise.reject("AirMapView not found"); + return; + } + if (view.map == null) { + promise.reject("AirMapView.map is not valid"); + return; + } + view.map.snapshot(new GoogleMap.SnapshotReadyCallback() { + public void onSnapshotReady(@Nullable Bitmap snapshot) { - // Convert image to requested width/height if necessary - if (snapshot == null) { - promise.reject("Failed to generate bitmap, snapshot = null"); - return; - } - if ((width != 0) && (height != 0) && (width != snapshot.getWidth() || height != snapshot.getHeight())) { - snapshot = Bitmap.createScaledBitmap(snapshot, width, height, true); - } + // Convert image to requested width/height if necessary + if (snapshot == null) { + promise.reject("Failed to generate bitmap, snapshot = null"); + return; + } + if ((width != 0) && (height != 0) && + (width != snapshot.getWidth() || height != snapshot.getHeight())) { + snapshot = Bitmap.createScaledBitmap(snapshot, width, height, true); + } - // Save the snapshot to disk - if (result.equals(SNAPSHOT_RESULT_FILE)) { - File tempFile; - FileOutputStream outputStream; - try { - tempFile = File.createTempFile("AirMapSnapshot", "." + format, context.getCacheDir()); - outputStream = new FileOutputStream(tempFile); - } - catch (Exception e) { - promise.reject(e); - return; - } - snapshot.compress(compressFormat, (int)(100.0 * quality), outputStream); - closeQuietly(outputStream); - String uri = Uri.fromFile(tempFile).toString(); - promise.resolve(uri); - } - else if (result.equals(SNAPSHOT_RESULT_BASE64)) { - ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - snapshot.compress(compressFormat, (int)(100.0 * quality), outputStream); - closeQuietly(outputStream); - byte[] bytes = outputStream.toByteArray(); - String data = Base64.encodeToString(bytes, Base64.NO_WRAP); - promise.resolve(data); - } - } - }); + // Save the snapshot to disk + if (result.equals(SNAPSHOT_RESULT_FILE)) { + File tempFile; + FileOutputStream outputStream; + try { + tempFile = + File.createTempFile("AirMapSnapshot", "." + format, context.getCacheDir()); + outputStream = new FileOutputStream(tempFile); + } catch (Exception e) { + promise.reject(e); + return; + } + snapshot.compress(compressFormat, (int) (100.0 * quality), outputStream); + closeQuietly(outputStream); + String uri = Uri.fromFile(tempFile).toString(); + promise.resolve(uri); + } else if (result.equals(SNAPSHOT_RESULT_BASE64)) { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + snapshot.compress(compressFormat, (int) (100.0 * quality), outputStream); + closeQuietly(outputStream); + byte[] bytes = outputStream.toByteArray(); + String data = Base64.encodeToString(bytes, Base64.NO_WRAP); + promise.resolve(data); } + } }); - } + } + }); + } } diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapPolygon.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapPolygon.java index 226bc241c..41257b32e 100644 --- a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapPolygon.java +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapPolygon.java @@ -14,99 +14,99 @@ public class AirMapPolygon extends AirMapFeature { - private PolygonOptions polygonOptions; - private Polygon polygon; - - private List coordinates; - private int strokeColor; - private int fillColor; - private float strokeWidth; - private boolean geodesic; - private float zIndex; - - public AirMapPolygon(Context context) { - super(context); + private PolygonOptions polygonOptions; + private Polygon polygon; + + private List coordinates; + private int strokeColor; + private int fillColor; + private float strokeWidth; + private boolean geodesic; + private float zIndex; + + public AirMapPolygon(Context context) { + super(context); + } + + public void setCoordinates(ReadableArray coordinates) { + // it's kind of a bummer that we can't run map() or anything on the ReadableArray + this.coordinates = new ArrayList<>(coordinates.size()); + for (int i = 0; i < coordinates.size(); i++) { + ReadableMap coordinate = coordinates.getMap(i); + this.coordinates.add(i, + new LatLng(coordinate.getDouble("latitude"), coordinate.getDouble("longitude"))); } - - public void setCoordinates(ReadableArray coordinates) { - // it's kind of a bummer that we can't run map() or anything on the ReadableArray - this.coordinates = new ArrayList<>(coordinates.size()); - for (int i = 0; i < coordinates.size(); i++) { - ReadableMap coordinate = coordinates.getMap(i); - this.coordinates.add(i, - new LatLng(coordinate.getDouble("latitude"), coordinate.getDouble("longitude"))); - } - if (polygon != null) { - polygon.setPoints(this.coordinates); - } - } - - public void setFillColor(int color) { - this.fillColor = color; - if (polygon != null) { - polygon.setFillColor(color); - } - } - - public void setStrokeColor(int color) { - this.strokeColor = color; - if (polygon != null) { - polygon.setStrokeColor(color); - } - } - - public void setStrokeWidth(float width) { - this.strokeWidth = width; - if (polygon != null) { - polygon.setStrokeWidth(width); - } - } - - public void setGeodesic(boolean geodesic) { - this.geodesic = geodesic; - if (polygon != null) { - polygon.setGeodesic(geodesic); - } + if (polygon != null) { + polygon.setPoints(this.coordinates); } + } - public void setZIndex(float zIndex) { - this.zIndex = zIndex; - if (polygon != null) { - polygon.setZIndex(zIndex); - } + public void setFillColor(int color) { + this.fillColor = color; + if (polygon != null) { + polygon.setFillColor(color); } + } - public PolygonOptions getPolygonOptions() { - if (polygonOptions == null) { - polygonOptions = createPolygonOptions(); - } - return polygonOptions; + public void setStrokeColor(int color) { + this.strokeColor = color; + if (polygon != null) { + polygon.setStrokeColor(color); } + } - private PolygonOptions createPolygonOptions() { - PolygonOptions options = new PolygonOptions(); - options.addAll(coordinates); - options.fillColor(fillColor); - options.strokeColor(strokeColor); - options.strokeWidth(strokeWidth); - options.geodesic(geodesic); - options.zIndex(zIndex); - return options; + public void setStrokeWidth(float width) { + this.strokeWidth = width; + if (polygon != null) { + polygon.setStrokeWidth(width); } + } - @Override - public Object getFeature() { - return polygon; + public void setGeodesic(boolean geodesic) { + this.geodesic = geodesic; + if (polygon != null) { + polygon.setGeodesic(geodesic); } + } - @Override - public void addToMap(GoogleMap map) { - polygon = map.addPolygon(getPolygonOptions()); - polygon.setClickable(true); + public void setZIndex(float zIndex) { + this.zIndex = zIndex; + if (polygon != null) { + polygon.setZIndex(zIndex); } + } - @Override - public void removeFromMap(GoogleMap map) { - polygon.remove(); + public PolygonOptions getPolygonOptions() { + if (polygonOptions == null) { + polygonOptions = createPolygonOptions(); } + return polygonOptions; + } + + private PolygonOptions createPolygonOptions() { + PolygonOptions options = new PolygonOptions(); + options.addAll(coordinates); + options.fillColor(fillColor); + options.strokeColor(strokeColor); + options.strokeWidth(strokeWidth); + options.geodesic(geodesic); + options.zIndex(zIndex); + return options; + } + + @Override + public Object getFeature() { + return polygon; + } + + @Override + public void addToMap(GoogleMap map) { + polygon = map.addPolygon(getPolygonOptions()); + polygon.setClickable(true); + } + + @Override + public void removeFromMap(GoogleMap map) { + polygon.remove(); + } } diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapPolygonManager.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapPolygonManager.java index 3eaa0e550..6f1605758 100644 --- a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapPolygonManager.java +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapPolygonManager.java @@ -13,71 +13,71 @@ import com.facebook.react.uimanager.ViewGroupManager; import com.facebook.react.uimanager.annotations.ReactProp; -import java.util.HashMap; import java.util.Map; + import javax.annotation.Nullable; public class AirMapPolygonManager extends ViewGroupManager { - private final DisplayMetrics metrics; + private final DisplayMetrics metrics; - public AirMapPolygonManager(ReactApplicationContext reactContext) { - super(); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { - metrics = new DisplayMetrics(); - ((WindowManager) reactContext.getSystemService(Context.WINDOW_SERVICE)) - .getDefaultDisplay() - .getRealMetrics(metrics); - } else { - metrics = reactContext.getResources().getDisplayMetrics(); - } + public AirMapPolygonManager(ReactApplicationContext reactContext) { + super(); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { + metrics = new DisplayMetrics(); + ((WindowManager) reactContext.getSystemService(Context.WINDOW_SERVICE)) + .getDefaultDisplay() + .getRealMetrics(metrics); + } else { + metrics = reactContext.getResources().getDisplayMetrics(); } + } - @Override - public String getName() { - return "AIRMapPolygon"; - } + @Override + public String getName() { + return "AIRMapPolygon"; + } - @Override - public AirMapPolygon createViewInstance(ThemedReactContext context) { - return new AirMapPolygon(context); - } + @Override + public AirMapPolygon createViewInstance(ThemedReactContext context) { + return new AirMapPolygon(context); + } - @ReactProp(name = "coordinates") - public void setCoordinate(AirMapPolygon view, ReadableArray coordinates) { - view.setCoordinates(coordinates); - } + @ReactProp(name = "coordinates") + public void setCoordinate(AirMapPolygon view, ReadableArray coordinates) { + view.setCoordinates(coordinates); + } - @ReactProp(name = "strokeWidth", defaultFloat = 1f) - public void setStrokeWidth(AirMapPolygon view, float widthInPoints) { - float widthInScreenPx = metrics.density * widthInPoints; // done for parity with iOS - view.setStrokeWidth(widthInScreenPx); - } + @ReactProp(name = "strokeWidth", defaultFloat = 1f) + public void setStrokeWidth(AirMapPolygon view, float widthInPoints) { + float widthInScreenPx = metrics.density * widthInPoints; // done for parity with iOS + view.setStrokeWidth(widthInScreenPx); + } - @ReactProp(name = "fillColor", defaultInt = Color.RED, customType = "Color") - public void setFillColor(AirMapPolygon view, int color) { - view.setFillColor(color); - } + @ReactProp(name = "fillColor", defaultInt = Color.RED, customType = "Color") + public void setFillColor(AirMapPolygon view, int color) { + view.setFillColor(color); + } - @ReactProp(name = "strokeColor", defaultInt = Color.RED, customType = "Color") - public void setStrokeColor(AirMapPolygon view, int color) { - view.setStrokeColor(color); - } + @ReactProp(name = "strokeColor", defaultInt = Color.RED, customType = "Color") + public void setStrokeColor(AirMapPolygon view, int color) { + view.setStrokeColor(color); + } - @ReactProp(name = "geodesic", defaultBoolean = false) - public void setGeodesic(AirMapPolygon view, boolean geodesic) { - view.setGeodesic(geodesic); - } + @ReactProp(name = "geodesic", defaultBoolean = false) + public void setGeodesic(AirMapPolygon view, boolean geodesic) { + view.setGeodesic(geodesic); + } - @ReactProp(name = "zIndex", defaultFloat = 1.0f) - public void setZIndex(AirMapPolygon view, float zIndex) { - view.setZIndex(zIndex); - } + @ReactProp(name = "zIndex", defaultFloat = 1.0f) + public void setZIndex(AirMapPolygon view, float zIndex) { + view.setZIndex(zIndex); + } - @Override - @Nullable - public Map getExportedCustomDirectEventTypeConstants() { - return MapBuilder.of( - "onPress", MapBuilder.of("registrationName", "onPress") - ); - } + @Override + @Nullable + public Map getExportedCustomDirectEventTypeConstants() { + return MapBuilder.of( + "onPress", MapBuilder.of("registrationName", "onPress") + ); + } } diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapPolyline.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapPolyline.java index 9a15fdc99..488e2972f 100644 --- a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapPolyline.java +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapPolyline.java @@ -14,89 +14,89 @@ public class AirMapPolyline extends AirMapFeature { - private PolylineOptions polylineOptions; - private Polyline polyline; - - private List coordinates; - private int color; - private float width; - private boolean geodesic; - private float zIndex; - - public AirMapPolyline(Context context) { - super(context); - } - - public void setCoordinates(ReadableArray coordinates) { - this.coordinates = new ArrayList<>(coordinates.size()); - for (int i = 0; i < coordinates.size(); i++) { - ReadableMap coordinate = coordinates.getMap(i); - this.coordinates.add(i, - new LatLng(coordinate.getDouble("latitude"), coordinate.getDouble("longitude"))); - } - if (polyline != null) { - polyline.setPoints(this.coordinates); - } - } - - public void setColor(int color) { - this.color = color; - if (polyline != null) { - polyline.setColor(color); - } + private PolylineOptions polylineOptions; + private Polyline polyline; + + private List coordinates; + private int color; + private float width; + private boolean geodesic; + private float zIndex; + + public AirMapPolyline(Context context) { + super(context); + } + + public void setCoordinates(ReadableArray coordinates) { + this.coordinates = new ArrayList<>(coordinates.size()); + for (int i = 0; i < coordinates.size(); i++) { + ReadableMap coordinate = coordinates.getMap(i); + this.coordinates.add(i, + new LatLng(coordinate.getDouble("latitude"), coordinate.getDouble("longitude"))); } - - public void setWidth(float width) { - this.width = width; - if (polyline != null) { - polyline.setWidth(width); - } - } - - public void setZIndex(float zIndex) { - this.zIndex = zIndex; - if (polyline != null) { - polyline.setZIndex(zIndex); - } - } - - public void setGeodesic(boolean geodesic) { - this.geodesic = geodesic; - if (polyline != null) { - polyline.setGeodesic(geodesic); - } + if (polyline != null) { + polyline.setPoints(this.coordinates); } + } - public PolylineOptions getPolylineOptions() { - if (polylineOptions == null) { - polylineOptions = createPolylineOptions(); - } - return polylineOptions; + public void setColor(int color) { + this.color = color; + if (polyline != null) { + polyline.setColor(color); } + } - private PolylineOptions createPolylineOptions() { - PolylineOptions options = new PolylineOptions(); - options.addAll(coordinates); - options.color(color); - options.width(width); - options.geodesic(geodesic); - options.zIndex(zIndex); - return options; + public void setWidth(float width) { + this.width = width; + if (polyline != null) { + polyline.setWidth(width); } + } - @Override - public Object getFeature() { - return polyline; + public void setZIndex(float zIndex) { + this.zIndex = zIndex; + if (polyline != null) { + polyline.setZIndex(zIndex); } + } - @Override - public void addToMap(GoogleMap map) { - polyline = map.addPolyline(getPolylineOptions()); - polyline.setClickable(true); + public void setGeodesic(boolean geodesic) { + this.geodesic = geodesic; + if (polyline != null) { + polyline.setGeodesic(geodesic); } + } - @Override - public void removeFromMap(GoogleMap map) { - polyline.remove(); + public PolylineOptions getPolylineOptions() { + if (polylineOptions == null) { + polylineOptions = createPolylineOptions(); } + return polylineOptions; + } + + private PolylineOptions createPolylineOptions() { + PolylineOptions options = new PolylineOptions(); + options.addAll(coordinates); + options.color(color); + options.width(width); + options.geodesic(geodesic); + options.zIndex(zIndex); + return options; + } + + @Override + public Object getFeature() { + return polyline; + } + + @Override + public void addToMap(GoogleMap map) { + polyline = map.addPolyline(getPolylineOptions()); + polyline.setClickable(true); + } + + @Override + public void removeFromMap(GoogleMap map) { + polyline.remove(); + } } diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapPolylineManager.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapPolylineManager.java index c5afc61e0..be80acfbc 100644 --- a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapPolylineManager.java +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapPolylineManager.java @@ -13,66 +13,66 @@ import com.facebook.react.uimanager.ViewGroupManager; import com.facebook.react.uimanager.annotations.ReactProp; -import java.util.HashMap; import java.util.Map; + import javax.annotation.Nullable; public class AirMapPolylineManager extends ViewGroupManager { - private final DisplayMetrics metrics; + private final DisplayMetrics metrics; - public AirMapPolylineManager(ReactApplicationContext reactContext) { - super(); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { - metrics = new DisplayMetrics(); - ((WindowManager) reactContext.getSystemService(Context.WINDOW_SERVICE)) - .getDefaultDisplay() - .getRealMetrics(metrics); - } else { - metrics = reactContext.getResources().getDisplayMetrics(); - } + public AirMapPolylineManager(ReactApplicationContext reactContext) { + super(); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { + metrics = new DisplayMetrics(); + ((WindowManager) reactContext.getSystemService(Context.WINDOW_SERVICE)) + .getDefaultDisplay() + .getRealMetrics(metrics); + } else { + metrics = reactContext.getResources().getDisplayMetrics(); } + } - @Override - public String getName() { - return "AIRMapPolyline"; - } + @Override + public String getName() { + return "AIRMapPolyline"; + } - @Override - public AirMapPolyline createViewInstance(ThemedReactContext context) { - return new AirMapPolyline(context); - } + @Override + public AirMapPolyline createViewInstance(ThemedReactContext context) { + return new AirMapPolyline(context); + } - @ReactProp(name = "coordinates") - public void setCoordinate(AirMapPolyline view, ReadableArray coordinates) { - view.setCoordinates(coordinates); - } + @ReactProp(name = "coordinates") + public void setCoordinate(AirMapPolyline view, ReadableArray coordinates) { + view.setCoordinates(coordinates); + } - @ReactProp(name = "strokeWidth", defaultFloat = 1f) - public void setStrokeWidth(AirMapPolyline view, float widthInPoints) { - float widthInScreenPx = metrics.density * widthInPoints; // done for parity with iOS - view.setWidth(widthInScreenPx); - } + @ReactProp(name = "strokeWidth", defaultFloat = 1f) + public void setStrokeWidth(AirMapPolyline view, float widthInPoints) { + float widthInScreenPx = metrics.density * widthInPoints; // done for parity with iOS + view.setWidth(widthInScreenPx); + } - @ReactProp(name = "strokeColor", defaultInt = Color.RED, customType = "Color") - public void setStrokeColor(AirMapPolyline view, int color) { - view.setColor(color); - } + @ReactProp(name = "strokeColor", defaultInt = Color.RED, customType = "Color") + public void setStrokeColor(AirMapPolyline view, int color) { + view.setColor(color); + } - @ReactProp(name = "geodesic", defaultBoolean = false) - public void setGeodesic(AirMapPolyline view, boolean geodesic) { - view.setGeodesic(geodesic); - } + @ReactProp(name = "geodesic", defaultBoolean = false) + public void setGeodesic(AirMapPolyline view, boolean geodesic) { + view.setGeodesic(geodesic); + } - @ReactProp(name = "zIndex", defaultFloat = 1.0f) - public void setZIndex(AirMapPolyline view, float zIndex) { - view.setZIndex(zIndex); - } + @ReactProp(name = "zIndex", defaultFloat = 1.0f) + public void setZIndex(AirMapPolyline view, float zIndex) { + view.setZIndex(zIndex); + } - @Override - @Nullable - public Map getExportedCustomDirectEventTypeConstants() { - return MapBuilder.of( - "onPress", MapBuilder.of("registrationName", "onPress") - ); - } + @Override + @Nullable + public Map getExportedCustomDirectEventTypeConstants() { + return MapBuilder.of( + "onPress", MapBuilder.of("registrationName", "onPress") + ); + } } diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapUrlTile.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapUrlTile.java index 691c2fd3c..ae51a63b4 100644 --- a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapUrlTile.java +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapUrlTile.java @@ -12,89 +12,90 @@ public class AirMapUrlTile extends AirMapFeature { - class AIRMapUrlTileProvider extends UrlTileProvider - { - private String urlTemplate; - public AIRMapUrlTileProvider(int width, int height, String urlTemplate) { - super(width, height); - this.urlTemplate = urlTemplate; - } - @Override - public synchronized URL getTileUrl(int x, int y, int zoom) { - - String s = this.urlTemplate - .replace("{x}", Integer.toString(x)) - .replace("{y}", Integer.toString(y)) - .replace("{z}", Integer.toString(zoom)); - URL url = null; - try { - url = new URL(s); - } catch (MalformedURLException e) { - throw new AssertionError(e); - } - return url; - } - - public void setUrlTemplate(String urlTemplate) { - this.urlTemplate = urlTemplate; - } - } - - private TileOverlayOptions tileOverlayOptions; - private TileOverlay tileOverlay; - private AIRMapUrlTileProvider tileProvider; - + class AIRMapUrlTileProvider extends UrlTileProvider { private String urlTemplate; - private float zIndex; - public AirMapUrlTile(Context context) { - super(context); + public AIRMapUrlTileProvider(int width, int height, String urlTemplate) { + super(width, height); + this.urlTemplate = urlTemplate; } - public void setUrlTemplate(String urlTemplate) { - this.urlTemplate = urlTemplate; - if (tileProvider != null) { - tileProvider.setUrlTemplate(urlTemplate); - } - if (tileOverlay != null) { - tileOverlay.clearTileCache(); - } + @Override + public synchronized URL getTileUrl(int x, int y, int zoom) { + + String s = this.urlTemplate + .replace("{x}", Integer.toString(x)) + .replace("{y}", Integer.toString(y)) + .replace("{z}", Integer.toString(zoom)); + URL url = null; + try { + url = new URL(s); + } catch (MalformedURLException e) { + throw new AssertionError(e); + } + return url; } - public void setZIndex(float zIndex) { - this.zIndex = zIndex; - if (tileOverlay != null) { - tileOverlay.setZIndex(zIndex); - } + public void setUrlTemplate(String urlTemplate) { + this.urlTemplate = urlTemplate; } + } - public TileOverlayOptions getTileOverlayOptions() { - if (tileOverlayOptions == null) { - tileOverlayOptions = createTileOverlayOptions(); - } - return tileOverlayOptions; - } + private TileOverlayOptions tileOverlayOptions; + private TileOverlay tileOverlay; + private AIRMapUrlTileProvider tileProvider; - private TileOverlayOptions createTileOverlayOptions() { - TileOverlayOptions options = new TileOverlayOptions(); - options.zIndex(zIndex); - this.tileProvider = new AIRMapUrlTileProvider(256, 256, this.urlTemplate); - options.tileProvider(this.tileProvider); - return options; - } + private String urlTemplate; + private float zIndex; - @Override - public Object getFeature() { - return tileOverlay; + public AirMapUrlTile(Context context) { + super(context); + } + + public void setUrlTemplate(String urlTemplate) { + this.urlTemplate = urlTemplate; + if (tileProvider != null) { + tileProvider.setUrlTemplate(urlTemplate); } + if (tileOverlay != null) { + tileOverlay.clearTileCache(); + } + } - @Override - public void addToMap(GoogleMap map) { - this.tileOverlay = map.addTileOverlay(getTileOverlayOptions()); + public void setZIndex(float zIndex) { + this.zIndex = zIndex; + if (tileOverlay != null) { + tileOverlay.setZIndex(zIndex); } + } - @Override - public void removeFromMap(GoogleMap map) { - tileOverlay.remove(); + public TileOverlayOptions getTileOverlayOptions() { + if (tileOverlayOptions == null) { + tileOverlayOptions = createTileOverlayOptions(); } + return tileOverlayOptions; + } + + private TileOverlayOptions createTileOverlayOptions() { + TileOverlayOptions options = new TileOverlayOptions(); + options.zIndex(zIndex); + this.tileProvider = new AIRMapUrlTileProvider(256, 256, this.urlTemplate); + options.tileProvider(this.tileProvider); + return options; + } + + @Override + public Object getFeature() { + return tileOverlay; + } + + @Override + public void addToMap(GoogleMap map) { + this.tileOverlay = map.addTileOverlay(getTileOverlayOptions()); + } + + @Override + public void removeFromMap(GoogleMap map) { + tileOverlay.remove(); + } } diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapUrlTileManager.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapUrlTileManager.java index 7ea0726dc..68bf07342 100644 --- a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapUrlTileManager.java +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapUrlTileManager.java @@ -11,38 +11,38 @@ import com.facebook.react.uimanager.annotations.ReactProp; public class AirMapUrlTileManager extends ViewGroupManager { - private DisplayMetrics metrics; - - public AirMapUrlTileManager(ReactApplicationContext reactContext) { - super(); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { - metrics = new DisplayMetrics(); - ((WindowManager) reactContext.getSystemService(Context.WINDOW_SERVICE)) - .getDefaultDisplay() - .getRealMetrics(metrics); - } else { - metrics = reactContext.getResources().getDisplayMetrics(); - } - } - - @Override - public String getName() { - return "AIRMapUrlTile"; - } - - @Override - public AirMapUrlTile createViewInstance(ThemedReactContext context) { - return new AirMapUrlTile(context); - } - - @ReactProp(name = "urlTemplate") - public void setUrlTemplate(AirMapUrlTile view, String urlTemplate) { - view.setUrlTemplate(urlTemplate); - } - - @ReactProp(name = "zIndex", defaultFloat = -1.0f) - public void setZIndex(AirMapUrlTile view, float zIndex) { - view.setZIndex(zIndex); + private DisplayMetrics metrics; + + public AirMapUrlTileManager(ReactApplicationContext reactContext) { + super(); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { + metrics = new DisplayMetrics(); + ((WindowManager) reactContext.getSystemService(Context.WINDOW_SERVICE)) + .getDefaultDisplay() + .getRealMetrics(metrics); + } else { + metrics = reactContext.getResources().getDisplayMetrics(); } + } + + @Override + public String getName() { + return "AIRMapUrlTile"; + } + + @Override + public AirMapUrlTile createViewInstance(ThemedReactContext context) { + return new AirMapUrlTile(context); + } + + @ReactProp(name = "urlTemplate") + public void setUrlTemplate(AirMapUrlTile view, String urlTemplate) { + view.setUrlTemplate(urlTemplate); + } + + @ReactProp(name = "zIndex", defaultFloat = -1.0f) + public void setZIndex(AirMapUrlTile view, float zIndex) { + view.setZIndex(zIndex); + } } diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java index 725270ac6..11e578634 100644 --- a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java @@ -1,6 +1,5 @@ package com.airbnb.android.react.maps; -import android.app.Activity; import android.content.Context; import android.content.pm.PackageManager; import android.content.res.ColorStateList; @@ -54,801 +53,807 @@ import static android.support.v4.content.PermissionChecker.checkSelfPermission; public class AirMapView extends MapView implements GoogleMap.InfoWindowAdapter, - GoogleMap.OnMarkerDragListener, OnMapReadyCallback { - public GoogleMap map; - private ProgressBar mapLoadingProgressBar; - private RelativeLayout mapLoadingLayout; - private ImageView cacheImageView; - private Boolean isMapLoaded = false; - private Integer loadingBackgroundColor = null; - private Integer loadingIndicatorColor = null; - private final int baseMapPadding = 50; - - private LatLngBounds boundsToMove; - private boolean showUserLocation = false; - private boolean isMonitoringRegion = false; - private boolean isTouchDown = false; - private boolean handlePanDrag = false; - private boolean moveOnMarkerPress = true; - private boolean cacheEnabled = false; - - private static final String[] PERMISSIONS = new String[] { - "android.permission.ACCESS_FINE_LOCATION", "android.permission.ACCESS_COARSE_LOCATION"}; - - private final List features = new ArrayList<>(); - private final Map markerMap = new HashMap<>(); - private final Map polylineMap = new HashMap<>(); - private final Map polygonMap = new HashMap<>(); - private final ScaleGestureDetector scaleDetector; - private final GestureDetectorCompat gestureDetector; - private final AirMapManager manager; - private LifecycleEventListener lifecycleListener; - private boolean paused = false; - private boolean destroyed = false; - private final ThemedReactContext context; - private final EventDispatcher eventDispatcher; - - private static boolean contextHasBug(Context context) { - return context == null || - context.getResources() == null || - context.getResources().getConfiguration() == null; - } - - // We do this to fix this bug: - // https://github.com/airbnb/react-native-maps/issues/271 - // - // which conflicts with another bug regarding the passed in context: - // https://github.com/airbnb/react-native-maps/issues/1147 - // - // Doing this allows us to avoid both bugs. - private static Context getNonBuggyContext(ThemedReactContext reactContext, - ReactApplicationContext appContext) { - Context superContext = reactContext; - if (!contextHasBug(appContext.getCurrentActivity())) { - superContext = appContext.getCurrentActivity(); - } else if (contextHasBug(superContext)) { - // we have the bug! let's try to find a better context to use - if (!contextHasBug(reactContext.getCurrentActivity())) { - superContext = reactContext.getCurrentActivity(); - } else if (!contextHasBug(reactContext.getApplicationContext())) { - superContext = reactContext.getApplicationContext(); - } else { - // ¯\_(ツ)_/¯ - } - } - return superContext; - } - - public AirMapView(ThemedReactContext reactContext, ReactApplicationContext appContext, AirMapManager manager, - GoogleMapOptions googleMapOptions) { - super(getNonBuggyContext(reactContext, appContext), googleMapOptions); - - this.manager = manager; - this.context = reactContext; - - super.onCreate(null); - // TODO(lmr): what about onStart???? - super.onResume(); - super.getMapAsync(this); - - final AirMapView view = this; - scaleDetector = - new ScaleGestureDetector(reactContext, new ScaleGestureDetector.SimpleOnScaleGestureListener() { - @Override - public boolean onScaleBegin(ScaleGestureDetector detector) { - view.startMonitoringRegion(); - return true; // stop recording this gesture. let mapview handle it. - } - }); - - gestureDetector = - new GestureDetectorCompat(reactContext, new GestureDetector.SimpleOnGestureListener() { - @Override - public boolean onDoubleTap(MotionEvent e) { - view.startMonitoringRegion(); - return false; - } - - @Override - public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, - float distanceY) { - if (handlePanDrag) { - onPanDrag(e2); - } - view.startMonitoringRegion(); - return false; - } - }); - - this.addOnLayoutChangeListener(new OnLayoutChangeListener() { - @Override public void onLayoutChange(View v, int left, int top, int right, int bottom, - int oldLeft, int oldTop, int oldRight, int oldBottom) { - if (!paused) { - AirMapView.this.cacheView(); - } - } - }); - - eventDispatcher = reactContext.getNativeModule(UIManagerModule.class).getEventDispatcher(); - } - - @Override - public void onMapReady(final GoogleMap map) { - if (destroyed) { - return; - } - this.map = map; - this.map.setInfoWindowAdapter(this); - this.map.setOnMarkerDragListener(this); - - manager.pushEvent(context, this, "onMapReady", new WritableNativeMap()); - - final AirMapView view = this; - - map.setOnMarkerClickListener(new GoogleMap.OnMarkerClickListener() { - @Override - public boolean onMarkerClick(Marker marker) { - WritableMap event; - AirMapMarker airMapMarker = markerMap.get(marker); - - event = makeClickEventData(marker.getPosition()); - event.putString("action", "marker-press"); - event.putString("id", airMapMarker.getIdentifier()); - manager.pushEvent(context, view, "onMarkerPress", event); - - event = makeClickEventData(marker.getPosition()); - event.putString("action", "marker-press"); - event.putString("id", airMapMarker.getIdentifier()); - manager.pushEvent(context, markerMap.get(marker), "onPress", event); - - // Return false to open the callout info window and center on the marker - // https://developers.google.com/android/reference/com/google/android/gms/maps/GoogleMap.OnMarkerClickListener - if (view.moveOnMarkerPress) { - return false; - } else { - marker.showInfoWindow(); - return true; - } - } - }); - - map.setOnPolygonClickListener(new GoogleMap.OnPolygonClickListener() { - @Override - public void onPolygonClick(Polygon polygon) { - WritableMap event = makeClickEventData(polygon.getPoints().get(0)); - event.putString("action", "polygon-press"); - manager.pushEvent(context, polygonMap.get(polygon), "onPress", event); - } - }); - - map.setOnPolylineClickListener(new GoogleMap.OnPolylineClickListener() { - @Override - public void onPolylineClick(Polyline polyline) { - WritableMap event = makeClickEventData(polyline.getPoints().get(0)); - event.putString("action", "polyline-press"); - manager.pushEvent(context, polylineMap.get(polyline), "onPress", event); - } - }); - - map.setOnInfoWindowClickListener(new GoogleMap.OnInfoWindowClickListener() { - @Override - public void onInfoWindowClick(Marker marker) { - WritableMap event; - - event = makeClickEventData(marker.getPosition()); - event.putString("action", "callout-press"); - manager.pushEvent(context, view, "onCalloutPress", event); - - event = makeClickEventData(marker.getPosition()); - event.putString("action", "callout-press"); - AirMapMarker markerView = markerMap.get(marker); - manager.pushEvent(context, markerView, "onCalloutPress", event); - - event = makeClickEventData(marker.getPosition()); - event.putString("action", "callout-press"); - AirMapCallout infoWindow = markerView.getCalloutView(); - if (infoWindow != null) manager.pushEvent(context, infoWindow, "onPress", event); - } - }); - - map.setOnMapClickListener(new GoogleMap.OnMapClickListener() { - @Override - public void onMapClick(LatLng point) { - WritableMap event = makeClickEventData(point); - event.putString("action", "press"); - manager.pushEvent(context, view, "onPress", event); - } - }); - - map.setOnMapLongClickListener(new GoogleMap.OnMapLongClickListener() { - @Override - public void onMapLongClick(LatLng point) { - WritableMap event = makeClickEventData(point); - event.putString("action", "long-press"); - manager.pushEvent(context, view, "onLongPress", makeClickEventData(point)); - } - }); - - map.setOnCameraChangeListener(new GoogleMap.OnCameraChangeListener() { - @Override - public void onCameraChange(CameraPosition position) { - LatLngBounds bounds = map.getProjection().getVisibleRegion().latLngBounds; - LatLng center = position.target; - lastBoundsEmitted = bounds; - eventDispatcher.dispatchEvent(new RegionChangeEvent(getId(), bounds, center, isTouchDown)); - view.stopMonitoringRegion(); - } - }); - - map.setOnMapLoadedCallback(new GoogleMap.OnMapLoadedCallback() { - @Override public void onMapLoaded() { - isMapLoaded = true; - AirMapView.this.cacheView(); - } - }); - - // We need to be sure to disable location-tracking when app enters background, in-case some - // other module - // has acquired a wake-lock and is controlling location-updates, otherwise, location-manager - // will be left - // updating location constantly, killing the battery, even though some other location-mgmt - // module may - // desire to shut-down location-services. - lifecycleListener = new LifecycleEventListener() { - @Override - public void onHostResume() { - if (hasPermissions()) { - //noinspection MissingPermission - map.setMyLocationEnabled(showUserLocation); - } - synchronized (AirMapView.this) { - AirMapView.this.onResume(); - paused = false; + GoogleMap.OnMarkerDragListener, OnMapReadyCallback { + public GoogleMap map; + private ProgressBar mapLoadingProgressBar; + private RelativeLayout mapLoadingLayout; + private ImageView cacheImageView; + private Boolean isMapLoaded = false; + private Integer loadingBackgroundColor = null; + private Integer loadingIndicatorColor = null; + private final int baseMapPadding = 50; + + private LatLngBounds boundsToMove; + private boolean showUserLocation = false; + private boolean isMonitoringRegion = false; + private boolean isTouchDown = false; + private boolean handlePanDrag = false; + private boolean moveOnMarkerPress = true; + private boolean cacheEnabled = false; + + private static final String[] PERMISSIONS = new String[]{ + "android.permission.ACCESS_FINE_LOCATION", "android.permission.ACCESS_COARSE_LOCATION"}; + + private final List features = new ArrayList<>(); + private final Map markerMap = new HashMap<>(); + private final Map polylineMap = new HashMap<>(); + private final Map polygonMap = new HashMap<>(); + private final ScaleGestureDetector scaleDetector; + private final GestureDetectorCompat gestureDetector; + private final AirMapManager manager; + private LifecycleEventListener lifecycleListener; + private boolean paused = false; + private boolean destroyed = false; + private final ThemedReactContext context; + private final EventDispatcher eventDispatcher; + + private static boolean contextHasBug(Context context) { + return context == null || + context.getResources() == null || + context.getResources().getConfiguration() == null; + } + + // We do this to fix this bug: + // https://github.com/airbnb/react-native-maps/issues/271 + // + // which conflicts with another bug regarding the passed in context: + // https://github.com/airbnb/react-native-maps/issues/1147 + // + // Doing this allows us to avoid both bugs. + private static Context getNonBuggyContext(ThemedReactContext reactContext, + ReactApplicationContext appContext) { + Context superContext = reactContext; + if (!contextHasBug(appContext.getCurrentActivity())) { + superContext = appContext.getCurrentActivity(); + } else if (contextHasBug(superContext)) { + // we have the bug! let's try to find a better context to use + if (!contextHasBug(reactContext.getCurrentActivity())) { + superContext = reactContext.getCurrentActivity(); + } else if (!contextHasBug(reactContext.getApplicationContext())) { + superContext = reactContext.getApplicationContext(); + } else { + // ¯\_(ツ)_/¯ + } + } + return superContext; + } + + public AirMapView(ThemedReactContext reactContext, ReactApplicationContext appContext, + AirMapManager manager, + GoogleMapOptions googleMapOptions) { + super(getNonBuggyContext(reactContext, appContext), googleMapOptions); + + this.manager = manager; + this.context = reactContext; + + super.onCreate(null); + // TODO(lmr): what about onStart???? + super.onResume(); + super.getMapAsync(this); + + final AirMapView view = this; + scaleDetector = + new ScaleGestureDetector(reactContext, + new ScaleGestureDetector.SimpleOnScaleGestureListener() { + @Override + public boolean onScaleBegin(ScaleGestureDetector detector) { + view.startMonitoringRegion(); + return true; // stop recording this gesture. let mapview handle it. + } + }); + + gestureDetector = + new GestureDetectorCompat(reactContext, new GestureDetector.SimpleOnGestureListener() { + @Override + public boolean onDoubleTap(MotionEvent e) { + view.startMonitoringRegion(); + return false; } - } - @Override - public void onHostPause() { - if (hasPermissions()) { - //noinspection MissingPermission - map.setMyLocationEnabled(false); - } - synchronized (AirMapView.this) { - if(!destroyed) { - AirMapView.this.onPause(); - } - paused = true; + @Override + public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, + float distanceY) { + if (handlePanDrag) { + onPanDrag(e2); } - } - - @Override - public void onHostDestroy() { - AirMapView.this.doDestroy(); - } - }; - - context.addLifecycleEventListener(lifecycleListener); - } - - private boolean hasPermissions() { - return checkSelfPermission(getContext(), PERMISSIONS[0]) == PackageManager.PERMISSION_GRANTED || - checkSelfPermission(getContext(), PERMISSIONS[1]) == PackageManager.PERMISSION_GRANTED; - } - - - - /* - onDestroy is final method so I can't override it. - */ - public synchronized void doDestroy() { - if (destroyed) { - return; - } - destroyed = true; + view.startMonitoringRegion(); + return false; + } + }); - if (lifecycleListener != null && context != null) { - context.removeLifecycleEventListener(lifecycleListener); - lifecycleListener = null; - } + this.addOnLayoutChangeListener(new OnLayoutChangeListener() { + @Override public void onLayoutChange(View v, int left, int top, int right, int bottom, + int oldLeft, int oldTop, int oldRight, int oldBottom) { if (!paused) { - onPause(); - paused = true; - } - onDestroy(); - } - - public void setRegion(ReadableMap region) { - if (region == null) return; - - Double lng = region.getDouble("longitude"); - Double lat = region.getDouble("latitude"); - Double lngDelta = region.getDouble("longitudeDelta"); - Double latDelta = region.getDouble("latitudeDelta"); - LatLngBounds bounds = new LatLngBounds( - new LatLng(lat - latDelta / 2, lng - lngDelta / 2), // southwest - new LatLng(lat + latDelta / 2, lng + lngDelta / 2) // northeast - ); - if (super.getHeight() <= 0 || super.getWidth() <= 0) { - // in this case, our map has not been laid out yet, so we save the bounds in a local - // variable, and make a guess of zoomLevel 10. Not to worry, though: as soon as layout - // occurs, we will move the camera to the saved bounds. Note that if we tried to move - // to the bounds now, it would trigger an exception. - map.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(lat, lng), 10)); - boundsToMove = bounds; - } else { - map.moveCamera(CameraUpdateFactory.newLatLngBounds(bounds, 0)); - boundsToMove = null; - } - } - - public void setShowsUserLocation(boolean showUserLocation) { - this.showUserLocation = showUserLocation; // hold onto this for lifecycle handling - if (hasPermissions()) { - //noinspection MissingPermission - map.setMyLocationEnabled(showUserLocation); - } - } - - public void setShowsMyLocationButton(boolean showMyLocationButton) { - if (hasPermissions()) { - map.getUiSettings().setMyLocationButtonEnabled(showMyLocationButton); - } - } - - public void setToolbarEnabled(boolean toolbarEnabled) { - if (hasPermissions()) { - map.getUiSettings().setMapToolbarEnabled(toolbarEnabled); - } - } - - public void setCacheEnabled(boolean cacheEnabled) { - this.cacheEnabled = cacheEnabled; - this.cacheView(); - } - - public void enableMapLoading(boolean loadingEnabled) { - if (loadingEnabled && !this.isMapLoaded) { - this.getMapLoadingLayoutView().setVisibility(View.VISIBLE); - } - } - - public void setMoveOnMarkerPress(boolean moveOnPress) { - this.moveOnMarkerPress = moveOnPress; - } - - public void setLoadingBackgroundColor(Integer loadingBackgroundColor) { - this.loadingBackgroundColor = loadingBackgroundColor; - - if (this.mapLoadingLayout != null) { - if (loadingBackgroundColor == null) { - this.mapLoadingLayout.setBackgroundColor(Color.WHITE); - } else { - this.mapLoadingLayout.setBackgroundColor(this.loadingBackgroundColor); - } - } - } - - public void setLoadingIndicatorColor(Integer loadingIndicatorColor) { - this.loadingIndicatorColor = loadingIndicatorColor; - if (this.mapLoadingProgressBar != null) { - Integer color = loadingIndicatorColor; - if (color == null) { - color = Color.parseColor("#606060"); - } - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - ColorStateList progressTintList = ColorStateList.valueOf(loadingIndicatorColor); - ColorStateList secondaryProgressTintList = ColorStateList.valueOf(loadingIndicatorColor); - ColorStateList indeterminateTintList = ColorStateList.valueOf(loadingIndicatorColor); - - this.mapLoadingProgressBar.setProgressTintList(progressTintList); - this.mapLoadingProgressBar.setSecondaryProgressTintList(secondaryProgressTintList); - this.mapLoadingProgressBar.setIndeterminateTintList(indeterminateTintList); - } else { - PorterDuff.Mode mode = PorterDuff.Mode.SRC_IN; - if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.GINGERBREAD_MR1) { - mode = PorterDuff.Mode.MULTIPLY; - } - if (this.mapLoadingProgressBar.getIndeterminateDrawable() != null) - this.mapLoadingProgressBar.getIndeterminateDrawable().setColorFilter(color, mode); - if (this.mapLoadingProgressBar.getProgressDrawable() != null) - this.mapLoadingProgressBar.getProgressDrawable().setColorFilter(color, mode); - } - } - } - - public void setHandlePanDrag(boolean handlePanDrag) { - this.handlePanDrag = handlePanDrag; - } - - public void addFeature(View child, int index) { - // Our desired API is to pass up annotations/overlays as children to the mapview component. - // This is where we intercept them and do the appropriate underlying mapview action. - if (child instanceof AirMapMarker) { - AirMapMarker annotation = (AirMapMarker) child; - annotation.addToMap(map); - features.add(index, annotation); - Marker marker = (Marker) annotation.getFeature(); - markerMap.put(marker, annotation); - } else if (child instanceof AirMapPolyline) { - AirMapPolyline polylineView = (AirMapPolyline) child; - polylineView.addToMap(map); - features.add(index, polylineView); - Polyline polyline = (Polyline) polylineView.getFeature(); - polylineMap.put(polyline, polylineView); - } else if (child instanceof AirMapPolygon) { - AirMapPolygon polygonView = (AirMapPolygon) child; - polygonView.addToMap(map); - features.add(index, polygonView); - Polygon polygon = (Polygon) polygonView.getFeature(); - polygonMap.put(polygon, polygonView); - } else if (child instanceof AirMapCircle) { - AirMapCircle circleView = (AirMapCircle) child; - circleView.addToMap(map); - features.add(index, circleView); - } else if (child instanceof AirMapUrlTile) { - AirMapUrlTile urlTileView = (AirMapUrlTile) child; - urlTileView.addToMap(map); - features.add(index, urlTileView); - } else { - ViewGroup children = (ViewGroup) child; - for (int i = 0; i < children.getChildCount(); i++) { - addFeature(children.getChildAt(i), index); - } - } - } - - public int getFeatureCount() { - return features.size(); - } - - public View getFeatureAt(int index) { - return features.get(index); - } - - public void removeFeatureAt(int index) { - AirMapFeature feature = features.remove(index); - if (feature instanceof AirMapMarker) { - markerMap.remove(feature.getFeature()); + AirMapView.this.cacheView(); } - feature.removeFromMap(map); - } - - public WritableMap makeClickEventData(LatLng point) { - WritableMap event = new WritableNativeMap(); - - WritableMap coordinate = new WritableNativeMap(); - coordinate.putDouble("latitude", point.latitude); - coordinate.putDouble("longitude", point.longitude); - event.putMap("coordinate", coordinate); - - Projection projection = map.getProjection(); - Point screenPoint = projection.toScreenLocation(point); - - WritableMap position = new WritableNativeMap(); - position.putDouble("x", screenPoint.x); - position.putDouble("y", screenPoint.y); - event.putMap("position", position); - - return event; - } - - public void updateExtraData(Object extraData) { - // if boundsToMove is not null, we now have the MapView's width/height, so we can apply - // a proper camera move - if (boundsToMove != null) { - HashMap data = (HashMap) extraData; - float width = data.get("width"); - float height = data.get("height"); - map.moveCamera( - CameraUpdateFactory.newLatLngBounds( - boundsToMove, - (int) width, - (int) height, - 0 - ) - ); - boundsToMove = null; - } - } - - public void animateToRegion(LatLngBounds bounds, int duration) { - if (map != null) { - startMonitoringRegion(); - map.animateCamera(CameraUpdateFactory.newLatLngBounds(bounds, 0), duration, null); - } - } - - public void animateToCoordinate(LatLng coordinate, int duration) { - if (map != null) { - startMonitoringRegion(); - map.animateCamera(CameraUpdateFactory.newLatLng(coordinate), duration, null); - } - } - - public void fitToElements(boolean animated) { - LatLngBounds.Builder builder = new LatLngBounds.Builder(); + } + }); - boolean addedPosition = false; + eventDispatcher = reactContext.getNativeModule(UIManagerModule.class).getEventDispatcher(); + } - for (AirMapFeature feature : features) { - if (feature instanceof AirMapMarker) { - Marker marker = (Marker) feature.getFeature(); - builder.include(marker.getPosition()); - addedPosition = true; - } - // TODO(lmr): may want to include shapes / etc. - } - if (addedPosition) { - LatLngBounds bounds = builder.build(); - CameraUpdate cu = CameraUpdateFactory.newLatLngBounds(bounds, baseMapPadding); - if (animated) { - startMonitoringRegion(); - map.animateCamera(cu); - } else { - map.moveCamera(cu); - } - } + @Override + public void onMapReady(final GoogleMap map) { + if (destroyed) { + return; } + this.map = map; + this.map.setInfoWindowAdapter(this); + this.map.setOnMarkerDragListener(this); - public void fitToSuppliedMarkers(ReadableArray markerIDsArray, boolean animated) { - LatLngBounds.Builder builder = new LatLngBounds.Builder(); - - String[] markerIDs = new String[markerIDsArray.size()]; - for (int i = 0; i < markerIDsArray.size(); i++) { - markerIDs[i] = markerIDsArray.getString(i); - } - - boolean addedPosition = false; + manager.pushEvent(context, this, "onMapReady", new WritableNativeMap()); - List markerIDList = Arrays.asList(markerIDs); + final AirMapView view = this; - for (AirMapFeature feature : features) { - if (feature instanceof AirMapMarker) { - String identifier = ((AirMapMarker)feature).getIdentifier(); - Marker marker = (Marker)feature.getFeature(); - if (markerIDList.contains(identifier)) { - builder.include(marker.getPosition()); - addedPosition = true; - } - } - } - - if (addedPosition) { - LatLngBounds bounds = builder.build(); - CameraUpdate cu = CameraUpdateFactory.newLatLngBounds(bounds, baseMapPadding); - if (animated) { - startMonitoringRegion(); - map.animateCamera(cu); - } else { - map.moveCamera(cu); - } - } - } + map.setOnMarkerClickListener(new GoogleMap.OnMarkerClickListener() { + @Override + public boolean onMarkerClick(Marker marker) { + WritableMap event; + AirMapMarker airMapMarker = markerMap.get(marker); - public void fitToCoordinates(ReadableArray coordinatesArray, ReadableMap edgePadding, boolean animated) { - LatLngBounds.Builder builder = new LatLngBounds.Builder(); - - for (int i = 0; i < coordinatesArray.size(); i++) { - ReadableMap latLng = coordinatesArray.getMap(i); - Double lat = latLng.getDouble("latitude"); - Double lng = latLng.getDouble("longitude"); - builder.include(new LatLng(lat, lng)); - } - - LatLngBounds bounds = builder.build(); - CameraUpdate cu = CameraUpdateFactory.newLatLngBounds(bounds, baseMapPadding); - - if (edgePadding != null) { - map.setPadding(edgePadding.getInt("left"), edgePadding.getInt("top"), edgePadding.getInt("right"), edgePadding.getInt("bottom")); - } + event = makeClickEventData(marker.getPosition()); + event.putString("action", "marker-press"); + event.putString("id", airMapMarker.getIdentifier()); + manager.pushEvent(context, view, "onMarkerPress", event); - if (animated) { - startMonitoringRegion(); - map.animateCamera(cu); + event = makeClickEventData(marker.getPosition()); + event.putString("action", "marker-press"); + event.putString("id", airMapMarker.getIdentifier()); + manager.pushEvent(context, markerMap.get(marker), "onPress", event); + + // Return false to open the callout info window and center on the marker + // https://developers.google.com/android/reference/com/google/android/gms/maps/GoogleMap + // .OnMarkerClickListener + if (view.moveOnMarkerPress) { + return false; } else { - map.moveCamera(cu); - } - map.setPadding(0, 0, 0, 0); // Without this, the Google logo is moved up by the value of edgePadding.bottom - } - - // InfoWindowAdapter interface - - @Override - public View getInfoWindow(Marker marker) { - AirMapMarker markerView = markerMap.get(marker); - return markerView.getCallout(); - } - - @Override - public View getInfoContents(Marker marker) { - AirMapMarker markerView = markerMap.get(marker); - return markerView.getInfoContents(); - } - - @Override - public boolean dispatchTouchEvent(MotionEvent ev) { - scaleDetector.onTouchEvent(ev); - gestureDetector.onTouchEvent(ev); - - int action = MotionEventCompat.getActionMasked(ev); - - switch (action) { - case (MotionEvent.ACTION_DOWN): - this.getParent().requestDisallowInterceptTouchEvent( - map != null && map.getUiSettings().isScrollGesturesEnabled()); - isTouchDown = true; - break; - case (MotionEvent.ACTION_MOVE): - startMonitoringRegion(); - break; - case (MotionEvent.ACTION_UP): - // Clear this regardless, since isScrollGesturesEnabled() may have been updated - this.getParent().requestDisallowInterceptTouchEvent(false); - isTouchDown = false; - break; - } - super.dispatchTouchEvent(ev); - return true; - } - - // Timer Implementation - - public void startMonitoringRegion() { - if (isMonitoringRegion) return; - timerHandler.postDelayed(timerRunnable, 100); - isMonitoringRegion = true; - } + marker.showInfoWindow(); + return true; + } + } + }); + + map.setOnPolygonClickListener(new GoogleMap.OnPolygonClickListener() { + @Override + public void onPolygonClick(Polygon polygon) { + WritableMap event = makeClickEventData(polygon.getPoints().get(0)); + event.putString("action", "polygon-press"); + manager.pushEvent(context, polygonMap.get(polygon), "onPress", event); + } + }); + + map.setOnPolylineClickListener(new GoogleMap.OnPolylineClickListener() { + @Override + public void onPolylineClick(Polyline polyline) { + WritableMap event = makeClickEventData(polyline.getPoints().get(0)); + event.putString("action", "polyline-press"); + manager.pushEvent(context, polylineMap.get(polyline), "onPress", event); + } + }); + + map.setOnInfoWindowClickListener(new GoogleMap.OnInfoWindowClickListener() { + @Override + public void onInfoWindowClick(Marker marker) { + WritableMap event; - public void stopMonitoringRegion() { - if (!isMonitoringRegion) return; - timerHandler.removeCallbacks(timerRunnable); - isMonitoringRegion = false; - } - - private LatLngBounds lastBoundsEmitted; - - Handler timerHandler = new Handler(); - Runnable timerRunnable = new Runnable() { - - @Override - public void run() { - - Projection projection = map.getProjection(); - VisibleRegion region = (projection != null) ? projection.getVisibleRegion() : null; - LatLngBounds bounds = (region != null) ? region.latLngBounds : null; - - if ((bounds != null) && - (lastBoundsEmitted == null || LatLngBoundsUtils.BoundsAreDifferent(bounds, lastBoundsEmitted))) { - LatLng center = map.getCameraPosition().target; - lastBoundsEmitted = bounds; - eventDispatcher.dispatchEvent(new RegionChangeEvent(getId(), bounds, center, true)); - } - - timerHandler.postDelayed(this, 100); - } - }; - - @Override - public void onMarkerDragStart(Marker marker) { - WritableMap event = makeClickEventData(marker.getPosition()); - manager.pushEvent(context, this, "onMarkerDragStart", event); - - AirMapMarker markerView = markerMap.get(marker); event = makeClickEventData(marker.getPosition()); - manager.pushEvent(context, markerView, "onDragStart", event); - } - - @Override - public void onMarkerDrag(Marker marker) { - WritableMap event = makeClickEventData(marker.getPosition()); - manager.pushEvent(context, this, "onMarkerDrag", event); + event.putString("action", "callout-press"); + manager.pushEvent(context, view, "onCalloutPress", event); - AirMapMarker markerView = markerMap.get(marker); event = makeClickEventData(marker.getPosition()); - manager.pushEvent(context, markerView, "onDrag", event); - } - - @Override - public void onMarkerDragEnd(Marker marker) { - WritableMap event = makeClickEventData(marker.getPosition()); - manager.pushEvent(context, this, "onMarkerDragEnd", event); - + event.putString("action", "callout-press"); AirMapMarker markerView = markerMap.get(marker); - event = makeClickEventData(marker.getPosition()); - manager.pushEvent(context, markerView, "onDragEnd", event); - } + manager.pushEvent(context, markerView, "onCalloutPress", event); - private ProgressBar getMapLoadingProgressBar() { - if (this.mapLoadingProgressBar == null) { - this.mapLoadingProgressBar = new ProgressBar(getContext()); - this.mapLoadingProgressBar.setIndeterminate(true); + event = makeClickEventData(marker.getPosition()); + event.putString("action", "callout-press"); + AirMapCallout infoWindow = markerView.getCalloutView(); + if (infoWindow != null) manager.pushEvent(context, infoWindow, "onPress", event); + } + }); + + map.setOnMapClickListener(new GoogleMap.OnMapClickListener() { + @Override + public void onMapClick(LatLng point) { + WritableMap event = makeClickEventData(point); + event.putString("action", "press"); + manager.pushEvent(context, view, "onPress", event); + } + }); + + map.setOnMapLongClickListener(new GoogleMap.OnMapLongClickListener() { + @Override + public void onMapLongClick(LatLng point) { + WritableMap event = makeClickEventData(point); + event.putString("action", "long-press"); + manager.pushEvent(context, view, "onLongPress", makeClickEventData(point)); + } + }); + + map.setOnCameraChangeListener(new GoogleMap.OnCameraChangeListener() { + @Override + public void onCameraChange(CameraPosition position) { + LatLngBounds bounds = map.getProjection().getVisibleRegion().latLngBounds; + LatLng center = position.target; + lastBoundsEmitted = bounds; + eventDispatcher.dispatchEvent(new RegionChangeEvent(getId(), bounds, center, isTouchDown)); + view.stopMonitoringRegion(); + } + }); + + map.setOnMapLoadedCallback(new GoogleMap.OnMapLoadedCallback() { + @Override public void onMapLoaded() { + isMapLoaded = true; + AirMapView.this.cacheView(); + } + }); + + // We need to be sure to disable location-tracking when app enters background, in-case some + // other module + // has acquired a wake-lock and is controlling location-updates, otherwise, location-manager + // will be left + // updating location constantly, killing the battery, even though some other location-mgmt + // module may + // desire to shut-down location-services. + lifecycleListener = new LifecycleEventListener() { + @Override + public void onHostResume() { + if (hasPermissions()) { + //noinspection MissingPermission + map.setMyLocationEnabled(showUserLocation); } - if (this.loadingIndicatorColor != null) { - this.setLoadingIndicatorColor(this.loadingIndicatorColor); + synchronized (AirMapView.this) { + AirMapView.this.onResume(); + paused = false; } - return this.mapLoadingProgressBar; - } - - private RelativeLayout getMapLoadingLayoutView() { - if (this.mapLoadingLayout == null) { - this.mapLoadingLayout = new RelativeLayout(getContext()); - this.mapLoadingLayout.setBackgroundColor(Color.LTGRAY); - this.addView(this.mapLoadingLayout, - new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, - ViewGroup.LayoutParams.MATCH_PARENT)); + } - RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams( - RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT); - params.addRule(RelativeLayout.CENTER_IN_PARENT); - this.mapLoadingLayout.addView(this.getMapLoadingProgressBar(), params); - - this.mapLoadingLayout.setVisibility(View.INVISIBLE); + @Override + public void onHostPause() { + if (hasPermissions()) { + //noinspection MissingPermission + map.setMyLocationEnabled(false); } - this.setLoadingBackgroundColor(this.loadingBackgroundColor); - return this.mapLoadingLayout; - } - - private ImageView getCacheImageView() { - if (this.cacheImageView == null) { - this.cacheImageView = new ImageView(getContext()); - this.addView(this.cacheImageView, - new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); - this.cacheImageView.setVisibility(View.INVISIBLE); + synchronized (AirMapView.this) { + if (!destroyed) { + AirMapView.this.onPause(); + } + paused = true; } - return this.cacheImageView; - } + } - private void removeCacheImageView() { - if (this.cacheImageView != null) { - ((ViewGroup)this.cacheImageView.getParent()).removeView(this.cacheImageView); - this.cacheImageView = null; - } - } + @Override + public void onHostDestroy() { + AirMapView.this.doDestroy(); + } + }; - private void removeMapLoadingProgressBar() { - if (this.mapLoadingProgressBar != null) { - ((ViewGroup)this.mapLoadingProgressBar.getParent()).removeView(this.mapLoadingProgressBar); - this.mapLoadingProgressBar = null; - } - } + context.addLifecycleEventListener(lifecycleListener); + } + + private boolean hasPermissions() { + return checkSelfPermission(getContext(), PERMISSIONS[0]) == PackageManager.PERMISSION_GRANTED || + checkSelfPermission(getContext(), PERMISSIONS[1]) == PackageManager.PERMISSION_GRANTED; + } + + + /* + onDestroy is final method so I can't override it. + */ + public synchronized void doDestroy() { + if (destroyed) { + return; + } + destroyed = true; + + if (lifecycleListener != null && context != null) { + context.removeLifecycleEventListener(lifecycleListener); + lifecycleListener = null; + } + if (!paused) { + onPause(); + paused = true; + } + onDestroy(); + } + + public void setRegion(ReadableMap region) { + if (region == null) return; + + Double lng = region.getDouble("longitude"); + Double lat = region.getDouble("latitude"); + Double lngDelta = region.getDouble("longitudeDelta"); + Double latDelta = region.getDouble("latitudeDelta"); + LatLngBounds bounds = new LatLngBounds( + new LatLng(lat - latDelta / 2, lng - lngDelta / 2), // southwest + new LatLng(lat + latDelta / 2, lng + lngDelta / 2) // northeast + ); + if (super.getHeight() <= 0 || super.getWidth() <= 0) { + // in this case, our map has not been laid out yet, so we save the bounds in a local + // variable, and make a guess of zoomLevel 10. Not to worry, though: as soon as layout + // occurs, we will move the camera to the saved bounds. Note that if we tried to move + // to the bounds now, it would trigger an exception. + map.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(lat, lng), 10)); + boundsToMove = bounds; + } else { + map.moveCamera(CameraUpdateFactory.newLatLngBounds(bounds, 0)); + boundsToMove = null; + } + } + + public void setShowsUserLocation(boolean showUserLocation) { + this.showUserLocation = showUserLocation; // hold onto this for lifecycle handling + if (hasPermissions()) { + //noinspection MissingPermission + map.setMyLocationEnabled(showUserLocation); + } + } + + public void setShowsMyLocationButton(boolean showMyLocationButton) { + if (hasPermissions()) { + map.getUiSettings().setMyLocationButtonEnabled(showMyLocationButton); + } + } + + public void setToolbarEnabled(boolean toolbarEnabled) { + if (hasPermissions()) { + map.getUiSettings().setMapToolbarEnabled(toolbarEnabled); + } + } + + public void setCacheEnabled(boolean cacheEnabled) { + this.cacheEnabled = cacheEnabled; + this.cacheView(); + } + + public void enableMapLoading(boolean loadingEnabled) { + if (loadingEnabled && !this.isMapLoaded) { + this.getMapLoadingLayoutView().setVisibility(View.VISIBLE); + } + } + + public void setMoveOnMarkerPress(boolean moveOnPress) { + this.moveOnMarkerPress = moveOnPress; + } + + public void setLoadingBackgroundColor(Integer loadingBackgroundColor) { + this.loadingBackgroundColor = loadingBackgroundColor; + + if (this.mapLoadingLayout != null) { + if (loadingBackgroundColor == null) { + this.mapLoadingLayout.setBackgroundColor(Color.WHITE); + } else { + this.mapLoadingLayout.setBackgroundColor(this.loadingBackgroundColor); + } + } + } + + public void setLoadingIndicatorColor(Integer loadingIndicatorColor) { + this.loadingIndicatorColor = loadingIndicatorColor; + if (this.mapLoadingProgressBar != null) { + Integer color = loadingIndicatorColor; + if (color == null) { + color = Color.parseColor("#606060"); + } + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + ColorStateList progressTintList = ColorStateList.valueOf(loadingIndicatorColor); + ColorStateList secondaryProgressTintList = ColorStateList.valueOf(loadingIndicatorColor); + ColorStateList indeterminateTintList = ColorStateList.valueOf(loadingIndicatorColor); + + this.mapLoadingProgressBar.setProgressTintList(progressTintList); + this.mapLoadingProgressBar.setSecondaryProgressTintList(secondaryProgressTintList); + this.mapLoadingProgressBar.setIndeterminateTintList(indeterminateTintList); + } else { + PorterDuff.Mode mode = PorterDuff.Mode.SRC_IN; + if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.GINGERBREAD_MR1) { + mode = PorterDuff.Mode.MULTIPLY; + } + if (this.mapLoadingProgressBar.getIndeterminateDrawable() != null) + this.mapLoadingProgressBar.getIndeterminateDrawable().setColorFilter(color, mode); + if (this.mapLoadingProgressBar.getProgressDrawable() != null) + this.mapLoadingProgressBar.getProgressDrawable().setColorFilter(color, mode); + } + } + } + + public void setHandlePanDrag(boolean handlePanDrag) { + this.handlePanDrag = handlePanDrag; + } + + public void addFeature(View child, int index) { + // Our desired API is to pass up annotations/overlays as children to the mapview component. + // This is where we intercept them and do the appropriate underlying mapview action. + if (child instanceof AirMapMarker) { + AirMapMarker annotation = (AirMapMarker) child; + annotation.addToMap(map); + features.add(index, annotation); + Marker marker = (Marker) annotation.getFeature(); + markerMap.put(marker, annotation); + } else if (child instanceof AirMapPolyline) { + AirMapPolyline polylineView = (AirMapPolyline) child; + polylineView.addToMap(map); + features.add(index, polylineView); + Polyline polyline = (Polyline) polylineView.getFeature(); + polylineMap.put(polyline, polylineView); + } else if (child instanceof AirMapPolygon) { + AirMapPolygon polygonView = (AirMapPolygon) child; + polygonView.addToMap(map); + features.add(index, polygonView); + Polygon polygon = (Polygon) polygonView.getFeature(); + polygonMap.put(polygon, polygonView); + } else if (child instanceof AirMapCircle) { + AirMapCircle circleView = (AirMapCircle) child; + circleView.addToMap(map); + features.add(index, circleView); + } else if (child instanceof AirMapUrlTile) { + AirMapUrlTile urlTileView = (AirMapUrlTile) child; + urlTileView.addToMap(map); + features.add(index, urlTileView); + } else { + ViewGroup children = (ViewGroup) child; + for (int i = 0; i < children.getChildCount(); i++) { + addFeature(children.getChildAt(i), index); + } + } + } + + public int getFeatureCount() { + return features.size(); + } + + public View getFeatureAt(int index) { + return features.get(index); + } + + public void removeFeatureAt(int index) { + AirMapFeature feature = features.remove(index); + if (feature instanceof AirMapMarker) { + markerMap.remove(feature.getFeature()); + } + feature.removeFromMap(map); + } + + public WritableMap makeClickEventData(LatLng point) { + WritableMap event = new WritableNativeMap(); + + WritableMap coordinate = new WritableNativeMap(); + coordinate.putDouble("latitude", point.latitude); + coordinate.putDouble("longitude", point.longitude); + event.putMap("coordinate", coordinate); + + Projection projection = map.getProjection(); + Point screenPoint = projection.toScreenLocation(point); + + WritableMap position = new WritableNativeMap(); + position.putDouble("x", screenPoint.x); + position.putDouble("y", screenPoint.y); + event.putMap("position", position); + + return event; + } + + public void updateExtraData(Object extraData) { + // if boundsToMove is not null, we now have the MapView's width/height, so we can apply + // a proper camera move + if (boundsToMove != null) { + HashMap data = (HashMap) extraData; + float width = data.get("width"); + float height = data.get("height"); + map.moveCamera( + CameraUpdateFactory.newLatLngBounds( + boundsToMove, + (int) width, + (int) height, + 0 + ) + ); + boundsToMove = null; + } + } + + public void animateToRegion(LatLngBounds bounds, int duration) { + if (map != null) { + startMonitoringRegion(); + map.animateCamera(CameraUpdateFactory.newLatLngBounds(bounds, 0), duration, null); + } + } + + public void animateToCoordinate(LatLng coordinate, int duration) { + if (map != null) { + startMonitoringRegion(); + map.animateCamera(CameraUpdateFactory.newLatLng(coordinate), duration, null); + } + } + + public void fitToElements(boolean animated) { + LatLngBounds.Builder builder = new LatLngBounds.Builder(); + + boolean addedPosition = false; + + for (AirMapFeature feature : features) { + if (feature instanceof AirMapMarker) { + Marker marker = (Marker) feature.getFeature(); + builder.include(marker.getPosition()); + addedPosition = true; + } + // TODO(lmr): may want to include shapes / etc. + } + if (addedPosition) { + LatLngBounds bounds = builder.build(); + CameraUpdate cu = CameraUpdateFactory.newLatLngBounds(bounds, baseMapPadding); + if (animated) { + startMonitoringRegion(); + map.animateCamera(cu); + } else { + map.moveCamera(cu); + } + } + } + + public void fitToSuppliedMarkers(ReadableArray markerIDsArray, boolean animated) { + LatLngBounds.Builder builder = new LatLngBounds.Builder(); + + String[] markerIDs = new String[markerIDsArray.size()]; + for (int i = 0; i < markerIDsArray.size(); i++) { + markerIDs[i] = markerIDsArray.getString(i); + } + + boolean addedPosition = false; + + List markerIDList = Arrays.asList(markerIDs); + + for (AirMapFeature feature : features) { + if (feature instanceof AirMapMarker) { + String identifier = ((AirMapMarker) feature).getIdentifier(); + Marker marker = (Marker) feature.getFeature(); + if (markerIDList.contains(identifier)) { + builder.include(marker.getPosition()); + addedPosition = true; + } + } + } + + if (addedPosition) { + LatLngBounds bounds = builder.build(); + CameraUpdate cu = CameraUpdateFactory.newLatLngBounds(bounds, baseMapPadding); + if (animated) { + startMonitoringRegion(); + map.animateCamera(cu); + } else { + map.moveCamera(cu); + } + } + } + + public void fitToCoordinates(ReadableArray coordinatesArray, ReadableMap edgePadding, + boolean animated) { + LatLngBounds.Builder builder = new LatLngBounds.Builder(); + + for (int i = 0; i < coordinatesArray.size(); i++) { + ReadableMap latLng = coordinatesArray.getMap(i); + Double lat = latLng.getDouble("latitude"); + Double lng = latLng.getDouble("longitude"); + builder.include(new LatLng(lat, lng)); + } + + LatLngBounds bounds = builder.build(); + CameraUpdate cu = CameraUpdateFactory.newLatLngBounds(bounds, baseMapPadding); + + if (edgePadding != null) { + map.setPadding(edgePadding.getInt("left"), edgePadding.getInt("top"), + edgePadding.getInt("right"), edgePadding.getInt("bottom")); + } + + if (animated) { + startMonitoringRegion(); + map.animateCamera(cu); + } else { + map.moveCamera(cu); + } + map.setPadding(0, 0, 0, + 0); // Without this, the Google logo is moved up by the value of edgePadding.bottom + } + + // InfoWindowAdapter interface - private void removeMapLoadingLayoutView() { - this.removeMapLoadingProgressBar(); - if (this.mapLoadingLayout != null) { - ((ViewGroup)this.mapLoadingLayout.getParent()).removeView(this.mapLoadingLayout); - this.mapLoadingLayout = null; - } + @Override + public View getInfoWindow(Marker marker) { + AirMapMarker markerView = markerMap.get(marker); + return markerView.getCallout(); + } + + @Override + public View getInfoContents(Marker marker) { + AirMapMarker markerView = markerMap.get(marker); + return markerView.getInfoContents(); + } + + @Override + public boolean dispatchTouchEvent(MotionEvent ev) { + scaleDetector.onTouchEvent(ev); + gestureDetector.onTouchEvent(ev); + + int action = MotionEventCompat.getActionMasked(ev); + + switch (action) { + case (MotionEvent.ACTION_DOWN): + this.getParent().requestDisallowInterceptTouchEvent( + map != null && map.getUiSettings().isScrollGesturesEnabled()); + isTouchDown = true; + break; + case (MotionEvent.ACTION_MOVE): + startMonitoringRegion(); + break; + case (MotionEvent.ACTION_UP): + // Clear this regardless, since isScrollGesturesEnabled() may have been updated + this.getParent().requestDisallowInterceptTouchEvent(false); + isTouchDown = false; + break; } + super.dispatchTouchEvent(ev); + return true; + } + + // Timer Implementation - private void cacheView() { - if (this.cacheEnabled) { - final ImageView cacheImageView = this.getCacheImageView(); - final RelativeLayout mapLoadingLayout = this.getMapLoadingLayoutView(); - cacheImageView.setVisibility(View.INVISIBLE); - mapLoadingLayout.setVisibility(View.VISIBLE); - if (this.isMapLoaded) { - this.map.snapshot(new GoogleMap.SnapshotReadyCallback() { - @Override public void onSnapshotReady(Bitmap bitmap) { - cacheImageView.setImageBitmap(bitmap); - cacheImageView.setVisibility(View.VISIBLE); - mapLoadingLayout.setVisibility(View.INVISIBLE); - } - }); - } - } - else { - this.removeCacheImageView(); - if (this.isMapLoaded) { - this.removeMapLoadingLayoutView(); - } - } - } + public void startMonitoringRegion() { + if (isMonitoringRegion) return; + timerHandler.postDelayed(timerRunnable, 100); + isMonitoringRegion = true; + } + + public void stopMonitoringRegion() { + if (!isMonitoringRegion) return; + timerHandler.removeCallbacks(timerRunnable); + isMonitoringRegion = false; + } + + private LatLngBounds lastBoundsEmitted; + + Handler timerHandler = new Handler(); + Runnable timerRunnable = new Runnable() { - public void onPanDrag(MotionEvent ev) { - Point point = new Point((int) ev.getX(), (int) ev.getY()); - LatLng coords = this.map.getProjection().fromScreenLocation(point); - WritableMap event = makeClickEventData(coords); - manager.pushEvent(context, this, "onPanDrag", event); - } + @Override + public void run() { + + Projection projection = map.getProjection(); + VisibleRegion region = (projection != null) ? projection.getVisibleRegion() : null; + LatLngBounds bounds = (region != null) ? region.latLngBounds : null; + + if ((bounds != null) && + (lastBoundsEmitted == null || + LatLngBoundsUtils.BoundsAreDifferent(bounds, lastBoundsEmitted))) { + LatLng center = map.getCameraPosition().target; + lastBoundsEmitted = bounds; + eventDispatcher.dispatchEvent(new RegionChangeEvent(getId(), bounds, center, true)); + } + + timerHandler.postDelayed(this, 100); + } + }; + + @Override + public void onMarkerDragStart(Marker marker) { + WritableMap event = makeClickEventData(marker.getPosition()); + manager.pushEvent(context, this, "onMarkerDragStart", event); + + AirMapMarker markerView = markerMap.get(marker); + event = makeClickEventData(marker.getPosition()); + manager.pushEvent(context, markerView, "onDragStart", event); + } + + @Override + public void onMarkerDrag(Marker marker) { + WritableMap event = makeClickEventData(marker.getPosition()); + manager.pushEvent(context, this, "onMarkerDrag", event); + + AirMapMarker markerView = markerMap.get(marker); + event = makeClickEventData(marker.getPosition()); + manager.pushEvent(context, markerView, "onDrag", event); + } + + @Override + public void onMarkerDragEnd(Marker marker) { + WritableMap event = makeClickEventData(marker.getPosition()); + manager.pushEvent(context, this, "onMarkerDragEnd", event); + + AirMapMarker markerView = markerMap.get(marker); + event = makeClickEventData(marker.getPosition()); + manager.pushEvent(context, markerView, "onDragEnd", event); + } + + private ProgressBar getMapLoadingProgressBar() { + if (this.mapLoadingProgressBar == null) { + this.mapLoadingProgressBar = new ProgressBar(getContext()); + this.mapLoadingProgressBar.setIndeterminate(true); + } + if (this.loadingIndicatorColor != null) { + this.setLoadingIndicatorColor(this.loadingIndicatorColor); + } + return this.mapLoadingProgressBar; + } + + private RelativeLayout getMapLoadingLayoutView() { + if (this.mapLoadingLayout == null) { + this.mapLoadingLayout = new RelativeLayout(getContext()); + this.mapLoadingLayout.setBackgroundColor(Color.LTGRAY); + this.addView(this.mapLoadingLayout, + new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.MATCH_PARENT)); + + RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams( + RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT); + params.addRule(RelativeLayout.CENTER_IN_PARENT); + this.mapLoadingLayout.addView(this.getMapLoadingProgressBar(), params); + + this.mapLoadingLayout.setVisibility(View.INVISIBLE); + } + this.setLoadingBackgroundColor(this.loadingBackgroundColor); + return this.mapLoadingLayout; + } + + private ImageView getCacheImageView() { + if (this.cacheImageView == null) { + this.cacheImageView = new ImageView(getContext()); + this.addView(this.cacheImageView, + new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.MATCH_PARENT)); + this.cacheImageView.setVisibility(View.INVISIBLE); + } + return this.cacheImageView; + } + + private void removeCacheImageView() { + if (this.cacheImageView != null) { + ((ViewGroup) this.cacheImageView.getParent()).removeView(this.cacheImageView); + this.cacheImageView = null; + } + } + + private void removeMapLoadingProgressBar() { + if (this.mapLoadingProgressBar != null) { + ((ViewGroup) this.mapLoadingProgressBar.getParent()).removeView(this.mapLoadingProgressBar); + this.mapLoadingProgressBar = null; + } + } + + private void removeMapLoadingLayoutView() { + this.removeMapLoadingProgressBar(); + if (this.mapLoadingLayout != null) { + ((ViewGroup) this.mapLoadingLayout.getParent()).removeView(this.mapLoadingLayout); + this.mapLoadingLayout = null; + } + } + + private void cacheView() { + if (this.cacheEnabled) { + final ImageView cacheImageView = this.getCacheImageView(); + final RelativeLayout mapLoadingLayout = this.getMapLoadingLayoutView(); + cacheImageView.setVisibility(View.INVISIBLE); + mapLoadingLayout.setVisibility(View.VISIBLE); + if (this.isMapLoaded) { + this.map.snapshot(new GoogleMap.SnapshotReadyCallback() { + @Override public void onSnapshotReady(Bitmap bitmap) { + cacheImageView.setImageBitmap(bitmap); + cacheImageView.setVisibility(View.VISIBLE); + mapLoadingLayout.setVisibility(View.INVISIBLE); + } + }); + } + } else { + this.removeCacheImageView(); + if (this.isMapLoaded) { + this.removeMapLoadingLayoutView(); + } + } + } + + public void onPanDrag(MotionEvent ev) { + Point point = new Point((int) ev.getX(), (int) ev.getY()); + LatLng coords = this.map.getProjection().fromScreenLocation(point); + WritableMap event = makeClickEventData(coords); + manager.pushEvent(context, this, "onPanDrag", event); + } } diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/LatLngBoundsUtils.java b/lib/android/src/main/java/com/airbnb/android/react/maps/LatLngBoundsUtils.java index ed1058c88..d32e0dc72 100644 --- a/lib/android/src/main/java/com/airbnb/android/react/maps/LatLngBoundsUtils.java +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/LatLngBoundsUtils.java @@ -4,44 +4,44 @@ import com.google.android.gms.maps.model.LatLngBounds; public class LatLngBoundsUtils { - public static boolean BoundsAreDifferent(LatLngBounds a, LatLngBounds b) { - LatLng centerA = a.getCenter(); - double latA = centerA.latitude; - double lngA = centerA.longitude; - double latDeltaA = a.northeast.latitude - a.southwest.latitude; - double lngDeltaA = a.northeast.longitude - a.southwest.longitude; - - LatLng centerB = b.getCenter(); - double latB = centerB.latitude; - double lngB = centerB.longitude; - double latDeltaB = b.northeast.latitude - b.southwest.latitude; - double lngDeltaB = b.northeast.longitude - b.southwest.longitude; - - double latEps = LatitudeEpsilon(a, b); - double lngEps = LongitudeEpsilon(a, b); - - return - different(latA, latB, latEps) || - different(lngA, lngB, lngEps) || - different(latDeltaA, latDeltaB, latEps) || - different(lngDeltaA, lngDeltaB, lngEps); - } - - private static boolean different(double a, double b, double epsilon) { - return Math.abs(a - b) > epsilon; - } - - private static double LatitudeEpsilon(LatLngBounds a, LatLngBounds b) { - double sizeA = a.northeast.latitude - a.southwest.latitude; // something mod 180? - double sizeB = b.northeast.latitude - b.southwest.latitude; // something mod 180? - double size = Math.min(Math.abs(sizeA), Math.abs(sizeB)); - return size / 2560; - } - - private static double LongitudeEpsilon(LatLngBounds a, LatLngBounds b) { - double sizeA = a.northeast.longitude - a.southwest.longitude; - double sizeB = b.northeast.longitude - b.southwest.longitude; - double size = Math.min(Math.abs(sizeA), Math.abs(sizeB)); - return size / 2560; - } + public static boolean BoundsAreDifferent(LatLngBounds a, LatLngBounds b) { + LatLng centerA = a.getCenter(); + double latA = centerA.latitude; + double lngA = centerA.longitude; + double latDeltaA = a.northeast.latitude - a.southwest.latitude; + double lngDeltaA = a.northeast.longitude - a.southwest.longitude; + + LatLng centerB = b.getCenter(); + double latB = centerB.latitude; + double lngB = centerB.longitude; + double latDeltaB = b.northeast.latitude - b.southwest.latitude; + double lngDeltaB = b.northeast.longitude - b.southwest.longitude; + + double latEps = LatitudeEpsilon(a, b); + double lngEps = LongitudeEpsilon(a, b); + + return + different(latA, latB, latEps) || + different(lngA, lngB, lngEps) || + different(latDeltaA, latDeltaB, latEps) || + different(lngDeltaA, lngDeltaB, lngEps); + } + + private static boolean different(double a, double b, double epsilon) { + return Math.abs(a - b) > epsilon; + } + + private static double LatitudeEpsilon(LatLngBounds a, LatLngBounds b) { + double sizeA = a.northeast.latitude - a.southwest.latitude; // something mod 180? + double sizeB = b.northeast.latitude - b.southwest.latitude; // something mod 180? + double size = Math.min(Math.abs(sizeA), Math.abs(sizeB)); + return size / 2560; + } + + private static double LongitudeEpsilon(LatLngBounds a, LatLngBounds b) { + double sizeA = a.northeast.longitude - a.southwest.longitude; + double sizeB = b.northeast.longitude - b.southwest.longitude; + double size = Math.min(Math.abs(sizeA), Math.abs(sizeB)); + return size / 2560; + } } diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/MapsPackage.java b/lib/android/src/main/java/com/airbnb/android/react/maps/MapsPackage.java index e76f63aa2..da59849b3 100644 --- a/lib/android/src/main/java/com/airbnb/android/react/maps/MapsPackage.java +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/MapsPackage.java @@ -13,41 +13,41 @@ import java.util.List; public class MapsPackage implements ReactPackage { - public MapsPackage(Activity activity) { - } // backwards compatibility - - public MapsPackage() { - } - - @Override - public List createNativeModules(ReactApplicationContext reactContext) { - return Arrays.asList(new AirMapModule(reactContext)); - } - - @Override - public List> createJSModules() { - return Collections.emptyList(); - } - - @Override - public List createViewManagers(ReactApplicationContext reactContext) { - AirMapCalloutManager calloutManager = new AirMapCalloutManager(); - AirMapMarkerManager annotationManager = new AirMapMarkerManager(); - AirMapPolylineManager polylineManager = new AirMapPolylineManager(reactContext); - AirMapPolygonManager polygonManager = new AirMapPolygonManager(reactContext); - AirMapCircleManager circleManager = new AirMapCircleManager(reactContext); - AirMapManager mapManager = new AirMapManager(reactContext); - AirMapLiteManager mapLiteManager = new AirMapLiteManager(reactContext); - AirMapUrlTileManager tileManager = new AirMapUrlTileManager(reactContext); - - return Arrays.asList( - calloutManager, - annotationManager, - polylineManager, - polygonManager, - circleManager, - mapManager, - mapLiteManager, - tileManager); - } + public MapsPackage(Activity activity) { + } // backwards compatibility + + public MapsPackage() { + } + + @Override + public List createNativeModules(ReactApplicationContext reactContext) { + return Arrays.asList(new AirMapModule(reactContext)); + } + + @Override + public List> createJSModules() { + return Collections.emptyList(); + } + + @Override + public List createViewManagers(ReactApplicationContext reactContext) { + AirMapCalloutManager calloutManager = new AirMapCalloutManager(); + AirMapMarkerManager annotationManager = new AirMapMarkerManager(); + AirMapPolylineManager polylineManager = new AirMapPolylineManager(reactContext); + AirMapPolygonManager polygonManager = new AirMapPolygonManager(reactContext); + AirMapCircleManager circleManager = new AirMapCircleManager(reactContext); + AirMapManager mapManager = new AirMapManager(reactContext); + AirMapLiteManager mapLiteManager = new AirMapLiteManager(reactContext); + AirMapUrlTileManager tileManager = new AirMapUrlTileManager(reactContext); + + return Arrays.asList( + calloutManager, + annotationManager, + polylineManager, + polygonManager, + circleManager, + mapManager, + mapLiteManager, + tileManager); + } } diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/RegionChangeEvent.java b/lib/android/src/main/java/com/airbnb/android/react/maps/RegionChangeEvent.java index 28a3b322b..43b1f678e 100644 --- a/lib/android/src/main/java/com/airbnb/android/react/maps/RegionChangeEvent.java +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/RegionChangeEvent.java @@ -8,40 +8,40 @@ import com.google.android.gms.maps.model.LatLngBounds; public class RegionChangeEvent extends Event { - private final LatLngBounds bounds; - private final LatLng center; - private final boolean continuous; - - public RegionChangeEvent(int id, LatLngBounds bounds, LatLng center, boolean continuous) { - super(id); - this.bounds = bounds; - this.center = center; - this.continuous = continuous; - } - - @Override - public String getEventName() { - return "topChange"; - } - - @Override - public boolean canCoalesce() { - return false; - } - - @Override - public void dispatch(RCTEventEmitter rctEventEmitter) { - - WritableMap event = new WritableNativeMap(); - event.putBoolean("continuous", continuous); - - WritableMap region = new WritableNativeMap(); - region.putDouble("latitude", center.latitude); - region.putDouble("longitude", center.longitude); - region.putDouble("latitudeDelta", bounds.northeast.latitude - bounds.southwest.latitude); - region.putDouble("longitudeDelta", bounds.northeast.longitude - bounds.southwest.longitude); - event.putMap("region", region); - - rctEventEmitter.receiveEvent(getViewTag(), getEventName(), event); - } + private final LatLngBounds bounds; + private final LatLng center; + private final boolean continuous; + + public RegionChangeEvent(int id, LatLngBounds bounds, LatLng center, boolean continuous) { + super(id); + this.bounds = bounds; + this.center = center; + this.continuous = continuous; + } + + @Override + public String getEventName() { + return "topChange"; + } + + @Override + public boolean canCoalesce() { + return false; + } + + @Override + public void dispatch(RCTEventEmitter rctEventEmitter) { + + WritableMap event = new WritableNativeMap(); + event.putBoolean("continuous", continuous); + + WritableMap region = new WritableNativeMap(); + region.putDouble("latitude", center.latitude); + region.putDouble("longitude", center.longitude); + region.putDouble("latitudeDelta", bounds.northeast.latitude - bounds.southwest.latitude); + region.putDouble("longitudeDelta", bounds.northeast.longitude - bounds.southwest.longitude); + event.putMap("region", region); + + rctEventEmitter.receiveEvent(getViewTag(), getEventName(), event); + } } diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/SizeReportingShadowNode.java b/lib/android/src/main/java/com/airbnb/android/react/maps/SizeReportingShadowNode.java index 40ace480f..bf6c29d65 100644 --- a/lib/android/src/main/java/com/airbnb/android/react/maps/SizeReportingShadowNode.java +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/SizeReportingShadowNode.java @@ -18,14 +18,14 @@ // which sends the width/height of the view after layout occurs. public class SizeReportingShadowNode extends LayoutShadowNode { - @Override - public void onCollectExtraUpdates(UIViewOperationQueue uiViewOperationQueue) { - super.onCollectExtraUpdates(uiViewOperationQueue); + @Override + public void onCollectExtraUpdates(UIViewOperationQueue uiViewOperationQueue) { + super.onCollectExtraUpdates(uiViewOperationQueue); - Map data = new HashMap<>(); - data.put("width", getLayoutWidth()); - data.put("height", getLayoutHeight()); + Map data = new HashMap<>(); + data.put("width", getLayoutWidth()); + data.put("height", getLayoutHeight()); - uiViewOperationQueue.enqueueUpdateExtraData(getReactTag(), data); - } + uiViewOperationQueue.enqueueUpdateExtraData(getReactTag(), data); + } } From d57edd2a095552999a961f210e610f0746f1470b Mon Sep 17 00:00:00 2001 From: Gabriel Peal Date: Tue, 27 Jun 2017 14:16:17 -0700 Subject: [PATCH 0270/1148] Allow react 16.0.0-alpha --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 30ffc43e8..ee92d4ab6 100644 --- a/package.json +++ b/package.json @@ -32,7 +32,7 @@ "mapkit" ], "peerDependencies": { - "react": ">=15.4.0", + "react": ">=15.4.0 || ^16.0.0-alpha", "react-native": ">=0.40" }, "devDependencies": { From ee1e7094be0eef6b5d01be64603d095841fff7fb Mon Sep 17 00:00:00 2001 From: Gabriel Peal Date: Tue, 27 Jun 2017 15:53:58 -0700 Subject: [PATCH 0271/1148] Use prop-types and add supprort for RN 0.45 --- .jscodeshiftignore | 9 +++++++++ example/android/app/build.gradle | 2 +- example/examples/EventListener.js | 2 +- lib/components/MapCallout.js | 3 ++- lib/components/MapCircle.js | 3 ++- lib/components/MapMarker.js | 3 ++- lib/components/MapPolygon.js | 3 ++- lib/components/MapPolyline.js | 3 ++- lib/components/MapUrlTile.js | 3 ++- lib/components/MapView.js | 3 ++- lib/components/decorateMapComponent.js | 2 +- package.json | 8 +++++--- 12 files changed, 31 insertions(+), 13 deletions(-) create mode 100644 .jscodeshiftignore diff --git a/.jscodeshiftignore b/.jscodeshiftignore new file mode 100644 index 000000000..a78536177 --- /dev/null +++ b/.jscodeshiftignore @@ -0,0 +1,9 @@ +# To run a codeshift on the react-native-maps library, cd to the root dir and run: +# jscodeshift -t PATH_TO_TRANSFORM . --ignore-config .jscodeshiftignore +.idea +android +docs +example +gradle +node_modules +scripts \ No newline at end of file diff --git a/example/android/app/build.gradle b/example/android/app/build.gradle index 7c63b3b43..7a8e8b7dd 100644 --- a/example/android/app/build.gradle +++ b/example/android/app/build.gradle @@ -127,7 +127,7 @@ android { } dependencies { - compile 'com.facebook.react:react-native:0.42.+' + compile 'com.facebook.react:react-native:0.45.+' compile 'com.android.support:appcompat-v7:25.3.0' compile 'com.android.support:support-annotations:25.3.0' compile project(':react-native-maps-lib') diff --git a/example/examples/EventListener.js b/example/examples/EventListener.js index c8d3e937f..19a393063 100644 --- a/example/examples/EventListener.js +++ b/example/examples/EventListener.js @@ -7,7 +7,7 @@ import { ScrollView, } from 'react-native'; // eslint-disable-next-line max-len -import SyntheticEvent from 'react-native/Libraries/Renderer/src/renderers/shared/stack/event/SyntheticEvent'; +import SyntheticEvent from 'react-native/Libraries/Renderer/src/renderers/shared/shared/event/SyntheticEvent'; import MapView from 'react-native-maps'; import PriceMarker from './PriceMarker'; diff --git a/lib/components/MapCallout.js b/lib/components/MapCallout.js index 8989df40c..226b52fe2 100644 --- a/lib/components/MapCallout.js +++ b/lib/components/MapCallout.js @@ -1,4 +1,5 @@ -import React, { PropTypes } from 'react'; +import PropTypes from 'prop-types'; +import React from 'react'; import { StyleSheet, ViewPropTypes, diff --git a/lib/components/MapCircle.js b/lib/components/MapCircle.js index a3371ca60..acf066b24 100644 --- a/lib/components/MapCircle.js +++ b/lib/components/MapCircle.js @@ -1,4 +1,5 @@ -import React, { PropTypes } from 'react'; +import PropTypes from 'prop-types'; +import React from 'react'; import { ViewPropTypes, } from 'react-native'; diff --git a/lib/components/MapMarker.js b/lib/components/MapMarker.js index 0589979fa..6e2b8585d 100644 --- a/lib/components/MapMarker.js +++ b/lib/components/MapMarker.js @@ -1,4 +1,5 @@ -import React, { PropTypes } from 'react'; +import PropTypes from 'prop-types'; +import React from 'react'; import { StyleSheet, Platform, diff --git a/lib/components/MapPolygon.js b/lib/components/MapPolygon.js index f88648fca..27f2aa322 100644 --- a/lib/components/MapPolygon.js +++ b/lib/components/MapPolygon.js @@ -1,4 +1,5 @@ -import React, { PropTypes } from 'react'; +import PropTypes from 'prop-types'; +import React from 'react'; import { ViewPropTypes, } from 'react-native'; diff --git a/lib/components/MapPolyline.js b/lib/components/MapPolyline.js index b2ecdffc1..af1573eff 100644 --- a/lib/components/MapPolyline.js +++ b/lib/components/MapPolyline.js @@ -1,4 +1,5 @@ -import React, { PropTypes } from 'react'; +import PropTypes from 'prop-types'; +import React from 'react'; import { ViewPropTypes, } from 'react-native'; diff --git a/lib/components/MapUrlTile.js b/lib/components/MapUrlTile.js index bb1d26552..f61c1e0d3 100644 --- a/lib/components/MapUrlTile.js +++ b/lib/components/MapUrlTile.js @@ -1,4 +1,5 @@ -import React, { PropTypes } from 'react'; +import PropTypes from 'prop-types'; +import React from 'react'; import { ViewPropTypes, diff --git a/lib/components/MapView.js b/lib/components/MapView.js index 0d8bf5450..a6660719a 100644 --- a/lib/components/MapView.js +++ b/lib/components/MapView.js @@ -1,4 +1,5 @@ -import React, { PropTypes } from 'react'; +import PropTypes from 'prop-types'; +import React from 'react'; import { EdgeInsetsPropType, Platform, diff --git a/lib/components/decorateMapComponent.js b/lib/components/decorateMapComponent.js index e655c4c33..168d4f122 100644 --- a/lib/components/decorateMapComponent.js +++ b/lib/components/decorateMapComponent.js @@ -1,4 +1,4 @@ -import { PropTypes } from 'react'; +import PropTypes from 'prop-types'; import { requireNativeComponent, NativeModules, diff --git a/package.json b/package.json index ee92d4ab6..275ea4349 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,8 @@ ], "peerDependencies": { "react": ">=15.4.0 || ^16.0.0-alpha", - "react-native": ">=0.40" + "react-native": ">=0.40", + "prop-types": "^15.5.10" }, "devDependencies": { "babel-eslint": "^6.1.2", @@ -48,8 +49,9 @@ "eslint-plugin-react": "^6.1.2", "gitbook-cli": "^2.3.0", "lodash": "^4.17.2", - "react": "~15.4.1", - "react-native": "^0.42.0" + "prop-types": "^15.5.10", + "react": "^16.0.0-alpha.12", + "react-native": "^0.45.1" }, "rnpm": { "android": { From 8a5a8d1decb0666da4f4845bb5ff753967c5df29 Mon Sep 17 00:00:00 2001 From: Gabriel Peal Date: Tue, 27 Jun 2017 16:09:58 -0700 Subject: [PATCH 0272/1148] Upgraded ios deps --- example/ios/Podfile.lock | 46 ++++++++++++++++++---------------------- examples/ios/bundler | 17 +++++++++++++++ examples/ios/fuzzy_match | 17 +++++++++++++++ examples/ios/pod | 17 +++++++++++++++ examples/ios/sandbox-pod | 17 +++++++++++++++ examples/ios/xcodeproj | 17 +++++++++++++++ 6 files changed, 106 insertions(+), 25 deletions(-) create mode 100755 examples/ios/bundler create mode 100755 examples/ios/fuzzy_match create mode 100755 examples/ios/pod create mode 100755 examples/ios/sandbox-pod create mode 100755 examples/ios/xcodeproj diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index ff6774aa2..3cf7f4d85 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -4,41 +4,37 @@ PODS: - GoogleMaps/Base (2.1.1) - GoogleMaps/Maps (2.1.1): - GoogleMaps/Base - - React (0.42.3): - - React/Core (= 0.42.3) - - react-native-google-maps (0.13.1): + - React (0.45.1): + - React/Core (= 0.45.1) + - react-native-google-maps (0.15.2): - GoogleMaps (= 2.1.1) - React - - react-native-maps (0.13.1): + - react-native-maps (0.15.2): - React - - React/Core (0.42.3): - - React/cxxreact - - Yoga (= 0.42.3.React) - - React/cxxreact (0.42.3): - - React/jschelpers - - React/jschelpers (0.42.3) - - React/RCTActionSheet (0.42.3): + - React/Core (0.45.1): + - Yoga (= 0.45.1.React) + - React/RCTActionSheet (0.45.1): - React/Core - - React/RCTAnimation (0.42.3): + - React/RCTAnimation (0.45.1): - React/Core - - React/RCTGeolocation (0.42.3): + - React/RCTGeolocation (0.45.1): - React/Core - - React/RCTImage (0.42.3): + - React/RCTImage (0.45.1): - React/Core - React/RCTNetwork - - React/RCTLinkingIOS (0.42.3): + - React/RCTLinkingIOS (0.45.1): - React/Core - - React/RCTNetwork (0.42.3): + - React/RCTNetwork (0.45.1): - React/Core - - React/RCTSettings (0.42.3): + - React/RCTSettings (0.45.1): - React/Core - - React/RCTText (0.42.3): + - React/RCTText (0.45.1): - React/Core - - React/RCTVibration (0.42.3): + - React/RCTVibration (0.45.1): - React/Core - - React/RCTWebSocket (0.42.3): + - React/RCTWebSocket (0.45.1): - React/Core - - Yoga (0.42.3.React) + - Yoga (0.45.1.React) DEPENDENCIES: - GoogleMaps @@ -69,10 +65,10 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: GoogleMaps: a5b5bbe47734e2443bde781a6aa64e69fdb6d785 - React: 35e039680feacd0563677d49ba410112d2748559 - react-native-google-maps: b2668747ec289759993dc2411a7078afafa8adea - react-native-maps: 326ddbaaea8f6044b1817fb028c40950c71cc38a - Yoga: 86ce777665c8259b94ef8dbea76b84634237f4ea + React: 0c9191a8b0c843d7004f950ac6b5f6cba9d125c7 + react-native-google-maps: d0b8772eb76e1615ea32c73bc9d573360b8c0817 + react-native-maps: fe2e4680b4d3fcfd84d636ccedd470fe358d55e1 + Yoga: 89c8738d42a0b46a113acb4e574336d61cba2985 PODFILE CHECKSUM: 222d08e48f834b6a3de650b72786105af7a9d331 diff --git a/examples/ios/bundler b/examples/ios/bundler new file mode 100755 index 000000000..905387619 --- /dev/null +++ b/examples/ios/bundler @@ -0,0 +1,17 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true +# +# This file was generated by Bundler. +# +# The application 'bundler' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +require "pathname" +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../../Gemfile", + Pathname.new(__FILE__).realpath) + +require "rubygems" +require "bundler/setup" + +load Gem.bin_path("bundler", "bundler") diff --git a/examples/ios/fuzzy_match b/examples/ios/fuzzy_match new file mode 100755 index 000000000..f71547393 --- /dev/null +++ b/examples/ios/fuzzy_match @@ -0,0 +1,17 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true +# +# This file was generated by Bundler. +# +# The application 'fuzzy_match' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +require "pathname" +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../../Gemfile", + Pathname.new(__FILE__).realpath) + +require "rubygems" +require "bundler/setup" + +load Gem.bin_path("fuzzy_match", "fuzzy_match") diff --git a/examples/ios/pod b/examples/ios/pod new file mode 100755 index 000000000..3c4a4d04c --- /dev/null +++ b/examples/ios/pod @@ -0,0 +1,17 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true +# +# This file was generated by Bundler. +# +# The application 'pod' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +require "pathname" +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../../Gemfile", + Pathname.new(__FILE__).realpath) + +require "rubygems" +require "bundler/setup" + +load Gem.bin_path("cocoapods", "pod") diff --git a/examples/ios/sandbox-pod b/examples/ios/sandbox-pod new file mode 100755 index 000000000..c76cfd0a5 --- /dev/null +++ b/examples/ios/sandbox-pod @@ -0,0 +1,17 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true +# +# This file was generated by Bundler. +# +# The application 'sandbox-pod' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +require "pathname" +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../../Gemfile", + Pathname.new(__FILE__).realpath) + +require "rubygems" +require "bundler/setup" + +load Gem.bin_path("cocoapods", "sandbox-pod") diff --git a/examples/ios/xcodeproj b/examples/ios/xcodeproj new file mode 100755 index 000000000..3c3452c17 --- /dev/null +++ b/examples/ios/xcodeproj @@ -0,0 +1,17 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true +# +# This file was generated by Bundler. +# +# The application 'xcodeproj' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +require "pathname" +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../../Gemfile", + Pathname.new(__FILE__).realpath) + +require "rubygems" +require "bundler/setup" + +load Gem.bin_path("xcodeproj", "xcodeproj") From 0a8f6ce7ec2aaeaddfab48a55ce4562328409987 Mon Sep 17 00:00:00 2001 From: Gabriel Peal Date: Tue, 27 Jun 2017 16:25:03 -0700 Subject: [PATCH 0273/1148] Added BatchedBridge --- example/ios/Podfile | 3 ++- example/ios/Podfile.lock | 9 ++++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/example/ios/Podfile b/example/ios/Podfile index 6cff9aae8..656f283e1 100644 --- a/example/ios/Podfile +++ b/example/ios/Podfile @@ -18,7 +18,8 @@ target 'AirMapsExplorer' do 'RCTSettings', 'RCTText', 'RCTVibration', - 'RCTWebSocket' + 'RCTWebSocket', + 'BatchedBridge' ] pod 'GoogleMaps' # <~~ remove this line if you do not want to support GoogleMaps on iOS diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index 3cf7f4d85..3eec18fee 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -11,8 +11,14 @@ PODS: - React - react-native-maps (0.15.2): - React + - React/BatchedBridge (0.45.1): + - React/Core + - React/cxxreact_legacy - React/Core (0.45.1): - Yoga (= 0.45.1.React) + - React/cxxreact_legacy (0.45.1): + - React/jschelpers_legacy + - React/jschelpers_legacy (0.45.1) - React/RCTActionSheet (0.45.1): - React/Core - React/RCTAnimation (0.45.1): @@ -40,6 +46,7 @@ DEPENDENCIES: - GoogleMaps - react-native-google-maps (from `../../`) - react-native-maps (from `../../`) + - React/BatchedBridge (from `../../node_modules/react-native`) - React/Core (from `../../node_modules/react-native`) - React/RCTActionSheet (from `../../node_modules/react-native`) - React/RCTAnimation (from `../../node_modules/react-native`) @@ -70,6 +77,6 @@ SPEC CHECKSUMS: react-native-maps: fe2e4680b4d3fcfd84d636ccedd470fe358d55e1 Yoga: 89c8738d42a0b46a113acb4e574336d61cba2985 -PODFILE CHECKSUM: 222d08e48f834b6a3de650b72786105af7a9d331 +PODFILE CHECKSUM: 8b3eb68ef6553bf1fcb8a467e0e63000b37ec692 COCOAPODS: 1.2.0 From 153e83def147395041e18709c40c7f19633de2c2 Mon Sep 17 00:00:00 2001 From: Gabriel Peal Date: Tue, 27 Jun 2017 16:54:34 -0700 Subject: [PATCH 0274/1148] v0.15.3 --- CHANGELOG.md | 8 ++++++++ lib/android/gradle.properties | 2 +- package.json | 2 +- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5968b7e7b..50b2027bc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Change Log +## 0.15.3 (June 27, 2017) + +* iOS: [#1362](https://github.com/airbnb/react-native-maps/pull/1362) Updates for React 0.43-0.45 and React 16. +* JS: [#1323](https://github.com/airbnb/react-native-maps/pull/1323) Updates for React 0.43-0.45 and React 16. +* Android/iOS/JS: [#1440](https://github.com/airbnb/react-native-maps/pull/1440) Updates for React 0.43-0.45 and React 16. +* iOS: [#1115](https://github.com/airbnb/react-native-maps/pull/1115) Fix animateToCoordinate and animateToRegion +* Android: [#1403](https://github.com/airbnb/react-native-maps/pull/1403) Fix an NPE + ## 0.15.2 (May 20, 2017) * iOS: [#1351](https://github.com/airbnb/react-native-maps/pull/1351) Fix file references diff --git a/lib/android/gradle.properties b/lib/android/gradle.properties index 65c67798d..1a5d3021b 100644 --- a/lib/android/gradle.properties +++ b/lib/android/gradle.properties @@ -1,5 +1,5 @@ VERSION_CODE=4 -VERSION_NAME=0.15.2 +VERSION_NAME=0.15.3 GROUP=com.airbnb.android POM_DESCRIPTION=React Native Map view component for Android diff --git a/package.json b/package.json index 275ea4349..7cb48301b 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "description": "React Native Mapview component for iOS + Android", "main": "index.js", "author": "Leland Richardson ", - "version": "0.15.2", + "version": "0.15.3", "scripts": { "start": "node node_modules/react-native/local-cli/cli.js start", "run:packager": "./node_modules/react-native/packager/packager.sh", From 5e6d74e3039197d98dbfe95604dae783946080fc Mon Sep 17 00:00:00 2001 From: foysal Date: Wed, 5 Jul 2017 20:49:34 +0200 Subject: [PATCH 0275/1148] updates npm cache clean command (#1450) latest version of npm seems to be missing the command ```npm clean cache``` but ```npm cache clean``` seems to work. Might help copy-pasters like me. --- docs/installation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/installation.md b/docs/installation.md index 12842d7c6..52063bef9 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -203,7 +203,7 @@ Enter the name of the API key and create it. 1. Clean the cache : ``` watchman watch-del-all - npm clean cache + npm cache clean ``` 1. When starting emulator, make sure you have enabled `Wipe user data`. From eb9eb0fe9549949dfbc7f51001dab52c98126909 Mon Sep 17 00:00:00 2001 From: Jacob Morris Date: Thu, 6 Jul 2017 04:50:23 +1000 Subject: [PATCH 0276/1148] Reference install solution in issue #718 in install docs (#1448) --- docs/installation.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/installation.md b/docs/installation.md index 52063bef9..ad9d4b383 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -123,6 +123,8 @@ Source: https://developers.google.com/maps/documentation/android-api/signup ## Troubleshooting +If you get the error `duplicate symbols for architecture x86_64` when building for iOS, you may need to reconfigure your linking and Podfile as [described in detail in this comment on issue #718](https://github.com/airbnb/react-native-maps/issues/718#issuecomment-295585410) + If you have a blank map issue, ([#118](https://github.com/airbnb/react-native-maps/issues/118), [#176](https://github.com/airbnb/react-native-maps/issues/176), [#684](https://github.com/airbnb/react-native-maps/issues/684)), try the following lines : ### On iOS: From 045ec7eee5f90d06b00f1eb624453d6a7d02df92 Mon Sep 17 00:00:00 2001 From: foyarash Date: Wed, 5 Jul 2017 21:43:45 +0200 Subject: [PATCH 0277/1148] Add minZoom and maxZoom properties for android and ios (#1360) * Add minZoom and maxZoom properties for android and ios * Add min/max zoom level properties to AIRMap.h * Fix assignation for zoom levels for gmaps ios * Resolve conflicts, fix potential nil value on ios * Resolve conflicts --- .../android/react/maps/AirMapManager.java | 10 ++ lib/components/MapView.js | 10 ++ lib/ios/AirGoogleMaps/AIRGoogleMap.m | 7 + lib/ios/AirGoogleMaps/AIRGoogleMapManager.m | 2 + lib/ios/AirMaps/AIRMap.h | 2 + lib/ios/AirMaps/AIRMapManager.h | 16 ++ lib/ios/AirMaps/AIRMapManager.m | 169 ++++++++++++++++++ 7 files changed, 216 insertions(+) diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java index 404f6a127..e8f98a766 100644 --- a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java @@ -178,6 +178,16 @@ public void setPitchEnabled(AirMapView view, boolean pitchEnabled) { view.map.getUiSettings().setTiltGesturesEnabled(pitchEnabled); } + @ReactProp(name = "minZoomLevel") + public void setMinZoomLevel(AirMapView view, float minZoomLevel) { + view.map.setMinZoomPreference(minZoomLevel); + } + + @ReactProp(name = "maxZoomLevel") + public void setMaxZoomLevel(AirMapView view, float maxZoomLevel) { + view.map.setMaxZoomPreference(maxZoomLevel); + } + @Override public void receiveCommand(AirMapView view, int commandId, @Nullable ReadableArray args) { Integer duration; diff --git a/lib/components/MapView.js b/lib/components/MapView.js index a6660719a..2e8ba4e84 100644 --- a/lib/components/MapView.js +++ b/lib/components/MapView.js @@ -385,6 +385,16 @@ const propTypes = { */ onMarkerDragEnd: PropTypes.func, + /** + * Minimum zoom value for the map, must be between 0 and 20 + */ + minZoomLevel: PropTypes.number, + + /** + * Maximum zoom value for the map, must be between 0 and 20 + */ + maxZoomLevel: PropTypes.number, + }; class MapView extends React.Component { diff --git a/lib/ios/AirGoogleMaps/AIRGoogleMap.m b/lib/ios/AirGoogleMaps/AIRGoogleMap.m index ef73067b6..f87d34c63 100644 --- a/lib/ios/AirGoogleMaps/AIRGoogleMap.m +++ b/lib/ios/AirGoogleMaps/AIRGoogleMap.m @@ -300,6 +300,13 @@ - (BOOL)showsMyLocationButton { return self.settings.myLocationButton; } +- (void)setMinZoomLevel:(CGFloat)minZoomLevel { + [self setMinZoom:minZoomLevel maxZoom:self.maxZoom ]; +} + +- (void)setMaxZoomLevel:(CGFloat)maxZoomLevel { + [self setMinZoom:self.minZoom maxZoom:maxZoomLevel ]; +} + (MKCoordinateRegion) makeGMSCameraPositionFromMap:(GMSMapView *)map andGMSCameraPosition:(GMSCameraPosition *)position { // solution from here: http://stackoverflow.com/a/16587735/1102215 diff --git a/lib/ios/AirGoogleMaps/AIRGoogleMapManager.m b/lib/ios/AirGoogleMaps/AIRGoogleMapManager.m index 6a3b92e90..c482305b8 100644 --- a/lib/ios/AirGoogleMaps/AIRGoogleMapManager.m +++ b/lib/ios/AirGoogleMaps/AIRGoogleMapManager.m @@ -66,6 +66,8 @@ - (UIView *)view RCT_EXPORT_VIEW_PROPERTY(onRegionChange, RCTDirectEventBlock) RCT_EXPORT_VIEW_PROPERTY(onRegionChangeComplete, RCTDirectEventBlock) RCT_EXPORT_VIEW_PROPERTY(mapType, GMSMapViewType) +RCT_EXPORT_VIEW_PROPERTY(minZoomLevel, CGFloat) +RCT_EXPORT_VIEW_PROPERTY(maxZoomLevel, CGFloat) RCT_EXPORT_METHOD(animateToRegion:(nonnull NSNumber *)reactTag withRegion:(MKCoordinateRegion)region diff --git a/lib/ios/AirMaps/AIRMap.h b/lib/ios/AirMaps/AIRMap.h index 18c9a0bc0..4a88617e6 100644 --- a/lib/ios/AirMaps/AIRMap.h +++ b/lib/ios/AirMaps/AIRMap.h @@ -37,6 +37,8 @@ extern const CGFloat AIRMapZoomBoundBuffer; @property (nonatomic, assign) UIEdgeInsets legalLabelInsets; @property (nonatomic, strong) NSTimer *regionChangeObserveTimer; @property (nonatomic, assign) MKCoordinateRegion initialRegion; +@property (nonatomic, assign) CGFloat minZoomLevel; +@property (nonatomic, assign) CGFloat maxZoomLevel; @property (nonatomic, assign) CLLocationCoordinate2D pendingCenter; @property (nonatomic, assign) MKCoordinateSpan pendingSpan; diff --git a/lib/ios/AirMaps/AIRMapManager.h b/lib/ios/AirMaps/AIRMapManager.h index cc9a8c75b..29df98bfc 100644 --- a/lib/ios/AirMaps/AIRMapManager.h +++ b/lib/ios/AirMaps/AIRMapManager.h @@ -8,7 +8,23 @@ */ #import +#import "AIRMap.h" + +#define MERCATOR_RADIUS 85445659.44705395 +#define MERCATOR_OFFSET 268435456 +#define MAX_GOOGLE_LEVELS 20 @interface AIRMapManager : RCTViewManager + +- (void)setCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate + zoomLevel:(double)zoomLevel + animated:(BOOL)animated + mapView:(AIRMap *)mapView; + +- (MKCoordinateRegion)coordinateRegionWithMapView:(AIRMap *)mapView + centerCoordinate:(CLLocationCoordinate2D)centerCoordinate + andZoomLevel:(double)zoomLevel; +- (double) zoomLevel:(AIRMap *)mapView; + @end diff --git a/lib/ios/AirMaps/AIRMapManager.m b/lib/ios/AirMaps/AIRMapManager.m index 619142bd6..8ea247244 100644 --- a/lib/ios/AirMaps/AIRMapManager.m +++ b/lib/ios/AirMaps/AIRMapManager.m @@ -97,6 +97,9 @@ - (UIView *)view RCT_EXPORT_VIEW_PROPERTY(onMarkerDragEnd, RCTDirectEventBlock) RCT_EXPORT_VIEW_PROPERTY(onCalloutPress, RCTDirectEventBlock) RCT_EXPORT_VIEW_PROPERTY(initialRegion, MKCoordinateRegion) +RCT_EXPORT_VIEW_PROPERTY(minZoomLevel, CGFloat) +RCT_EXPORT_VIEW_PROPERTY(maxZoomLevel, CGFloat) + RCT_CUSTOM_VIEW_PROPERTY(region, MKCoordinateRegion, AIRMap) { @@ -625,11 +628,19 @@ - (void)mapView:(AIRMap *)mapView regionWillChangeAnimated:(__unused BOOL)animat - (void)mapView:(AIRMap *)mapView regionDidChangeAnimated:(__unused BOOL)animated { + CGFloat zoomLevel = [self zoomLevel:mapView]; [mapView.regionChangeObserveTimer invalidate]; mapView.regionChangeObserveTimer = nil; [self _regionChanged:mapView]; + if (mapView.minZoomLevel != nil && zoomLevel < mapView.minZoomLevel) { + [self setCenterCoordinate:[mapView centerCoordinate] zoomLevel:mapView.minZoomLevel animated:TRUE mapView:mapView]; + } + else if (mapView.maxZoomLevel != nil && zoomLevel > mapView.maxZoomLevel) { + [self setCenterCoordinate:[mapView centerCoordinate] zoomLevel:mapView.maxZoomLevel animated:TRUE mapView:mapView]; + } + // Don't send region did change events until map has // started rendering, as these won't represent the final location if (mapView.hasStartedRendering) { @@ -665,6 +676,7 @@ - (void)_regionChanged:(AIRMap *)mapView BOOL needZoom = NO; CGFloat newLongitudeDelta = 0.0f; MKCoordinateRegion region = mapView.region; + CGFloat zoomLevel = [self zoomLevel:mapView]; // On iOS 7, it's possible that we observe invalid locations during initialization of the map. // Filter those out. if (!CLLocationCoordinate2DIsValid(region.center)) { @@ -759,4 +771,161 @@ - (double)metersFromPixel:(NSUInteger)px atPoint:(CGPoint)pt forMap:(AIRMap *)ma return MKMetersBetweenMapPoints(MKMapPointForCoordinate(coordA), MKMapPointForCoordinate(coordB)); } ++ (double)longitudeToPixelSpaceX:(double)longitude +{ + return round(MERCATOR_OFFSET + MERCATOR_RADIUS * longitude * M_PI / 180.0); +} + ++ (double)latitudeToPixelSpaceY:(double)latitude +{ + if (latitude == 90.0) { + return 0; + } else if (latitude == -90.0) { + return MERCATOR_OFFSET * 2; + } else { + return round(MERCATOR_OFFSET - MERCATOR_RADIUS * logf((1 + sinf(latitude * M_PI / 180.0)) / (1 - sinf(latitude * M_PI / 180.0))) / 2.0); + } +} + ++ (double)pixelSpaceXToLongitude:(double)pixelX +{ + return ((round(pixelX) - MERCATOR_OFFSET) / MERCATOR_RADIUS) * 180.0 / M_PI; +} + ++ (double)pixelSpaceYToLatitude:(double)pixelY +{ + return (M_PI / 2.0 - 2.0 * atan(exp((round(pixelY) - MERCATOR_OFFSET) / MERCATOR_RADIUS))) * 180.0 / M_PI; +} + +#pragma mark - +#pragma mark Helper methods + +- (MKCoordinateSpan)coordinateSpanWithMapView:(AIRMap *)mapView + centerCoordinate:(CLLocationCoordinate2D)centerCoordinate + andZoomLevel:(double)zoomLevel +{ + // convert center coordiate to pixel space + double centerPixelX = [AIRMapManager longitudeToPixelSpaceX:centerCoordinate.longitude]; + double centerPixelY = [AIRMapManager latitudeToPixelSpaceY:centerCoordinate.latitude]; + + // determine the scale value from the zoom level + double zoomExponent = 20 - zoomLevel; + double zoomScale = pow(2, zoomExponent); + + // scale the map’s size in pixel space + CGSize mapSizeInPixels = mapView.bounds.size; + double scaledMapWidth = mapSizeInPixels.width * zoomScale; + double scaledMapHeight = mapSizeInPixels.height * zoomScale; + + // figure out the position of the top-left pixel + double topLeftPixelX = centerPixelX - (scaledMapWidth / 2); + double topLeftPixelY = centerPixelY - (scaledMapHeight / 2); + + // find delta between left and right longitudes + CLLocationDegrees minLng = [AIRMapManager pixelSpaceXToLongitude:topLeftPixelX]; + CLLocationDegrees maxLng = [AIRMapManager pixelSpaceXToLongitude:topLeftPixelX + scaledMapWidth]; + CLLocationDegrees longitudeDelta = maxLng - minLng; + + // find delta between top and bottom latitudes + CLLocationDegrees minLat = [AIRMapManager pixelSpaceYToLatitude:topLeftPixelY]; + CLLocationDegrees maxLat = [AIRMapManager pixelSpaceYToLatitude:topLeftPixelY + scaledMapHeight]; + CLLocationDegrees latitudeDelta = -1 * (maxLat - minLat); + + // create and return the lat/lng span + MKCoordinateSpan span = MKCoordinateSpanMake(latitudeDelta, longitudeDelta); + return span; +} + +#pragma mark - +#pragma mark Public methods + +- (void)setCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate + zoomLevel:(double)zoomLevel + animated:(BOOL)animated + mapView:(AIRMap *)mapView +{ + // clamp large numbers to 28 + zoomLevel = MIN(zoomLevel, 28); + + // use the zoom level to compute the region + MKCoordinateSpan span = [self coordinateSpanWithMapView:mapView centerCoordinate:centerCoordinate andZoomLevel:zoomLevel]; + MKCoordinateRegion region = MKCoordinateRegionMake(centerCoordinate, span); + + // set the region like normal + [mapView setRegion:region animated:animated]; +} + +//KMapView cannot display tiles that cross the pole (as these would involve wrapping the map from top to bottom, something that a Mercator projection just cannot do). +-(MKCoordinateRegion)coordinateRegionWithMapView:(AIRMap *)mapView + centerCoordinate:(CLLocationCoordinate2D)centerCoordinate + andZoomLevel:(double)zoomLevel +{ + // clamp lat/long values to appropriate ranges + centerCoordinate.latitude = MIN(MAX(-90.0, centerCoordinate.latitude), 90.0); + centerCoordinate.longitude = fmod(centerCoordinate.longitude, 180.0); + + // convert center coordiate to pixel space + double centerPixelX = [AIRMapManager longitudeToPixelSpaceX:centerCoordinate.longitude]; + double centerPixelY = [AIRMapManager latitudeToPixelSpaceY:centerCoordinate.latitude]; + + // determine the scale value from the zoom level + double zoomExponent = 20 - zoomLevel; + double zoomScale = pow(2, zoomExponent); + + // scale the map’s size in pixel space + CGSize mapSizeInPixels = mapView.bounds.size; + double scaledMapWidth = mapSizeInPixels.width * zoomScale; + double scaledMapHeight = mapSizeInPixels.height * zoomScale; + + // figure out the position of the left pixel + double topLeftPixelX = centerPixelX - (scaledMapWidth / 2); + + // find delta between left and right longitudes + CLLocationDegrees minLng = [AIRMapManager pixelSpaceXToLongitude:topLeftPixelX]; + CLLocationDegrees maxLng = [AIRMapManager pixelSpaceXToLongitude:topLeftPixelX + scaledMapWidth]; + CLLocationDegrees longitudeDelta = maxLng - minLng; + + // if we’re at a pole then calculate the distance from the pole towards the equator + // as MKMapView doesn’t like drawing boxes over the poles + double topPixelY = centerPixelY - (scaledMapHeight / 2); + double bottomPixelY = centerPixelY + (scaledMapHeight / 2); + BOOL adjustedCenterPoint = NO; + if (topPixelY > MERCATOR_OFFSET * 2) { + topPixelY = centerPixelY - scaledMapHeight; + bottomPixelY = MERCATOR_OFFSET * 2; + adjustedCenterPoint = YES; + } + + // find delta between top and bottom latitudes + CLLocationDegrees minLat = [AIRMapManager pixelSpaceYToLatitude:topPixelY]; + CLLocationDegrees maxLat = [AIRMapManager pixelSpaceYToLatitude:bottomPixelY]; + CLLocationDegrees latitudeDelta = -1 * (maxLat - minLat); + + // create and return the lat/lng span + MKCoordinateSpan span = MKCoordinateSpanMake(latitudeDelta, longitudeDelta); + MKCoordinateRegion region = MKCoordinateRegionMake(centerCoordinate, span); + // once again, MKMapView doesn’t like drawing boxes over the poles + // so adjust the center coordinate to the center of the resulting region + if (adjustedCenterPoint) { + region.center.latitude = [AIRMapManager pixelSpaceYToLatitude:((bottomPixelY + topPixelY) / 2.0)]; + } + + return region; +} + +- (double) zoomLevel:(AIRMap *)mapView { + MKCoordinateRegion region = mapView.region; + + double centerPixelX = [AIRMapManager longitudeToPixelSpaceX: region.center.longitude]; + double topLeftPixelX = [AIRMapManager longitudeToPixelSpaceX: region.center.longitude - region.span.longitudeDelta / 2]; + + double scaledMapWidth = (centerPixelX - topLeftPixelX) * 2; + CGSize mapSizeInPixels = mapView.bounds.size; + double zoomScale = scaledMapWidth / mapSizeInPixels.width; + double zoomExponent = log(zoomScale) / log(2); + double zoomLevel = 20 - zoomExponent; + + return zoomLevel; +} + @end From 8a86e9899dc5674516e5fea374ae307d59732bdc Mon Sep 17 00:00:00 2001 From: Yann Pringault Date: Thu, 6 Jul 2017 18:26:40 +0200 Subject: [PATCH 0278/1148] Add onMapReady callback (#1369) * Add onMapReady callback Fix #246 * Call onMapReady when state has changed * Add onMapReady callback on iOS --- docs/mapview.md | 1 + lib/components/MapView.js | 11 +++++++++-- lib/ios/AirGoogleMaps/AIRGoogleMap.h | 2 ++ lib/ios/AirGoogleMaps/AIRGoogleMap.m | 4 ++++ lib/ios/AirGoogleMaps/AIRGoogleMapManager.m | 6 ++++++ lib/ios/AirMaps/AIRMap.h | 1 + lib/ios/AirMaps/AIRMapManager.m | 3 +++ 7 files changed, 26 insertions(+), 2 deletions(-) diff --git a/docs/mapview.md b/docs/mapview.md index 3df5640c3..e8b86aee6 100644 --- a/docs/mapview.md +++ b/docs/mapview.md @@ -40,6 +40,7 @@ To access event data, you will need to use `e.nativeEvent`. For example, `onPres | Event Name | Returns | Notes |---|---|---| +| `onMapReady` | | Callback that is called once the map is fully loaded. | `onRegionChange` | `Region` | Callback that is called continuously when the region changes, such as when a user is dragging the map. | `onRegionChangeComplete` | `Region` | Callback that is called once when the region changes, such as when the user is done moving the map. | `onPress` | `{ coordinate: LatLng, position: Point }` | Callback that is called when user taps on the map. diff --git a/lib/components/MapView.js b/lib/components/MapView.js index 2e8ba4e84..e3763f8f3 100644 --- a/lib/components/MapView.js +++ b/lib/components/MapView.js @@ -318,6 +318,11 @@ const propTypes = { */ legalLabelInsets: EdgeInsetsPropType, + /** + * Callback that is called once the map is fully loaded. + */ + onMapReady: PropTypes.func, + /** * Callback that is called continuously when the user is dragging the map. */ @@ -441,14 +446,16 @@ class MapView extends React.Component { } _onMapReady() { - const { region, initialRegion } = this.props; + const { region, initialRegion, onMapReady } = this.props; if (region) { this.map.setNativeProps({ region }); } else if (initialRegion) { this.map.setNativeProps({ region: initialRegion }); } this._updateStyle(); - this.setState({ isReady: true }); + this.setState({ isReady: true }, () => { + if (onMapReady) onMapReady(); + }); } _onLayout(e) { diff --git a/lib/ios/AirGoogleMaps/AIRGoogleMap.h b/lib/ios/AirGoogleMaps/AIRGoogleMap.h index 0e9554eb6..0d47b72b1 100644 --- a/lib/ios/AirGoogleMaps/AIRGoogleMap.h +++ b/lib/ios/AirGoogleMaps/AIRGoogleMap.h @@ -18,6 +18,7 @@ @property (nonatomic, assign) MKCoordinateRegion initialRegion; @property (nonatomic, assign) MKCoordinateRegion region; @property (nonatomic, assign) NSString *customMapStyleString; +@property (nonatomic, copy) RCTBubblingEventBlock onMapReady; @property (nonatomic, copy) RCTBubblingEventBlock onPress; @property (nonatomic, copy) RCTBubblingEventBlock onLongPress; @property (nonatomic, copy) RCTBubblingEventBlock onMarkerPress; @@ -40,6 +41,7 @@ @property (nonatomic, assign) BOOL showsUserLocation; @property (nonatomic, assign) BOOL showsMyLocationButton; +- (void)didFinishTileRendering; - (BOOL)didTapMarker:(GMSMarker *)marker; - (void)didTapPolyline:(GMSPolyline *)polyline; - (void)didTapPolygon:(GMSPolygon *)polygon; diff --git a/lib/ios/AirGoogleMaps/AIRGoogleMap.m b/lib/ios/AirGoogleMaps/AIRGoogleMap.m index f87d34c63..48b5ff446 100644 --- a/lib/ios/AirGoogleMaps/AIRGoogleMap.m +++ b/lib/ios/AirGoogleMaps/AIRGoogleMap.m @@ -155,6 +155,10 @@ - (void)setRegion:(MKCoordinateRegion)region { self.camera = [AIRGoogleMap makeGMSCameraPositionFromMap:self andMKCoordinateRegion:region]; } +- (void)didFinishTileRendering { + if (self.onMapReady) self.onMapReady(@{}); +} + - (BOOL)didTapMarker:(GMSMarker *)marker { AIRGMSMarker *airMarker = (AIRGMSMarker *)marker; diff --git a/lib/ios/AirGoogleMaps/AIRGoogleMapManager.m b/lib/ios/AirGoogleMaps/AIRGoogleMapManager.m index c482305b8..53157e99a 100644 --- a/lib/ios/AirGoogleMaps/AIRGoogleMapManager.m +++ b/lib/ios/AirGoogleMaps/AIRGoogleMapManager.m @@ -59,6 +59,7 @@ - (UIView *)view RCT_EXPORT_VIEW_PROPERTY(showsUserLocation, BOOL) RCT_EXPORT_VIEW_PROPERTY(showsMyLocationButton, BOOL) RCT_EXPORT_VIEW_PROPERTY(customMapStyleString, NSString) +RCT_EXPORT_VIEW_PROPERTY(onMapReady, RCTBubblingEventBlock) RCT_EXPORT_VIEW_PROPERTY(onPress, RCTBubblingEventBlock) RCT_EXPORT_VIEW_PROPERTY(onLongPress, RCTBubblingEventBlock) RCT_EXPORT_VIEW_PROPERTY(onChange, RCTBubblingEventBlock) @@ -222,6 +223,11 @@ - (UIView *)view } +- (void)mapViewDidFinishTileRendering:(GMSMapView *)mapView { + AIRGoogleMap *googleMapView = (AIRGoogleMap *)mapView; + [googleMapView didFinishTileRendering]; +} + - (BOOL)mapView:(GMSMapView *)mapView didTapMarker:(GMSMarker *)marker { AIRGoogleMap *googleMapView = (AIRGoogleMap *)mapView; return [googleMapView didTapMarker:marker]; diff --git a/lib/ios/AirMaps/AIRMap.h b/lib/ios/AirMaps/AIRMap.h index 4a88617e6..48a07ddb2 100644 --- a/lib/ios/AirMaps/AIRMap.h +++ b/lib/ios/AirMaps/AIRMap.h @@ -46,6 +46,7 @@ extern const CGFloat AIRMapZoomBoundBuffer; @property (nonatomic, assign) BOOL ignoreRegionChanges; +@property (nonatomic, copy) RCTBubblingEventBlock onMapReady; @property (nonatomic, copy) RCTBubblingEventBlock onChange; @property (nonatomic, copy) RCTBubblingEventBlock onPress; @property (nonatomic, copy) RCTBubblingEventBlock onPanDrag; diff --git a/lib/ios/AirMaps/AIRMapManager.m b/lib/ios/AirMaps/AIRMapManager.m index 8ea247244..e99249ace 100644 --- a/lib/ios/AirMaps/AIRMapManager.m +++ b/lib/ios/AirMaps/AIRMapManager.m @@ -85,6 +85,7 @@ - (UIView *)view RCT_EXPORT_VIEW_PROPERTY(minDelta, CGFloat) RCT_EXPORT_VIEW_PROPERTY(legalLabelInsets, UIEdgeInsets) RCT_EXPORT_VIEW_PROPERTY(mapType, MKMapType) +RCT_EXPORT_VIEW_PROPERTY(onMapReady, RCTBubblingEventBlock) RCT_EXPORT_VIEW_PROPERTY(onChange, RCTBubblingEventBlock) RCT_EXPORT_VIEW_PROPERTY(onPanDrag, RCTBubblingEventBlock) RCT_EXPORT_VIEW_PROPERTY(onPress, RCTBubblingEventBlock) @@ -662,6 +663,8 @@ - (void)mapViewDidFinishRenderingMap:(AIRMap *)mapView fullyRendered:(BOOL)fully { [mapView finishLoading]; [mapView cacheViewIfNeeded]; + + mapView.onMapReady(@{}); } #pragma mark Private From 3202602d2becb1a0cfeea2e8ca839d6f5cb0c82d Mon Sep 17 00:00:00 2001 From: Frank Rowe Date: Thu, 6 Jul 2017 12:27:22 -0400 Subject: [PATCH 0279/1148] add MKTileOverlayRenderer (#1357) --- lib/ios/AirMaps/AIRMapManager.m | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/ios/AirMaps/AIRMapManager.m b/lib/ios/AirMaps/AIRMapManager.m index e99249ace..41b124aae 100644 --- a/lib/ios/AirMaps/AIRMapManager.m +++ b/lib/ios/AirMaps/AIRMapManager.m @@ -482,6 +482,8 @@ - (MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id Date: Tue, 18 Jul 2017 16:41:52 +1000 Subject: [PATCH 0280/1148] Handle Android RN 0.47 breaking change (#1481) --- .../main/java/com/airbnb/android/react/maps/MapsPackage.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/MapsPackage.java b/lib/android/src/main/java/com/airbnb/android/react/maps/MapsPackage.java index da59849b3..6ecc55165 100644 --- a/lib/android/src/main/java/com/airbnb/android/react/maps/MapsPackage.java +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/MapsPackage.java @@ -24,7 +24,7 @@ public List createNativeModules(ReactApplicationContext reactConte return Arrays.asList(new AirMapModule(reactContext)); } - @Override + // Deprecated RN 0.47 public List> createJSModules() { return Collections.emptyList(); } From 32350e26cf7c2be6031dbabf23b8e27cd7269c00 Mon Sep 17 00:00:00 2001 From: Sagi Kedmi Date: Sun, 23 Jul 2017 12:46:57 +0300 Subject: [PATCH 0281/1148] Remove caret from "react": "^16.0.0-alpha.12" `npm install` / `yarn install` auto updates to `16.0.0-alpha.13` which breaks the proptypes import. Removing caret to prevent auto update to `alpha.13`. For more information: https://github.com/facebook/react-native/issues/14454 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7cb48301b..332063dbb 100644 --- a/package.json +++ b/package.json @@ -50,7 +50,7 @@ "gitbook-cli": "^2.3.0", "lodash": "^4.17.2", "prop-types": "^15.5.10", - "react": "^16.0.0-alpha.12", + "react": "16.0.0-alpha.12", "react-native": "^0.45.1" }, "rnpm": { From 7f182ddc9c209bd9f9dbd27f7f93c5e5f14e6a5e Mon Sep 17 00:00:00 2001 From: Mike Lambert Date: Thu, 27 Jul 2017 12:49:18 -0400 Subject: [PATCH 0282/1148] Attempt to fix crashes. A variant of https://github.com/airbnb/react-native-maps/pull/1403 but for another lifecycle method, as proposed by @Nelrohd. (#1464) --- .../main/java/com/airbnb/android/react/maps/AirMapView.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java index 11e578634..c1606eebb 100644 --- a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java @@ -304,7 +304,9 @@ public void onHostResume() { map.setMyLocationEnabled(showUserLocation); } synchronized (AirMapView.this) { - AirMapView.this.onResume(); + if (!destroyed) { + AirMapView.this.onResume(); + } paused = false; } } From dd1b8aa9499769dda008cbba464ea9b7a5c21369 Mon Sep 17 00:00:00 2001 From: Benjamin Dobell Date: Fri, 28 Jul 2017 02:50:59 +1000 Subject: [PATCH 0283/1148] Zoom level fixes (#1485) --- lib/ios/AirMaps/AIRMap.h | 1 + lib/ios/AirMaps/AIRMap.m | 4 ++++ lib/ios/AirMaps/AIRMapManager.h | 1 - lib/ios/AirMaps/AIRMapManager.m | 12 ++++++------ 4 files changed, 11 insertions(+), 7 deletions(-) diff --git a/lib/ios/AirMaps/AIRMap.h b/lib/ios/AirMaps/AIRMap.h index 48a07ddb2..1d5f92cdc 100644 --- a/lib/ios/AirMaps/AIRMap.h +++ b/lib/ios/AirMaps/AIRMap.h @@ -17,6 +17,7 @@ extern const CLLocationDegrees AIRMapDefaultSpan; extern const NSTimeInterval AIRMapRegionChangeObserveInterval; extern const CGFloat AIRMapZoomBoundBuffer; +extern const NSInteger AIRMapMaxZoomLevel; @interface AIRMap: MKMapView diff --git a/lib/ios/AirMaps/AIRMap.m b/lib/ios/AirMaps/AIRMap.m index a9db64ab4..647be4b8a 100644 --- a/lib/ios/AirMaps/AIRMap.m +++ b/lib/ios/AirMaps/AIRMap.m @@ -21,6 +21,7 @@ const CLLocationDegrees AIRMapDefaultSpan = 0.005; const NSTimeInterval AIRMapRegionChangeObserveInterval = 0.1; const CGFloat AIRMapZoomBoundBuffer = 0.01; +const NSInteger AIRMapMaxZoomLevel = 20; @interface MKMapView (UIGestureRecognizer) @@ -79,6 +80,9 @@ - (instancetype)init // be identical to the built-in callout view (which has a private API) self.calloutView = [SMCalloutView platformCalloutView]; self.calloutView.delegate = self; + + self.minZoomLevel = 0; + self.maxZoomLevel = AIRMapMaxZoomLevel; } return self; } diff --git a/lib/ios/AirMaps/AIRMapManager.h b/lib/ios/AirMaps/AIRMapManager.h index 29df98bfc..1d73b405e 100644 --- a/lib/ios/AirMaps/AIRMapManager.h +++ b/lib/ios/AirMaps/AIRMapManager.h @@ -12,7 +12,6 @@ #define MERCATOR_RADIUS 85445659.44705395 #define MERCATOR_OFFSET 268435456 -#define MAX_GOOGLE_LEVELS 20 @interface AIRMapManager : RCTViewManager diff --git a/lib/ios/AirMaps/AIRMapManager.m b/lib/ios/AirMaps/AIRMapManager.m index 41b124aae..76aef88fe 100644 --- a/lib/ios/AirMaps/AIRMapManager.m +++ b/lib/ios/AirMaps/AIRMapManager.m @@ -637,10 +637,10 @@ - (void)mapView:(AIRMap *)mapView regionDidChangeAnimated:(__unused BOOL)animate [self _regionChanged:mapView]; - if (mapView.minZoomLevel != nil && zoomLevel < mapView.minZoomLevel) { + if (zoomLevel < mapView.minZoomLevel) { [self setCenterCoordinate:[mapView centerCoordinate] zoomLevel:mapView.minZoomLevel animated:TRUE mapView:mapView]; } - else if (mapView.maxZoomLevel != nil && zoomLevel > mapView.maxZoomLevel) { + else if (zoomLevel > mapView.maxZoomLevel) { [self setCenterCoordinate:[mapView centerCoordinate] zoomLevel:mapView.maxZoomLevel animated:TRUE mapView:mapView]; } @@ -814,7 +814,7 @@ - (MKCoordinateSpan)coordinateSpanWithMapView:(AIRMap *)mapView double centerPixelY = [AIRMapManager latitudeToPixelSpaceY:centerCoordinate.latitude]; // determine the scale value from the zoom level - double zoomExponent = 20 - zoomLevel; + double zoomExponent = AIRMapMaxZoomLevel - zoomLevel; double zoomScale = pow(2, zoomExponent); // scale the map’s size in pixel space @@ -850,7 +850,7 @@ - (void)setCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate mapView:(AIRMap *)mapView { // clamp large numbers to 28 - zoomLevel = MIN(zoomLevel, 28); + zoomLevel = MIN(zoomLevel, AIRMapMaxZoomLevel); // use the zoom level to compute the region MKCoordinateSpan span = [self coordinateSpanWithMapView:mapView centerCoordinate:centerCoordinate andZoomLevel:zoomLevel]; @@ -874,7 +874,7 @@ -(MKCoordinateRegion)coordinateRegionWithMapView:(AIRMap *)mapView double centerPixelY = [AIRMapManager latitudeToPixelSpaceY:centerCoordinate.latitude]; // determine the scale value from the zoom level - double zoomExponent = 20 - zoomLevel; + double zoomExponent = AIRMapMaxZoomLevel - zoomLevel; double zoomScale = pow(2, zoomExponent); // scale the map’s size in pixel space @@ -928,7 +928,7 @@ - (double) zoomLevel:(AIRMap *)mapView { CGSize mapSizeInPixels = mapView.bounds.size; double zoomScale = scaledMapWidth / mapSizeInPixels.width; double zoomExponent = log(zoomScale) / log(2); - double zoomLevel = 20 - zoomExponent; + double zoomLevel = AIRMapMaxZoomLevel - zoomExponent; return zoomLevel; } From db0d617c0e13a549c5d99b1758a00b6988db6e7b Mon Sep 17 00:00:00 2001 From: Matt Shen Date: Fri, 28 Jul 2017 02:54:50 +1000 Subject: [PATCH 0284/1148] skip region monitoring if map object is null (#1443) This happen if google play services version is lower than required --- .../main/java/com/airbnb/android/react/maps/AirMapView.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java index c1606eebb..cfe581bd0 100644 --- a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java @@ -701,13 +701,13 @@ public boolean dispatchTouchEvent(MotionEvent ev) { // Timer Implementation public void startMonitoringRegion() { - if (isMonitoringRegion) return; + if (map == null || isMonitoringRegion) return; timerHandler.postDelayed(timerRunnable, 100); isMonitoringRegion = true; } public void stopMonitoringRegion() { - if (!isMonitoringRegion) return; + if (map == null || !isMonitoringRegion) return; timerHandler.removeCallbacks(timerRunnable); isMonitoringRegion = false; } From 3235a341ccb74f1b156ee19eed69656ff5de40d0 Mon Sep 17 00:00:00 2001 From: Nikolay Radkov Date: Thu, 27 Jul 2017 19:57:19 +0300 Subject: [PATCH 0285/1148] Fix crashing the application when a user presses on the map and the Google Play Services need to be updated or at the moment of the process of updating (#1469) --- .../airbnb/android/react/maps/AirMapView.java | 24 ++++++++++--------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java index cfe581bd0..c8b016ce1 100644 --- a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java @@ -720,18 +720,20 @@ public void stopMonitoringRegion() { @Override public void run() { - Projection projection = map.getProjection(); - VisibleRegion region = (projection != null) ? projection.getVisibleRegion() : null; - LatLngBounds bounds = (region != null) ? region.latLngBounds : null; - - if ((bounds != null) && - (lastBoundsEmitted == null || - LatLngBoundsUtils.BoundsAreDifferent(bounds, lastBoundsEmitted))) { - LatLng center = map.getCameraPosition().target; - lastBoundsEmitted = bounds; - eventDispatcher.dispatchEvent(new RegionChangeEvent(getId(), bounds, center, true)); + if (map != null) { + Projection projection = map.getProjection(); + VisibleRegion region = (projection != null) ? projection.getVisibleRegion() : null; + LatLngBounds bounds = (region != null) ? region.latLngBounds : null; + + if ((bounds != null) && + (lastBoundsEmitted == null || + LatLngBoundsUtils.BoundsAreDifferent(bounds, lastBoundsEmitted))) { + LatLng center = map.getCameraPosition().target; + lastBoundsEmitted = bounds; + eventDispatcher.dispatchEvent(new RegionChangeEvent(getId(), bounds, center, true)); + } } - + timerHandler.postDelayed(this, 100); } }; From 28388a73e209ae30083e466dd3dc64fe1c441d2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20B=C3=B8ving?= Date: Thu, 27 Jul 2017 19:10:06 +0200 Subject: [PATCH 0286/1148] Fix timing function used in AnimatedRegion.spring (#1479) --- lib/components/AnimatedRegion.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/components/AnimatedRegion.js b/lib/components/AnimatedRegion.js index 29356ca9e..ad18c5e07 100644 --- a/lib/components/AnimatedRegion.js +++ b/lib/components/AnimatedRegion.js @@ -111,25 +111,25 @@ export default class AnimatedMapRegion extends AnimatedWithChildren { spring(config) { var animations = []; config.hasOwnProperty('latitude') && - animations.push(Animated.timing(this.latitude, { + animations.push(Animated.spring(this.latitude, { ...config, toValue: config.latitude })); config.hasOwnProperty('longitude') && - animations.push(Animated.timing(this.longitude, { + animations.push(Animated.spring(this.longitude, { ...config, toValue: config.longitude })); config.hasOwnProperty('latitudeDelta') && - animations.push(Animated.timing(this.latitudeDelta, { + animations.push(Animated.spring(this.latitudeDelta, { ...config, toValue: config.latitudeDelta })); config.hasOwnProperty('longitudeDelta') && - animations.push(Animated.timing(this.longitudeDelta, { + animations.push(Animated.spring(this.longitudeDelta, { ...config, toValue: config.longitudeDelta })); From 80a570e26bf479af0fbe4c106480440ac332637f Mon Sep 17 00:00:00 2001 From: Matt Shen Date: Tue, 1 Aug 2017 15:49:28 +1000 Subject: [PATCH 0287/1148] fix rare android crashes when map size is 0 --- .../airbnb/android/react/maps/AirMapView.java | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java index c8b016ce1..bc52506cf 100644 --- a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java @@ -541,16 +541,17 @@ public void updateExtraData(Object extraData) { // a proper camera move if (boundsToMove != null) { HashMap data = (HashMap) extraData; - float width = data.get("width"); - float height = data.get("height"); - map.moveCamera( - CameraUpdateFactory.newLatLngBounds( - boundsToMove, - (int) width, - (int) height, - 0 - ) - ); + int width = data.get("width") == null ? 0 : data.get("width").intValue(); + int height = data.get("height") == null ? 0 : data.get("height").intValue(); + + //fix for https://github.com/airbnb/react-native-maps/issues/245, + //it's not guaranteed the passed-in height and width would be greater than 0. + if (width <= 0 || height <= 0) { + map.moveCamera(CameraUpdateFactory.newLatLngBounds(boundsToMove, 0)); + } else { + map.moveCamera(CameraUpdateFactory.newLatLngBounds(boundsToMove, width, height, 0)); + } + boundsToMove = null; } } From 6357776523cf1d423f8d579b079bdfdecb7b24e6 Mon Sep 17 00:00:00 2001 From: Andre Shonubi Date: Wed, 9 Aug 2017 17:53:45 -0400 Subject: [PATCH 0288/1148] Document MapView min/max zoom properties (#1538) --- docs/mapview.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/mapview.md b/docs/mapview.md index e8b86aee6..a73e123b8 100644 --- a/docs/mapview.md +++ b/docs/mapview.md @@ -22,6 +22,8 @@ | `showsIndoors` | `Boolean` | `true` | A Boolean indicating whether indoor maps should be enabled. | `showsIndoorLevelPicker` | `Boolean` | `false` | A Boolean indicating whether indoor level picker should be enabled. **Note:** Android only. | `zoomEnabled` | `Boolean` | `true` | If `false` the user won't be able to pinch/zoom the map. +| `minZoomLevel` | `Number` | `0` | Minimum zoom value for the map, must be between 0 and 20 +| `maxZoomLevel` | `Number` | `20` | Maximum zoom value for the map, must be between 0 and 20 | `rotateEnabled` | `Boolean` | `true` | If `false` the user won't be able to pinch/rotate the map. | `scrollEnabled` | `Boolean` | `true` | If `false` the user won't be able to change the map region being displayed. | `pitchEnabled` | `Boolean` | `true` | If `false` the user won't be able to adjust the camera’s pitch angle. From 4cc4e45f6275ade05c7e0da3141e4a5d3983b6dc Mon Sep 17 00:00:00 2001 From: Christopher Dro Date: Wed, 9 Aug 2017 15:07:10 -0700 Subject: [PATCH 0289/1148] v0.16.0 --- CHANGELOG.md | 7 +++++++ lib/android/gradle.properties | 2 +- package.json | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 50b2027bc..45c5bd082 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Change Log +## 0.16.0 (August 9, 2017) +* Android: [#1481](https://github.com/airbnb/react-native-maps/pull/#1481) Handle Android RN 0.47 breaking change +* iOS: [#1357](https://github.com/airbnb/react-native-maps/pull/1357) add MKTileOverlayRenderer +* iOS: [#1369](https://github.com/airbnb/react-native-maps/pull/1369) Add onMapReady callback +* Android/iOS/JS: [#1360](https://github.com/airbnb/react-native-maps/pull/1360) Add minZoom and maxZoom properties for android and ios +* JS: [#1479](https://github.com/airbnb/react-native-maps/pull/1479) Fix timing function used in AnimatedRegion.spring + ## 0.15.3 (June 27, 2017) * iOS: [#1362](https://github.com/airbnb/react-native-maps/pull/1362) Updates for React 0.43-0.45 and React 16. diff --git a/lib/android/gradle.properties b/lib/android/gradle.properties index 1a5d3021b..ddc39b69d 100644 --- a/lib/android/gradle.properties +++ b/lib/android/gradle.properties @@ -1,5 +1,5 @@ VERSION_CODE=4 -VERSION_NAME=0.15.3 +VERSION_NAME=0.16.0 GROUP=com.airbnb.android POM_DESCRIPTION=React Native Map view component for Android diff --git a/package.json b/package.json index 7cb48301b..408db6b03 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "description": "React Native Mapview component for iOS + Android", "main": "index.js", "author": "Leland Richardson ", - "version": "0.15.3", + "version": "0.16.0", "scripts": { "start": "node node_modules/react-native/local-cli/cli.js start", "run:packager": "./node_modules/react-native/packager/packager.sh", From 7006e3afee2cb82e20a1bd3c10ce5e163a3c448c Mon Sep 17 00:00:00 2001 From: sandinosaso Date: Fri, 11 Aug 2017 00:43:08 -0300 Subject: [PATCH 0290/1148] Adds support to animateToBearing and animateToViewingAngle functions on IOS. --- docs/mapview.md | 2 ++ example/examples/DisplayLatLng.js | 24 ++++++++++++++ lib/components/MapView.js | 8 +++++ lib/ios/AirGoogleMaps/AIRGoogleMapManager.m | 36 +++++++++++++++++++++ 4 files changed, 70 insertions(+) diff --git a/docs/mapview.md b/docs/mapview.md index a73e123b8..8cc1d8291 100644 --- a/docs/mapview.md +++ b/docs/mapview.md @@ -64,6 +64,8 @@ To access event data, you will need to use `e.nativeEvent`. For example, `onPres |---|---|---| | `animateToRegion` | `region: Region`, `duration: Number` | | `animateToCoordinate` | `coordinate: LatLng`, `duration: Number` | +| `animateToBearing` | `bearing: Number`, `duration: Number` | +| `animateToViewingAngle` | `angle: Number`, `duration: Number` | | `fitToElements` | `animated: Boolean` | | `fitToSuppliedMarkers` | `markerIDs: String[]`, `animated: Boolean` | If you need to use this in `ComponentDidMount`, make sure you put it in a timeout or it will cause performance problems. | `fitToCoordinates` | `coordinates: Array, options: { edgePadding: EdgePadding, animated: Boolean }` | If called in `ComponentDidMount` in android, it will cause an exception. It is recommended to call it from the MapView `onLayout` event. diff --git a/example/examples/DisplayLatLng.js b/example/examples/DisplayLatLng.js index aa2dde2ac..688427b35 100644 --- a/example/examples/DisplayLatLng.js +++ b/example/examples/DisplayLatLng.js @@ -47,6 +47,18 @@ class DisplayLatLng extends React.Component { this.map.animateToCoordinate(this.randomCoordinate()); } + animateToRandomBearing() { + this.map.animateToBearing(this.getRandomFloat(-360, 360)); + } + + animateToRandomViewingAngle() { + this.map.animateToViewingAngle(this.getRandomFloat(0, 90)); + } + + getRandomFloat(min, max) { + return (Math.random() * (max - min)) + min; + } + randomCoordinate() { const region = this.state.region; return { @@ -98,6 +110,18 @@ class DisplayLatLng extends React.Component { > Animate (Coordinate) + this.animateToRandomBearing()} + style={[styles.bubble, styles.button]} + > + Animate (Bearing) + + this.animateToRandomViewingAngle()} + style={[styles.bubble, styles.button]} + > + Animate (View Angle) + ); diff --git a/lib/components/MapView.js b/lib/components/MapView.js index e3763f8f3..19256b85c 100644 --- a/lib/components/MapView.js +++ b/lib/components/MapView.js @@ -492,6 +492,14 @@ class MapView extends React.Component { this._runCommand('animateToCoordinate', [latLng, duration || 500]); } + animateToBearing(bearing, duration) { + this._runCommand('animateToBearing', [bearing, duration || 500]); + } + + animateToViewingAngle(angle, duration) { + this._runCommand('animateToViewingAngle', [angle, duration || 500]); + } + fitToElements(animated) { this._runCommand('fitToElements', [animated]); } diff --git a/lib/ios/AirGoogleMaps/AIRGoogleMapManager.m b/lib/ios/AirGoogleMaps/AIRGoogleMapManager.m index 53157e99a..c1531b5a7 100644 --- a/lib/ios/AirGoogleMaps/AIRGoogleMapManager.m +++ b/lib/ios/AirGoogleMaps/AIRGoogleMapManager.m @@ -108,6 +108,42 @@ - (UIView *)view }]; } +RCT_EXPORT_METHOD(animateToViewingAngle:(nonnull NSNumber *)reactTag + withAngle:(double)angle + withDuration:(CGFloat)duration) +{ + [self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary *viewRegistry) { + id view = viewRegistry[reactTag]; + if (![view isKindOfClass:[AIRGoogleMap class]]) { + RCTLogError(@"Invalid view returned from registry, expecting AIRGoogleMap, got: %@", view); + } else { + [CATransaction begin]; + [CATransaction setAnimationDuration:duration/1000]; + AIRGoogleMap *mapView = (AIRGoogleMap *)view; + [mapView animateToViewingAngle:angle]; + [CATransaction commit]; + } + }]; +} + +RCT_EXPORT_METHOD(animateToBearing:(nonnull NSNumber *)reactTag + withBearing:(CGFloat)bearing + withDuration:(CGFloat)duration) +{ + [self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary *viewRegistry) { + id view = viewRegistry[reactTag]; + if (![view isKindOfClass:[AIRGoogleMap class]]) { + RCTLogError(@"Invalid view returned from registry, expecting AIRGoogleMap, got: %@", view); + } else { + [CATransaction begin]; + [CATransaction setAnimationDuration:duration/1000]; + AIRGoogleMap *mapView = (AIRGoogleMap *)view; + [mapView animateToBearing:bearing]; + [CATransaction commit]; + } + }]; +} + RCT_EXPORT_METHOD(fitToElements:(nonnull NSNumber *)reactTag animated:(BOOL)animated) { From c9c52ab9ccb0e8f446f457be54e04f151b6a2f47 Mon Sep 17 00:00:00 2001 From: Eugene Hauptmann Date: Tue, 15 Aug 2017 08:35:08 -0700 Subject: [PATCH 0291/1148] fix `Archive` configuration for iOS builds (#1550) --- example/ios/Podfile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/example/ios/Podfile b/example/ios/Podfile index 656f283e1..66771a383 100644 --- a/example/ios/Podfile +++ b/example/ios/Podfile @@ -36,5 +36,9 @@ post_install do |installer| config.build_settings['CLANG_ENABLE_MODULES'] = 'No' end end + + if target.name == "React" + target.remove_from_project + end end end From fd8dc08ffaa0fadbaa73d9e29033a16f808e318f Mon Sep 17 00:00:00 2001 From: foyarash Date: Tue, 15 Aug 2017 17:37:10 +0200 Subject: [PATCH 0292/1148] Fix initial region native prop (#1546) * Fix initial region bug * Remove useless change --- lib/components/MapView.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/components/MapView.js b/lib/components/MapView.js index e3763f8f3..f9b974aec 100644 --- a/lib/components/MapView.js +++ b/lib/components/MapView.js @@ -450,7 +450,7 @@ class MapView extends React.Component { if (region) { this.map.setNativeProps({ region }); } else if (initialRegion) { - this.map.setNativeProps({ region: initialRegion }); + this.map.setNativeProps({ initialRegion }); } this._updateStyle(); this.setState({ isReady: true }, () => { From b908c08ac2367652249918f4f5694eaf17a1eac2 Mon Sep 17 00:00:00 2001 From: "Wanseob (Eric) Kim" Date: Tue, 15 Aug 2017 11:35:13 -0700 Subject: [PATCH 0293/1148] Issue1176 improve ios marker performance by X100 (#1187) * Issue1176 attempt to fix UI lag success by re-using UIImage * Now use NSMutableDictionary instead of single UIImage * appearAnimation happen at init rather than setIcon * Init NSMutableDictionary * Remove reference to other app --- lib/ios/AirGoogleMaps/AIRGoogleMapMarker.m | 80 +++++----------------- lib/ios/AirGoogleMaps/GlobalVars.h | 22 ++++++ lib/ios/AirGoogleMaps/GlobalVars.m | 54 +++++++++++++++ 3 files changed, 92 insertions(+), 64 deletions(-) create mode 100644 lib/ios/AirGoogleMaps/GlobalVars.h create mode 100644 lib/ios/AirGoogleMaps/GlobalVars.m diff --git a/lib/ios/AirGoogleMaps/AIRGoogleMapMarker.m b/lib/ios/AirGoogleMaps/AIRGoogleMapMarker.m index c41be55bb..9d96dfafc 100644 --- a/lib/ios/AirGoogleMaps/AIRGoogleMapMarker.m +++ b/lib/ios/AirGoogleMaps/AIRGoogleMapMarker.m @@ -12,6 +12,7 @@ #import "AIRGMSMarker.h" #import "AIRGoogleMapCallout.h" #import "DummyView.h" +#import "GlobalVars.h" CGRect unionRect(CGRect a, CGRect b) { return CGRectMake( @@ -36,6 +37,7 @@ - (instancetype)init if ((self = [super init])) { _realMarker = [[AIRGMSMarker alloc] init]; _realMarker.fakeMarker = self; + _realMarker.appearAnimation = kGMSMarkerAnimationPop; } return self; } @@ -92,6 +94,18 @@ - (void)insertReactSubview:(id)subview atIndex:(NSInteger)atIndex [super insertReactSubview:(UIView*)dummySubview atIndex:atIndex]; } +- (void)setIcon:(UIImage*)image { + CGImageRef cgref = [image CGImage]; + CIImage *cim = [image CIImage]; + + if (cim == nil && cgref == NULL) { + // image does not contain image data + _realMarker.icon = [GMSMarker markerImageWithColor:UIColor.blueColor]; + } else { + _realMarker.icon = image; + } +} + - (void)removeReactSubview:(id)dummySubview { UIView* subview = ((DummyView*)dummySubview).view; @@ -188,70 +202,8 @@ - (void)setOpacity:(double)opacity - (void)setImageSrc:(NSString *)imageSrc { - _imageSrc = imageSrc; - - if (_reloadImageCancellationBlock) { - _reloadImageCancellationBlock(); - _reloadImageCancellationBlock = nil; - } - - if (!_imageSrc) { - if (_iconImageView) [_iconImageView removeFromSuperview]; - return; - } - - if (!_iconImageView) { - // prevent glitch with marker (cf. https://github.com/airbnb/react-native-maps/issues/738) - UIImageView *empyImageView = [[UIImageView alloc] init]; - _iconImageView = empyImageView; - [self iconViewInsertSubview:_iconImageView atIndex:0]; - } - - _reloadImageCancellationBlock = [_bridge.imageLoader loadImageWithURLRequest:[RCTConvert NSURLRequest:_imageSrc] - size:self.bounds.size - scale:RCTScreenScale() - clipped:YES - resizeMode:RCTResizeModeCenter - progressBlock:nil - partialLoadBlock:nil - completionBlock:^(NSError *error, UIImage *image) { - if (error) { - // TODO(lmr): do something with the error? - NSLog(@"%@", error); - } - dispatch_async(dispatch_get_main_queue(), ^{ - - // TODO(gil): This way allows different image sizes - if (_iconImageView) [_iconImageView removeFromSuperview]; - - // ... but this way is more efficient? -// if (_iconImageView) { -// [_iconImageView setImage:image]; -// return; -// } - - UIImageView *imageView = [[UIImageView alloc] initWithImage:image]; - - // TODO: w,h or pixel density could be a prop. - float density = 1; - float w = image.size.width/density; - float h = image.size.height/density; - CGRect bounds = CGRectMake(0, 0, w, h); - - imageView.contentMode = UIViewContentModeScaleAspectFit; - [imageView setFrame:bounds]; - - // NOTE: sizeToFit doesn't work instead. Not sure why. - // TODO: Doing it this way is not ideal because it causes things to reshuffle - // when the image loads IF the image is larger than the UIView. - // Shouldn't required images have size info automatically via RN? - CGRect selfBounds = unionRect(bounds, self.bounds); - [self setFrame:selfBounds]; - - _iconImageView = imageView; - [self iconViewInsertSubview:imageView atIndex:0]; - }); - }]; + UIImage * image = [[GlobalVars sharedInstance] getSharedUIImage:imageSrc]; + [self setIcon:image]; } - (void)setTitle:(NSString *)title { diff --git a/lib/ios/AirGoogleMaps/GlobalVars.h b/lib/ios/AirGoogleMaps/GlobalVars.h new file mode 100644 index 000000000..86c3555f7 --- /dev/null +++ b/lib/ios/AirGoogleMaps/GlobalVars.h @@ -0,0 +1,22 @@ +// +// GlobalVars.h +// +// Created by Eric Kim on 2017-04-04. +// Copyright © 2017 Apply Digital. All rights reserved. +// + +#import +#import + +@interface GlobalVars : NSObject +{ + NSMutableDictionary *dict; +} + ++ (GlobalVars *)sharedInstance; + +- (UIImage *)getSharedUIImage:(NSString *)imageSrc; + +@property(strong, nonatomic, readwrite) NSMutableDictionary *dict; + +@end diff --git a/lib/ios/AirGoogleMaps/GlobalVars.m b/lib/ios/AirGoogleMaps/GlobalVars.m new file mode 100644 index 000000000..7a541dab4 --- /dev/null +++ b/lib/ios/AirGoogleMaps/GlobalVars.m @@ -0,0 +1,54 @@ +// +// GlobalVars.m +// +// Created by Eric Kim on 2017-04-04. +// Copyright © 2017 Apply Digital. All rights reserved. +// + +#import "GlobalVars.h" + +@implementation GlobalVars + +@synthesize dict = _dict; + ++ (GlobalVars *)sharedInstance { + static dispatch_once_t onceToken; + static GlobalVars *instance = nil; + dispatch_once(&onceToken, ^{ + instance = [[GlobalVars alloc] init]; + }); + return instance; +} + +- (UIImage *)getSharedUIImage:(NSString *)imageSrc { + + UIImage* cachedImage = dict[imageSrc]; + + CGImageRef cgref = [cachedImage CGImage]; + CIImage *cim = [cachedImage CIImage]; + + if (cim == nil && cgref == NULL) { + UIImage *newImage; + if ([imageSrc hasPrefix:@"http://"] || [imageSrc hasPrefix:@"https://"]){ + NSURL *url = [NSURL URLWithString:imageSrc]; + NSData *data = [NSData dataWithContentsOfURL:url]; + newImage = [UIImage imageWithData:data scale:[UIScreen mainScreen].scale]; + } else { + newImage = [UIImage imageWithContentsOfFile:imageSrc]; + } + dict[imageSrc] = newImage; + return newImage; + } else { + return cachedImage; + } +} + +- (id)init { + self = [super init]; + if (self) { + dict = [[NSMutableDictionary alloc] init]; + } + return self; +} + +@end From 75a38eab271b83d37a7f4089de806acac1a4865d Mon Sep 17 00:00:00 2001 From: Ben Speakman Date: Tue, 15 Aug 2017 19:36:25 +0100 Subject: [PATCH 0294/1148] Add legalNotice constant (#1458) --- .../com/airbnb/android/react/maps/AirMapModule.java | 11 +++++++++++ lib/ios/AirGoogleMaps/AIRGoogleMapManager.m | 3 +++ 2 files changed, 14 insertions(+) diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapModule.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapModule.java index 1a096255e..bd1fb6ed0 100644 --- a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapModule.java +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapModule.java @@ -15,6 +15,7 @@ import com.facebook.react.uimanager.UIBlock; import com.facebook.react.uimanager.UIManagerModule; import com.google.android.gms.maps.GoogleMap; +import com.google.android.gms.common.GoogleApiAvailability; import java.io.ByteArrayOutputStream; import java.io.Closeable; @@ -22,6 +23,9 @@ import java.io.FileOutputStream; import java.io.IOException; +import java.util.Map; +import java.util.HashMap; + import javax.annotation.Nullable; public class AirMapModule extends ReactContextBaseJavaModule { @@ -40,6 +44,13 @@ public String getName() { return "AirMapModule"; } + @Override + public Map getConstants() { + final Map constants = new HashMap<>(); + constants.put("legalNotice", GoogleApiAvailability.getInstance().getOpenSourceSoftwareLicenseInfo(getReactApplicationContext())); + return constants; + } + public Activity getActivity() { return getCurrentActivity(); } diff --git a/lib/ios/AirGoogleMaps/AIRGoogleMapManager.m b/lib/ios/AirGoogleMaps/AIRGoogleMapManager.m index 53157e99a..086822b73 100644 --- a/lib/ios/AirGoogleMaps/AIRGoogleMapManager.m +++ b/lib/ios/AirGoogleMaps/AIRGoogleMapManager.m @@ -222,6 +222,9 @@ - (UIView *)view }]; } +- (NSDictionary *)constantsToExport { + return @{ @"legalNotice": [GMSServices openSourceLicenseInfo] }; +} - (void)mapViewDidFinishTileRendering:(GMSMapView *)mapView { AIRGoogleMap *googleMapView = (AIRGoogleMap *)mapView; From 971d91e522d7ad517a0d944b57c873483b78f9e2 Mon Sep 17 00:00:00 2001 From: foyarash Date: Tue, 15 Aug 2017 20:39:50 +0200 Subject: [PATCH 0295/1148] Update marker component (#1428) --- lib/components/MapMarker.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/components/MapMarker.js b/lib/components/MapMarker.js index 6e2b8585d..b81bab87a 100644 --- a/lib/components/MapMarker.js +++ b/lib/components/MapMarker.js @@ -257,7 +257,7 @@ class MapMarker extends React.Component { let image; if (this.props.image) { image = resolveAssetSource(this.props.image) || {}; - image = image.uri; + image = image.uri || this.props.image; } const AIRMapMarker = this.getAirComponent(); From a3b15c6466570bb58cc23b4868bb7124e891e020 Mon Sep 17 00:00:00 2001 From: Guilherme Pontes Date: Tue, 15 Aug 2017 20:41:53 +0200 Subject: [PATCH 0296/1148] Enhance Podfile. (#1252) --- example/ios/Podfile | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/example/ios/Podfile b/example/ios/Podfile index 66771a383..fd01b85a0 100644 --- a/example/ios/Podfile +++ b/example/ios/Podfile @@ -5,9 +5,10 @@ platform :ios, '8.0' # Change 'AirMapsExplorer' to match the target in your Xcode project. target 'AirMapsExplorer' do + rn_path = '../../node_modules/react-native' - pod 'Yoga', :path => '../../node_modules/react-native/ReactCommon/yoga/Yoga.podspec' - pod 'React', path: '../../node_modules/react-native', :subspecs => [ + pod 'Yoga', path: "#{rn_path}/ReactCommon/yoga/Yoga.podspec" + pod 'React', path: rn_path, subspecs: [ 'Core', 'RCTActionSheet', 'RCTAnimation', @@ -22,16 +23,14 @@ target 'AirMapsExplorer' do 'BatchedBridge' ] - pod 'GoogleMaps' # <~~ remove this line if you do not want to support GoogleMaps on iOS + pod 'GoogleMaps' # Remove this line if you don't want to support GoogleMaps on iOS pod 'react-native-maps', path: '../../' - pod 'react-native-google-maps', path: '../../' # <~~ if you need GoogleMaps support on iOS - + pod 'react-native-google-maps', path: '../../' # If you need GoogleMaps support on iOS end - post_install do |installer| installer.pods_project.targets.each do |target| - if target.name == "react-native-google-maps" + if target.name == 'react-native-google-maps' target.build_configurations.each do |config| config.build_settings['CLANG_ENABLE_MODULES'] = 'No' end From f953252223c119d61522d9923197b79575458a81 Mon Sep 17 00:00:00 2001 From: Christopher Dro Date: Tue, 15 Aug 2017 11:47:11 -0700 Subject: [PATCH 0297/1148] v0.16.1 --- CHANGELOG.md | 8 +++++++- lib/android/gradle.properties | 2 +- package.json | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 45c5bd082..5ae94159d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,13 @@ # Change Log +## 0.16.1 (August 15, 2017) +* Android: [#1428](https://github.com/airbnb/react-native-maps/pull/#1428) Add ability to load marker image from drawable +* iOS: [#1187](https://github.com/airbnb/react-native-maps/pull/1187) Improve marker performance +* iOS/Android: [#1458](https://github.com/airbnb/react-native-maps/pull/1458) Add Google Maps legalNotice constant +* JS: [#1546](https://github.com/airbnb/react-native-maps/pull/1546) Fix initial region native prop + ## 0.16.0 (August 9, 2017) -* Android: [#1481](https://github.com/airbnb/react-native-maps/pull/#1481) Handle Android RN 0.47 breaking change +* Android: [#1481](https://github.com/airbnb/react-native-maps/pull/1481) Handle Android RN 0.47 breaking change * iOS: [#1357](https://github.com/airbnb/react-native-maps/pull/1357) add MKTileOverlayRenderer * iOS: [#1369](https://github.com/airbnb/react-native-maps/pull/1369) Add onMapReady callback * Android/iOS/JS: [#1360](https://github.com/airbnb/react-native-maps/pull/1360) Add minZoom and maxZoom properties for android and ios diff --git a/lib/android/gradle.properties b/lib/android/gradle.properties index ddc39b69d..04d072cc5 100644 --- a/lib/android/gradle.properties +++ b/lib/android/gradle.properties @@ -1,5 +1,5 @@ VERSION_CODE=4 -VERSION_NAME=0.16.0 +VERSION_NAME=0.16.1 GROUP=com.airbnb.android POM_DESCRIPTION=React Native Map view component for Android diff --git a/package.json b/package.json index 408db6b03..104be9b04 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "description": "React Native Mapview component for iOS + Android", "main": "index.js", "author": "Leland Richardson ", - "version": "0.16.0", + "version": "0.16.1", "scripts": { "start": "node node_modules/react-native/local-cli/cli.js start", "run:packager": "./node_modules/react-native/packager/packager.sh", From 4376c97304b47033bbd3562aeff8da451a4f520d Mon Sep 17 00:00:00 2001 From: foyarash Date: Thu, 17 Aug 2017 18:38:38 +0200 Subject: [PATCH 0298/1148] Fix initial region android (#1563) * Fix initial region on android * Fix initial region for android --- .../com/airbnb/android/react/maps/AirMapManager.java | 5 +++++ .../java/com/airbnb/android/react/maps/AirMapView.java | 10 +++++++++- lib/components/MapView.js | 5 ++++- 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java index e8f98a766..9ba6295cd 100644 --- a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java @@ -75,6 +75,11 @@ public void setRegion(AirMapView view, ReadableMap region) { view.setRegion(region); } + @ReactProp(name = "initialRegion") + public void setInitialRegion(AirMapView view, ReadableMap initialRegion) { + view.setInitialRegion(initialRegion); + } + @ReactProp(name = "mapType") public void setMapType(AirMapView view, @Nullable String mapType) { int typeId = MAP_TYPES.get(mapType); diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java index c8b016ce1..14983dc79 100644 --- a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java @@ -70,6 +70,7 @@ public class AirMapView extends MapView implements GoogleMap.InfoWindowAdapter, private boolean handlePanDrag = false; private boolean moveOnMarkerPress = true; private boolean cacheEnabled = false; + private boolean initialRegionSet = false; private static final String[] PERMISSIONS = new String[]{ "android.permission.ACCESS_FINE_LOCATION", "android.permission.ACCESS_COARSE_LOCATION"}; @@ -360,6 +361,13 @@ public synchronized void doDestroy() { onDestroy(); } + public void setInitialRegion(ReadableMap initialRegion) { + if (!initialRegionSet && initialRegion != null) { + setRegion(initialRegion); + initialRegionSet = true; + } + } + public void setRegion(ReadableMap region) { if (region == null) return; @@ -733,7 +741,7 @@ public void run() { eventDispatcher.dispatchEvent(new RegionChangeEvent(getId(), bounds, center, true)); } } - + timerHandler.postDelayed(this, 100); } }; diff --git a/lib/components/MapView.js b/lib/components/MapView.js index f9b974aec..a0f3fa02c 100644 --- a/lib/components/MapView.js +++ b/lib/components/MapView.js @@ -462,10 +462,13 @@ class MapView extends React.Component { const { layout } = e.nativeEvent; if (!layout.width || !layout.height) return; if (this.state.isReady && !this.__layoutCalled) { - const region = this.props.region || this.props.initialRegion; + const { region, initialRegion } = this.props; if (region) { this.__layoutCalled = true; this.map.setNativeProps({ region }); + } else if (initialRegion) { + this.__layoutCalled = true; + this.map.setNativeProps({ initialRegion }); } } if (this.props.onLayout) { From cbdeeafca8f7fc38a398ac105bda94713342c5ae Mon Sep 17 00:00:00 2001 From: Christopher Dro Date: Thu, 17 Aug 2017 09:50:54 -0700 Subject: [PATCH 0299/1148] Revert "Issue1176 improve ios marker performance by X100 (#1187)" This reverts commit b908c08ac2367652249918f4f5694eaf17a1eac2. --- lib/ios/AirGoogleMaps/AIRGoogleMapMarker.m | 80 +++++++++++++++++----- lib/ios/AirGoogleMaps/GlobalVars.h | 22 ------ lib/ios/AirGoogleMaps/GlobalVars.m | 54 --------------- 3 files changed, 64 insertions(+), 92 deletions(-) delete mode 100644 lib/ios/AirGoogleMaps/GlobalVars.h delete mode 100644 lib/ios/AirGoogleMaps/GlobalVars.m diff --git a/lib/ios/AirGoogleMaps/AIRGoogleMapMarker.m b/lib/ios/AirGoogleMaps/AIRGoogleMapMarker.m index 9d96dfafc..c41be55bb 100644 --- a/lib/ios/AirGoogleMaps/AIRGoogleMapMarker.m +++ b/lib/ios/AirGoogleMaps/AIRGoogleMapMarker.m @@ -12,7 +12,6 @@ #import "AIRGMSMarker.h" #import "AIRGoogleMapCallout.h" #import "DummyView.h" -#import "GlobalVars.h" CGRect unionRect(CGRect a, CGRect b) { return CGRectMake( @@ -37,7 +36,6 @@ - (instancetype)init if ((self = [super init])) { _realMarker = [[AIRGMSMarker alloc] init]; _realMarker.fakeMarker = self; - _realMarker.appearAnimation = kGMSMarkerAnimationPop; } return self; } @@ -94,18 +92,6 @@ - (void)insertReactSubview:(id)subview atIndex:(NSInteger)atIndex [super insertReactSubview:(UIView*)dummySubview atIndex:atIndex]; } -- (void)setIcon:(UIImage*)image { - CGImageRef cgref = [image CGImage]; - CIImage *cim = [image CIImage]; - - if (cim == nil && cgref == NULL) { - // image does not contain image data - _realMarker.icon = [GMSMarker markerImageWithColor:UIColor.blueColor]; - } else { - _realMarker.icon = image; - } -} - - (void)removeReactSubview:(id)dummySubview { UIView* subview = ((DummyView*)dummySubview).view; @@ -202,8 +188,70 @@ - (void)setOpacity:(double)opacity - (void)setImageSrc:(NSString *)imageSrc { - UIImage * image = [[GlobalVars sharedInstance] getSharedUIImage:imageSrc]; - [self setIcon:image]; + _imageSrc = imageSrc; + + if (_reloadImageCancellationBlock) { + _reloadImageCancellationBlock(); + _reloadImageCancellationBlock = nil; + } + + if (!_imageSrc) { + if (_iconImageView) [_iconImageView removeFromSuperview]; + return; + } + + if (!_iconImageView) { + // prevent glitch with marker (cf. https://github.com/airbnb/react-native-maps/issues/738) + UIImageView *empyImageView = [[UIImageView alloc] init]; + _iconImageView = empyImageView; + [self iconViewInsertSubview:_iconImageView atIndex:0]; + } + + _reloadImageCancellationBlock = [_bridge.imageLoader loadImageWithURLRequest:[RCTConvert NSURLRequest:_imageSrc] + size:self.bounds.size + scale:RCTScreenScale() + clipped:YES + resizeMode:RCTResizeModeCenter + progressBlock:nil + partialLoadBlock:nil + completionBlock:^(NSError *error, UIImage *image) { + if (error) { + // TODO(lmr): do something with the error? + NSLog(@"%@", error); + } + dispatch_async(dispatch_get_main_queue(), ^{ + + // TODO(gil): This way allows different image sizes + if (_iconImageView) [_iconImageView removeFromSuperview]; + + // ... but this way is more efficient? +// if (_iconImageView) { +// [_iconImageView setImage:image]; +// return; +// } + + UIImageView *imageView = [[UIImageView alloc] initWithImage:image]; + + // TODO: w,h or pixel density could be a prop. + float density = 1; + float w = image.size.width/density; + float h = image.size.height/density; + CGRect bounds = CGRectMake(0, 0, w, h); + + imageView.contentMode = UIViewContentModeScaleAspectFit; + [imageView setFrame:bounds]; + + // NOTE: sizeToFit doesn't work instead. Not sure why. + // TODO: Doing it this way is not ideal because it causes things to reshuffle + // when the image loads IF the image is larger than the UIView. + // Shouldn't required images have size info automatically via RN? + CGRect selfBounds = unionRect(bounds, self.bounds); + [self setFrame:selfBounds]; + + _iconImageView = imageView; + [self iconViewInsertSubview:imageView atIndex:0]; + }); + }]; } - (void)setTitle:(NSString *)title { diff --git a/lib/ios/AirGoogleMaps/GlobalVars.h b/lib/ios/AirGoogleMaps/GlobalVars.h deleted file mode 100644 index 86c3555f7..000000000 --- a/lib/ios/AirGoogleMaps/GlobalVars.h +++ /dev/null @@ -1,22 +0,0 @@ -// -// GlobalVars.h -// -// Created by Eric Kim on 2017-04-04. -// Copyright © 2017 Apply Digital. All rights reserved. -// - -#import -#import - -@interface GlobalVars : NSObject -{ - NSMutableDictionary *dict; -} - -+ (GlobalVars *)sharedInstance; - -- (UIImage *)getSharedUIImage:(NSString *)imageSrc; - -@property(strong, nonatomic, readwrite) NSMutableDictionary *dict; - -@end diff --git a/lib/ios/AirGoogleMaps/GlobalVars.m b/lib/ios/AirGoogleMaps/GlobalVars.m deleted file mode 100644 index 7a541dab4..000000000 --- a/lib/ios/AirGoogleMaps/GlobalVars.m +++ /dev/null @@ -1,54 +0,0 @@ -// -// GlobalVars.m -// -// Created by Eric Kim on 2017-04-04. -// Copyright © 2017 Apply Digital. All rights reserved. -// - -#import "GlobalVars.h" - -@implementation GlobalVars - -@synthesize dict = _dict; - -+ (GlobalVars *)sharedInstance { - static dispatch_once_t onceToken; - static GlobalVars *instance = nil; - dispatch_once(&onceToken, ^{ - instance = [[GlobalVars alloc] init]; - }); - return instance; -} - -- (UIImage *)getSharedUIImage:(NSString *)imageSrc { - - UIImage* cachedImage = dict[imageSrc]; - - CGImageRef cgref = [cachedImage CGImage]; - CIImage *cim = [cachedImage CIImage]; - - if (cim == nil && cgref == NULL) { - UIImage *newImage; - if ([imageSrc hasPrefix:@"http://"] || [imageSrc hasPrefix:@"https://"]){ - NSURL *url = [NSURL URLWithString:imageSrc]; - NSData *data = [NSData dataWithContentsOfURL:url]; - newImage = [UIImage imageWithData:data scale:[UIScreen mainScreen].scale]; - } else { - newImage = [UIImage imageWithContentsOfFile:imageSrc]; - } - dict[imageSrc] = newImage; - return newImage; - } else { - return cachedImage; - } -} - -- (id)init { - self = [super init]; - if (self) { - dict = [[NSMutableDictionary alloc] init]; - } - return self; -} - -@end From fad3aabba4c65047ae7c8d12019ec0818b9556be Mon Sep 17 00:00:00 2001 From: Christopher Dro Date: Thu, 17 Aug 2017 09:55:00 -0700 Subject: [PATCH 0300/1148] v0.16.2 --- CHANGELOG.md | 4 ++++ lib/android/gradle.properties | 2 +- package.json | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5ae94159d..f9ae8057e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Change Log +## 0.16.2 (August 17, 2017) +* Android: [#1563](https://github.com/airbnb/react-native-maps/pull/#1563) Add missing native method for setting initial region +* iOS: [#1187](https://github.com/airbnb/react-native-maps/pull/1187) Reverted due to build issues + ## 0.16.1 (August 15, 2017) * Android: [#1428](https://github.com/airbnb/react-native-maps/pull/#1428) Add ability to load marker image from drawable * iOS: [#1187](https://github.com/airbnb/react-native-maps/pull/1187) Improve marker performance diff --git a/lib/android/gradle.properties b/lib/android/gradle.properties index 04d072cc5..9b4cf86c9 100644 --- a/lib/android/gradle.properties +++ b/lib/android/gradle.properties @@ -1,5 +1,5 @@ VERSION_CODE=4 -VERSION_NAME=0.16.1 +VERSION_NAME=0.16.2 GROUP=com.airbnb.android POM_DESCRIPTION=React Native Map view component for Android diff --git a/package.json b/package.json index 104be9b04..6914f242b 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "description": "React Native Mapview component for iOS + Android", "main": "index.js", "author": "Leland Richardson ", - "version": "0.16.1", + "version": "0.16.2", "scripts": { "start": "node node_modules/react-native/local-cli/cli.js start", "run:packager": "./node_modules/react-native/packager/packager.sh", From af3ff1efba5c28e2f808572d1aa84a5dbdc15021 Mon Sep 17 00:00:00 2001 From: sandinosaso Date: Sat, 26 Aug 2017 20:18:32 -0300 Subject: [PATCH 0301/1148] Add support for AirMap (Native IOS Maps) as suggested on the PR comments. --- lib/ios/AirMaps/AIRMapManager.m | 42 +++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/lib/ios/AirMaps/AIRMapManager.m b/lib/ios/AirMaps/AIRMapManager.m index 76aef88fe..a1970bbbe 100644 --- a/lib/ios/AirMaps/AIRMapManager.m +++ b/lib/ios/AirMaps/AIRMapManager.m @@ -152,6 +152,48 @@ - (UIView *)view }]; } +RCT_EXPORT_METHOD(animateToViewingAngle:(nonnull NSNumber *)reactTag + withAngle:(double)angle + withDuration:(CGFloat)duration) +{ + [self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary *viewRegistry) { + id view = viewRegistry[reactTag]; + if (![view isKindOfClass:[AIRMap class]]) { + RCTLogError(@"Invalid view returned from registry, expecting AIRMap, got: %@", view); + } else { + AIRMap *mapView = (AIRMap *)view; + + MKMapCamera *mapCamera = [[mapView camera] copy]; + [mapCamera setPitch:angle]; + + [AIRMap animateWithDuration:duration/1000 animations:^{ + [mapView setCamera:mapCamera animated:YES]; + }]; + } + }]; +} + +RCT_EXPORT_METHOD(animateToBearing:(nonnull NSNumber *)reactTag + withBearing:(CGFloat)bearing + withDuration:(CGFloat)duration) +{ + [self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary *viewRegistry) { + id view = viewRegistry[reactTag]; + if (![view isKindOfClass:[AIRMap class]]) { + RCTLogError(@"Invalid view returned from registry, expecting AIRMap, got: %@", view); + } else { + AIRMap *mapView = (AIRMap *)view; + + MKMapCamera *mapCamera = [[mapView camera] copy]; + [mapCamera setHeading:bearing]; + + [AIRMap animateWithDuration:duration/1000 animations:^{ + [mapView setCamera:mapCamera animated:YES]; + }]; + } + }]; +} + RCT_EXPORT_METHOD(fitToElements:(nonnull NSNumber *)reactTag animated:(BOOL)animated) { From 725af03f92aea866a1632ddc737a265e43173321 Mon Sep 17 00:00:00 2001 From: Myck Date: Mon, 28 Aug 2017 18:30:19 +0200 Subject: [PATCH 0302/1148] fixe mistakes on circle.md (#1584) lineJoin : wrong type lineCap : add other values --- docs/circle.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/circle.md b/docs/circle.md index 70a5e078e..992ac4567 100644 --- a/docs/circle.md +++ b/docs/circle.md @@ -10,8 +10,8 @@ | `strokeColor` | `String` | `#000`, `rgba(r,g,b,0.5)` | The stroke color to use for the path. | `fillColor` | `String` | `#000`, `rgba(r,g,b,0.5)` | The fill color to use for the path. | `zIndex` | `Number` | 0 | The order in which this tile overlay is drawn with respect to other overlays. An overlay with a larger z-index is drawn over overlays with smaller z-indices. The order of overlays with the same z-index is arbitrary. The default zIndex is 0. (Android Only) -| `lineCap` | `String` | `round` | The line cap style to apply to the open ends of the path. -| `lineJoin` | `Array` | | The line join style to apply to corners of the path. +| `lineCap` | `String` | `round` | The line cap style to apply to the open ends of the path. Other values : `butt`, `square` +| `lineJoin` | `String` | | The line join style to apply to corners of the path. possible value: `miter`, `round`, `bevel` | `miterLimit` | `Number` | | The limiting value that helps avoid spikes at junctions between connected line segments. The miter limit helps you avoid spikes in paths that use the `miter` `lineJoin` style. If the ratio of the miter length—that is, the diagonal length of the miter join—to the line thickness exceeds the miter limit, the joint is converted to a bevel join. The default miter limit is 10, which results in the conversion of miters whose angle at the joint is less than 11 degrees. | `geodesic` | `Boolean` | | Boolean to indicate whether to draw each segment of the line as a geodesic as opposed to straight lines on the Mercator projection. A geodesic is the shortest path between two points on the Earth's surface. The geodesic curve is constructed assuming the Earth is a sphere. | `lineDashPhase` | `Number` | `0` | (iOS only) The offset (in points) at which to start drawing the dash pattern. Use this property to start drawing a dashed line partway through a segment or gap. For example, a phase value of 6 for the patter 5-2-3-2 would cause drawing to begin in the middle of the first gap. From a71356819cf63f55f752571779830f6525e2981b Mon Sep 17 00:00:00 2001 From: paulmasters Date: Mon, 28 Aug 2017 17:39:14 +0100 Subject: [PATCH 0303/1148] Fall back to View.propTypes if ViewPropTypes is not available (#1473) (#1474) --- lib/components/MapView.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/components/MapView.js b/lib/components/MapView.js index a0f3fa02c..e984b9bb1 100644 --- a/lib/components/MapView.js +++ b/lib/components/MapView.js @@ -8,6 +8,7 @@ import { NativeModules, ColorPropType, findNodeHandle, + View, ViewPropTypes, } from 'react-native'; import MapMarker from './MapMarker'; @@ -45,8 +46,11 @@ const viewConfig = { }, }; +// if ViewPropTypes is not defined fall back to View.propType (to support RN < 0.44) +const viewPropTypes = ViewPropTypes || View.propTypes; + const propTypes = { - ...ViewPropTypes, + ...viewPropTypes, /** * When provider is "google", we will use GoogleMaps. * Any value other than "google" will default to using @@ -60,7 +64,7 @@ const propTypes = { * Used to style and layout the `MapView`. See `StyleSheet.js` and * `ViewStylePropTypes.js` for more info. */ - style: ViewPropTypes.style, + style: viewPropTypes.style, /** * A json object that describes the style of the map. This is transformed to a string From a0c8af09090a8d834bafd0ee4e5078ac55b66454 Mon Sep 17 00:00:00 2001 From: Jessy Musoko Date: Fri, 4 Aug 2017 23:13:36 +0200 Subject: [PATCH 0304/1148] Added [iOS / Google Maps] support for showsIndoorLevelPicker. --- lib/ios/AirGoogleMaps/AIRGoogleMap.h | 1 + lib/ios/AirGoogleMaps/AIRGoogleMap.m | 8 ++++++++ lib/ios/AirGoogleMaps/AIRGoogleMapManager.m | 1 + 3 files changed, 10 insertions(+) diff --git a/lib/ios/AirGoogleMaps/AIRGoogleMap.h b/lib/ios/AirGoogleMaps/AIRGoogleMap.h index 0d47b72b1..d2a8e3e6f 100644 --- a/lib/ios/AirGoogleMaps/AIRGoogleMap.h +++ b/lib/ios/AirGoogleMaps/AIRGoogleMap.h @@ -40,6 +40,7 @@ @property (nonatomic, assign) BOOL pitchEnabled; @property (nonatomic, assign) BOOL showsUserLocation; @property (nonatomic, assign) BOOL showsMyLocationButton; +@property (nonatomic, assign) BOOL showsIndoorLevelPicker; - (void)didFinishTileRendering; - (BOOL)didTapMarker:(GMSMarker *)marker; diff --git a/lib/ios/AirGoogleMaps/AIRGoogleMap.m b/lib/ios/AirGoogleMaps/AIRGoogleMap.m index 48b5ff446..f10238531 100644 --- a/lib/ios/AirGoogleMaps/AIRGoogleMap.m +++ b/lib/ios/AirGoogleMaps/AIRGoogleMap.m @@ -312,6 +312,14 @@ - (void)setMaxZoomLevel:(CGFloat)maxZoomLevel { [self setMinZoom:self.minZoom maxZoom:maxZoomLevel ]; } +- (void)setShowsIndoorLevelPicker:(BOOL)showsIndoorLevelPicker { + self.settings.indoorPicker = showsIndoorLevelPicker; +} + +- (BOOL)showsIndoorLevelPicker { + return self.settings.indoorPicker; +} + + (MKCoordinateRegion) makeGMSCameraPositionFromMap:(GMSMapView *)map andGMSCameraPosition:(GMSCameraPosition *)position { // solution from here: http://stackoverflow.com/a/16587735/1102215 GMSVisibleRegion visibleRegion = map.projection.visibleRegion; diff --git a/lib/ios/AirGoogleMaps/AIRGoogleMapManager.m b/lib/ios/AirGoogleMaps/AIRGoogleMapManager.m index 086822b73..54ff10b10 100644 --- a/lib/ios/AirGoogleMaps/AIRGoogleMapManager.m +++ b/lib/ios/AirGoogleMaps/AIRGoogleMapManager.m @@ -58,6 +58,7 @@ - (UIView *)view RCT_EXPORT_VIEW_PROPERTY(pitchEnabled, BOOL) RCT_EXPORT_VIEW_PROPERTY(showsUserLocation, BOOL) RCT_EXPORT_VIEW_PROPERTY(showsMyLocationButton, BOOL) +RCT_EXPORT_VIEW_PROPERTY(showsIndoorLevelPicker, BOOL) RCT_EXPORT_VIEW_PROPERTY(customMapStyleString, NSString) RCT_EXPORT_VIEW_PROPERTY(onMapReady, RCTBubblingEventBlock) RCT_EXPORT_VIEW_PROPERTY(onPress, RCTBubblingEventBlock) From c56d699f3c69841a3520cd2bad4af805279e448a Mon Sep 17 00:00:00 2001 From: Jessy Date: Mon, 28 Aug 2017 20:05:02 +0200 Subject: [PATCH 0305/1148] Updated "showsIndoorLevelPicker" documentation. --- docs/mapview.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/mapview.md b/docs/mapview.md index a73e123b8..f11094725 100644 --- a/docs/mapview.md +++ b/docs/mapview.md @@ -20,7 +20,7 @@ | `showsBuildings` | `Boolean` | `true` | A Boolean indicating whether the map displays extruded building information. | `showsTraffic` | `Boolean` | `true` | A Boolean value indicating whether the map displays traffic information. | `showsIndoors` | `Boolean` | `true` | A Boolean indicating whether indoor maps should be enabled. -| `showsIndoorLevelPicker` | `Boolean` | `false` | A Boolean indicating whether indoor level picker should be enabled. **Note:** Android only. +| `showsIndoorLevelPicker` | `Boolean` | `false` | A Boolean indicating whether indoor level picker should be enabled. **Note:** Google Maps only (either Android or iOS with `PROVIDER_GOOGLE`). | `zoomEnabled` | `Boolean` | `true` | If `false` the user won't be able to pinch/zoom the map. | `minZoomLevel` | `Number` | `0` | Minimum zoom value for the map, must be between 0 and 20 | `maxZoomLevel` | `Number` | `20` | Maximum zoom value for the map, must be between 0 and 20 From c184189adfd3c9fcdbef49449e3e5aa4926ac473 Mon Sep 17 00:00:00 2001 From: Paito Anderson Date: Mon, 28 Aug 2017 23:21:21 -0400 Subject: [PATCH 0306/1148] Added Typescript Definitions --- index.d.ts | 159 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 159 insertions(+) create mode 100644 index.d.ts diff --git a/index.d.ts b/index.d.ts new file mode 100644 index 000000000..d885759b2 --- /dev/null +++ b/index.d.ts @@ -0,0 +1,159 @@ +import * as React from 'react'; + +declare module "react-native-maps" { + + export type ProviderType = 'google'; + export type MapType = 'standard' | 'satellite' | 'hybrid' | 'terrain' | 'none'; + export type LineCapType = 'butt' | 'round' | 'square'; + export type LineJoinType = 'miter' | 'round' | 'bevel'; + + export interface MapViewProperties { + provider?: ProviderType; + style?: any; + customMapStyle?: any[]; + customMapStyleString?: string; + showsUserLocation?: boolean; + userLocationAnnotationTitle?: string; + showsMyLocationButton?: boolean; + followsUserLocation?: boolean; + showsPointsOfInterest?: boolean; + showsCompass?: boolean; + zoomEnabled?: boolean; + rotateEnabled?: boolean; + cacheEnabled?: boolean; + loadingEnabled?: boolean; + loadingBackgroundColor?: any; + loadingIndicatorColor?: any; + scrollEnabled?: boolean; + pitchEnabled?: boolean; + toolbarEnabled?: boolean; + moveOnMarkerPress?: boolean; + showsScale?: boolean; + showsBuildings?: boolean; + showsTraffic?: boolean; + showsIndoors?: boolean; + showsIndoorLevelPicker?: boolean; + mapType?: MapType; + region?: { latitude: number; longitude: number; latitudeDelta: number; longitudeDelta: number; }; + initialRegion?: { latitude: number; longitude: number; latitudeDelta: number; longitudeDelta: number; }; + liteMode?: boolean; + maxDelta?: number; + minDelta?: number; + legalLabelInsets?: any; + onChange?: Function; + onMapReady?: Function; + onRegionChange?: Function; + onRegionChangeComplete?: Function; + onPress?: Function; + onLayout?: Function; + onLongPress?: Function; + onPanDrag?: Function; + onMarkerPress?: Function; + onMarkerSelect?: Function; + onMarkerDeselect?: Function; + onCalloutPress?: Function; + onMarkerDragStart?: Function; + onMarkerDrag?: Function; + onMarkerDragEnd?: Function; + minZoomLevel?: number; + maxZoomLevel?: number; + } + + export interface MarkerProperties { + identifier?: string; + reuseIdentifier?: string; + title?: string; + description?: string; + image?: any; + opacity?: number; + pinColor?: string; + coordinate: { latitude: number; longitude: number }; + centerOffset?: { x: number; y: number }; + calloutOffset?: { x: number; y: number }; + anchor?: { x: number; y: number }; + calloutAnchor?: { x: number; y: number }; + flat?: boolean; + draggable?: boolean; + onPress?: Function; + onSelect?: Function; + onDeselect?: Function; + onCalloutPress?: Function; + onDragStart?: Function; + onDrag?: Function; + onDragEnd?: Function; + } + + export interface MapPolylineProperties { + coordinates?: { latitude: number; longitude: number; }[]; + onPress?: Function; + tappable?: boolean; + fillColor?: string; + strokeWidth?: number; + strokeColor?: string; + zIndex?: number; + lineCap?: LineCapType; + lineJoin?: LineJoinType; + miterLimit?: number; + geodesic?: boolean; + lineDashPhase?: number; + lineDashPattern?: number[]; + } + + export interface MapPolygonProperties { + coordinates?: { latitude: number; longitude: number; }[]; + holes?: { latitude: number; longitude: number; }[][]; + onPress?: Function; + tappable?: boolean; + strokeWidth?: number; + strokeColor?: string; + fillColor?: string; + zIndex?: number; + lineCap?: LineCapType; + lineJoin?: LineJoinType; + miterLimit?: number; + geodesic?: boolean; + lineDashPhase?: number; + lineDashPattern?: number[]; + } + + export interface MapCircleProperties { + center: { latitude: number; longitude: number }; + radius: number; + onPress?: Function; + strokeWidth?: number; + strokeColor?: string; + fillColor?: string; + zIndex?: number; + lineCap?: LineCapType; + lineJoin?: LineJoinType; + miterLimit?: number; + lineDashPhase?: number; + lineDashPattern?: number[]; + } + + export interface MapUrlTitleProperties { + urlTemplate: string; + zIndex?: number; + } + + export interface MapCalloutProperties { + tooltip?: boolean; + onPress?: Function; + } + + class MapView extends React.Component { + static Animated: any; + static AnimatedRegion: any; + } + + namespace MapView { + class Marker extends React.Component {} + class Polyline extends React.Component {} + class Polygon extends React.Component {} + class Circle extends React.Component {} + class UrlTile extends React.Component {} + class Callout extends React.Component {} + } + + export default MapView; +} From 3611c22ff3802682b604b5d8ba33f37f2213bdb9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20Hagstr=C3=B6m?= Date: Tue, 29 Aug 2017 18:25:13 +0200 Subject: [PATCH 0307/1148] Set initial region on view (#1579) --- lib/ios/AirMaps/AIRMapManager.m | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/lib/ios/AirMaps/AIRMapManager.m b/lib/ios/AirMaps/AIRMapManager.m index 76aef88fe..8ddd98c55 100644 --- a/lib/ios/AirMaps/AIRMapManager.m +++ b/lib/ios/AirMaps/AIRMapManager.m @@ -97,7 +97,17 @@ - (UIView *)view RCT_EXPORT_VIEW_PROPERTY(onMarkerDrag, RCTDirectEventBlock) RCT_EXPORT_VIEW_PROPERTY(onMarkerDragEnd, RCTDirectEventBlock) RCT_EXPORT_VIEW_PROPERTY(onCalloutPress, RCTDirectEventBlock) -RCT_EXPORT_VIEW_PROPERTY(initialRegion, MKCoordinateRegion) +RCT_CUSTOM_VIEW_PROPERTY(initialRegion, MKCoordinateRegion, AIRMap) +{ + if (json == nil) return; + + // don't emit region change events when we are setting the initialRegion + BOOL originalIgnore = view.ignoreRegionChanges; + view.ignoreRegionChanges = YES; + [view setInitialRegion:[RCTConvert MKCoordinateRegion:json]]; + view.ignoreRegionChanges = originalIgnore; +} + RCT_EXPORT_VIEW_PROPERTY(minZoomLevel, CGFloat) RCT_EXPORT_VIEW_PROPERTY(maxZoomLevel, CGFloat) @@ -665,7 +675,7 @@ - (void)mapViewDidFinishRenderingMap:(AIRMap *)mapView fullyRendered:(BOOL)fully { [mapView finishLoading]; [mapView cacheViewIfNeeded]; - + mapView.onMapReady(@{}); } From 605ec9a7a4351fccd1dcd6ce43af35ab2381dd2c Mon Sep 17 00:00:00 2001 From: Tikhon Botchkarev Date: Fri, 1 Sep 2017 18:11:22 -0400 Subject: [PATCH 0308/1148] Remove legalNotice from android AirMapModule As per https://developers.google.com/android/reference/com/google/android/gms/common/GooglePlayServicesUtil this information does not need to be displayed in app. --- .../main/java/com/airbnb/android/react/maps/AirMapModule.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapModule.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapModule.java index bd1fb6ed0..dfc71d6d9 100644 --- a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapModule.java +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapModule.java @@ -47,7 +47,7 @@ public String getName() { @Override public Map getConstants() { final Map constants = new HashMap<>(); - constants.put("legalNotice", GoogleApiAvailability.getInstance().getOpenSourceSoftwareLicenseInfo(getReactApplicationContext())); + constants.put("legalNotice", "This license information is displayed in Settings > Google > Open Source on any device running Google Play services."); return constants; } From ddf858bdf1813ca20a231f3ef0dff5dbe4fbfedc Mon Sep 17 00:00:00 2001 From: Paito Anderson Date: Sat, 2 Sep 2017 19:43:17 -0400 Subject: [PATCH 0309/1148] Added missing satellite option for iOS Google Maps (#1603) --- lib/ios/AirGoogleMaps/RCTConvert+GMSMapViewType.m | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/ios/AirGoogleMaps/RCTConvert+GMSMapViewType.m b/lib/ios/AirGoogleMaps/RCTConvert+GMSMapViewType.m index bd339f30e..cfceba559 100644 --- a/lib/ios/AirGoogleMaps/RCTConvert+GMSMapViewType.m +++ b/lib/ios/AirGoogleMaps/RCTConvert+GMSMapViewType.m @@ -13,6 +13,7 @@ @implementation RCTConvert (GMSMapViewType) ( @{ @"standard": @(kGMSTypeNormal), + @"satellite": @(kGMSTypeSatellite), @"hybrid": @(kGMSTypeHybrid), @"terrain": @(kGMSTypeTerrain), @"none": @(kGMSTypeNone) From e6a3f7aedc12cbb5584cb7df638e8ee0c8847aef Mon Sep 17 00:00:00 2001 From: Daniel Merrill Date: Sat, 2 Sep 2017 17:17:58 -0700 Subject: [PATCH 0310/1148] [MapView] revert initialRegion change (#1613) Reverts JS changes made in #1563 which broke initialRegion on iOS, causing the map to display a region centered around 0, 0. --- lib/components/MapView.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/lib/components/MapView.js b/lib/components/MapView.js index e984b9bb1..53db49548 100644 --- a/lib/components/MapView.js +++ b/lib/components/MapView.js @@ -466,13 +466,10 @@ class MapView extends React.Component { const { layout } = e.nativeEvent; if (!layout.width || !layout.height) return; if (this.state.isReady && !this.__layoutCalled) { - const { region, initialRegion } = this.props; + const region = this.props.region || this.props.initialRegion; if (region) { this.__layoutCalled = true; this.map.setNativeProps({ region }); - } else if (initialRegion) { - this.__layoutCalled = true; - this.map.setNativeProps({ initialRegion }); } } if (this.props.onLayout) { From 0916cdff2764a29d0817d3ccc45541ecf411fa1c Mon Sep 17 00:00:00 2001 From: Christopher Dro Date: Sat, 2 Sep 2017 17:23:22 -0700 Subject: [PATCH 0311/1148] Revert "[MapView] revert initialRegion change (#1613)" This reverts commit e6a3f7aedc12cbb5584cb7df638e8ee0c8847aef. --- lib/components/MapView.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/components/MapView.js b/lib/components/MapView.js index 53db49548..e984b9bb1 100644 --- a/lib/components/MapView.js +++ b/lib/components/MapView.js @@ -466,10 +466,13 @@ class MapView extends React.Component { const { layout } = e.nativeEvent; if (!layout.width || !layout.height) return; if (this.state.isReady && !this.__layoutCalled) { - const region = this.props.region || this.props.initialRegion; + const { region, initialRegion } = this.props; if (region) { this.__layoutCalled = true; this.map.setNativeProps({ region }); + } else if (initialRegion) { + this.__layoutCalled = true; + this.map.setNativeProps({ initialRegion }); } } if (this.props.onLayout) { From daf62e6c4a592b2f84c4f7effb4540ac5225d427 Mon Sep 17 00:00:00 2001 From: Christopher Dro Date: Sat, 2 Sep 2017 17:27:31 -0700 Subject: [PATCH 0312/1148] Bump 0.16.3 --- CHANGELOG.md | 4 ++++ lib/android/gradle.properties | 2 +- package.json | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f9ae8057e..c00583d5e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Change Log +## 0.16.3 (September 2, 2017) +* iOS: [#1603](https://github.com/airbnb/react-native-maps/pull/1603) Added missing satellite option for iOS Google Maps +* iOS: [#1579](https://github.com/airbnb/react-native-maps/pull/1579) Set initial region on view + ## 0.16.2 (August 17, 2017) * Android: [#1563](https://github.com/airbnb/react-native-maps/pull/#1563) Add missing native method for setting initial region * iOS: [#1187](https://github.com/airbnb/react-native-maps/pull/1187) Reverted due to build issues diff --git a/lib/android/gradle.properties b/lib/android/gradle.properties index 9b4cf86c9..c49d0997b 100644 --- a/lib/android/gradle.properties +++ b/lib/android/gradle.properties @@ -1,5 +1,5 @@ VERSION_CODE=4 -VERSION_NAME=0.16.2 +VERSION_NAME=0.16.3 GROUP=com.airbnb.android POM_DESCRIPTION=React Native Map view component for Android diff --git a/package.json b/package.json index 6914f242b..e8db38a4a 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "description": "React Native Mapview component for iOS + Android", "main": "index.js", "author": "Leland Richardson ", - "version": "0.16.2", + "version": "0.16.3", "scripts": { "start": "node node_modules/react-native/local-cli/cli.js start", "run:packager": "./node_modules/react-native/packager/packager.sh", From ecfc89b6151c03f90a379c4a580c0a3de851f802 Mon Sep 17 00:00:00 2001 From: sandinosaso Date: Sun, 27 Aug 2017 13:00:00 -0300 Subject: [PATCH 0313/1148] Add support for animateToViewingAngle and animateToBearing for Android --- .../android/react/maps/AirMapManager.java | 24 ++++++++++++++++--- .../airbnb/android/react/maps/AirMapView.java | 20 ++++++++++++++++ 2 files changed, 41 insertions(+), 3 deletions(-) diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java index e8f98a766..58824dd0c 100644 --- a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java @@ -29,9 +29,11 @@ public class AirMapManager extends ViewGroupManager { private static final String REACT_CLASS = "AIRMap"; private static final int ANIMATE_TO_REGION = 1; private static final int ANIMATE_TO_COORDINATE = 2; - private static final int FIT_TO_ELEMENTS = 3; - private static final int FIT_TO_SUPPLIED_MARKERS = 4; - private static final int FIT_TO_COORDINATES = 5; + private static final int ANIMATE_TO_VIEWING_ANGLE = 3; + private static final int ANIMATE_TO_BEARING = 4; + private static final int FIT_TO_ELEMENTS = 5; + private static final int FIT_TO_SUPPLIED_MARKERS = 6; + private static final int FIT_TO_COORDINATES = 7; private final Map MAP_TYPES = MapBuilder.of( "standard", GoogleMap.MAP_TYPE_NORMAL, @@ -195,6 +197,8 @@ public void receiveCommand(AirMapView view, int commandId, @Nullable ReadableArr Double lng; Double lngDelta; Double latDelta; + float bearing; + float angle; ReadableMap region; switch (commandId) { @@ -220,6 +224,18 @@ public void receiveCommand(AirMapView view, int commandId, @Nullable ReadableArr view.animateToCoordinate(new LatLng(lat, lng), duration); break; + case ANIMATE_TO_VIEWING_ANGLE: + angle = (float)args.getDouble(0); + duration = args.getInt(1); + view.animateToViewingAngle(angle, duration); + break; + + case ANIMATE_TO_BEARING: + bearing = (float)args.getDouble(0); + duration = args.getInt(1); + view.animateToBearing(bearing, duration); + break; + case FIT_TO_ELEMENTS: view.fitToElements(args.getBoolean(0)); break; @@ -262,6 +278,8 @@ public Map getCommandsMap() { return MapBuilder.of( "animateToRegion", ANIMATE_TO_REGION, "animateToCoordinate", ANIMATE_TO_COORDINATE, + "animateToViewingAngle", ANIMATE_TO_VIEWING_ANGLE, + "animateToBearing", ANIMATE_TO_BEARING, "fitToElements", FIT_TO_ELEMENTS, "fitToSuppliedMarkers", FIT_TO_SUPPLIED_MARKERS, "fitToCoordinates", FIT_TO_COORDINATES diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java index c8b016ce1..9d3f572a9 100644 --- a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java @@ -562,6 +562,26 @@ public void animateToRegion(LatLngBounds bounds, int duration) { } } + public void animateToViewingAngle(float angle, int duration) { + if (map != null) { + startMonitoringRegion(); + CameraPosition cameraPosition = new CameraPosition.Builder(map.getCameraPosition()) + .tilt(angle) + .build(); + map.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition), duration, null); + } + } + + public void animateToBearing(float bearing, int duration) { + if (map != null) { + startMonitoringRegion(); + CameraPosition cameraPosition = new CameraPosition.Builder(map.getCameraPosition()) + .bearing(bearing) + .build(); + map.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition), duration, null); + } + } + public void animateToCoordinate(LatLng coordinate, int duration) { if (map != null) { startMonitoringRegion(); From 6885fda900f1fc152de1bac5908e25bd98b59c32 Mon Sep 17 00:00:00 2001 From: Carlo Date: Wed, 13 Sep 2017 18:24:55 -0700 Subject: [PATCH 0314/1148] [MapMarker] fix android release crash on custom marker (#1643) --- .../main/java/com/airbnb/android/react/maps/AirMapMarker.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapMarker.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapMarker.java index 52c4dcd08..cb0274bfa 100644 --- a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapMarker.java +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapMarker.java @@ -2,6 +2,7 @@ import android.content.Context; import android.graphics.Bitmap; +import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.drawable.Animatable; import android.net.Uri; @@ -236,6 +237,9 @@ public void setImage(String uri) { logoHolder.setController(controller); } else { iconBitmapDescriptor = getBitmapDescriptorByName(uri); + if (iconBitmapDescriptor != null) { + iconBitmap = BitmapFactory.decodeResource(getResources(), getDrawableResourceByName(uri)); + } update(); } } From 6ad2eca39d7e4033be246d3f61f9cd5d17281944 Mon Sep 17 00:00:00 2001 From: Christopher Dro Date: Wed, 13 Sep 2017 18:27:10 -0700 Subject: [PATCH 0315/1148] v0.16.4 --- CHANGELOG.md | 3 +++ lib/android/gradle.properties | 2 +- package.json | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c00583d5e..5952fe825 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,8 @@ # Change Log +## 0.16.4 (September 13, 2017) +* Android: [#1643](https://github.com/airbnb/react-native-maps/pull/1643) [MapMarker] fix android release crash on custom marker + ## 0.16.3 (September 2, 2017) * iOS: [#1603](https://github.com/airbnb/react-native-maps/pull/1603) Added missing satellite option for iOS Google Maps * iOS: [#1579](https://github.com/airbnb/react-native-maps/pull/1579) Set initial region on view diff --git a/lib/android/gradle.properties b/lib/android/gradle.properties index c49d0997b..a6b4e78ee 100644 --- a/lib/android/gradle.properties +++ b/lib/android/gradle.properties @@ -1,5 +1,5 @@ VERSION_CODE=4 -VERSION_NAME=0.16.3 +VERSION_NAME=0.16.4 GROUP=com.airbnb.android POM_DESCRIPTION=React Native Map view component for Android diff --git a/package.json b/package.json index e8db38a4a..11f1004fb 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "description": "React Native Mapview component for iOS + Android", "main": "index.js", "author": "Leland Richardson ", - "version": "0.16.3", + "version": "0.16.4", "scripts": { "start": "node node_modules/react-native/local-cli/cli.js start", "run:packager": "./node_modules/react-native/packager/packager.sh", From 86e79df9f65a448cfe195c0a2ebfdab652b96c2e Mon Sep 17 00:00:00 2001 From: Paito Anderson Date: Sun, 8 Oct 2017 22:25:27 -0400 Subject: [PATCH 0316/1148] Update index.d.ts --- index.d.ts | 151 ++++++++++++++++++++++++++--------------------------- 1 file changed, 74 insertions(+), 77 deletions(-) diff --git a/index.d.ts b/index.d.ts index d885759b2..9a770c3fc 100644 --- a/index.d.ts +++ b/index.d.ts @@ -1,65 +1,68 @@ import * as React from 'react'; -declare module "react-native-maps" { +interface MapViewProps { + provider?: 'google'; + style: any; + customMapStyle?: any[]; + customMapStyleString?: string; + showsUserLocation?: boolean; + userLocationAnnotationTitle?: string; + showsMyLocationButton?: boolean; + followsUserLocation?: boolean; + showsPointsOfInterest?: boolean; + showsCompass?: boolean; + zoomEnabled?: boolean; + rotateEnabled?: boolean; + cacheEnabled?: boolean; + loadingEnabled?: boolean; + loadingBackgroundColor?: any; + loadingIndicatorColor?: any; + scrollEnabled?: boolean; + pitchEnabled?: boolean; + toolbarEnabled?: boolean; + moveOnMarkerPress?: boolean; + showsScale?: boolean; + showsBuildings?: boolean; + showsTraffic?: boolean; + showsIndoors?: boolean; + showsIndoorLevelPicker?: boolean; + mapType?: 'standard' | 'satellite' | 'hybrid' | 'terrain' | 'none'; + region?: { latitude: number; longitude: number; latitudeDelta: number; longitudeDelta: number; }; + initialRegion?: { latitude: number; longitude: number; latitudeDelta: number; longitudeDelta: number; }; + liteMode?: boolean; + maxDelta?: number; + minDelta?: number; + legalLabelInsets?: any; + onChange?: Function; + onMapReady?: Function; + onRegionChange?: Function; + onRegionChangeComplete?: Function; + onPress?: Function; + onLayout?: Function; + onLongPress?: Function; + onPanDrag?: Function; + onMarkerPress?: Function; + onMarkerSelect?: Function; + onMarkerDeselect?: Function; + onCalloutPress?: Function; + onMarkerDragStart?: Function; + onMarkerDrag?: Function; + onMarkerDragEnd?: Function; + minZoomLevel?: number; + maxZoomLevel?: number; +} - export type ProviderType = 'google'; - export type MapType = 'standard' | 'satellite' | 'hybrid' | 'terrain' | 'none'; - export type LineCapType = 'butt' | 'round' | 'square'; - export type LineJoinType = 'miter' | 'round' | 'bevel'; +declare class MapView extends React.Component { + static Animated: any; + static AnimatedRegion: any; +} - export interface MapViewProperties { - provider?: ProviderType; - style?: any; - customMapStyle?: any[]; - customMapStyleString?: string; - showsUserLocation?: boolean; - userLocationAnnotationTitle?: string; - showsMyLocationButton?: boolean; - followsUserLocation?: boolean; - showsPointsOfInterest?: boolean; - showsCompass?: boolean; - zoomEnabled?: boolean; - rotateEnabled?: boolean; - cacheEnabled?: boolean; - loadingEnabled?: boolean; - loadingBackgroundColor?: any; - loadingIndicatorColor?: any; - scrollEnabled?: boolean; - pitchEnabled?: boolean; - toolbarEnabled?: boolean; - moveOnMarkerPress?: boolean; - showsScale?: boolean; - showsBuildings?: boolean; - showsTraffic?: boolean; - showsIndoors?: boolean; - showsIndoorLevelPicker?: boolean; - mapType?: MapType; - region?: { latitude: number; longitude: number; latitudeDelta: number; longitudeDelta: number; }; - initialRegion?: { latitude: number; longitude: number; latitudeDelta: number; longitudeDelta: number; }; - liteMode?: boolean; - maxDelta?: number; - minDelta?: number; - legalLabelInsets?: any; - onChange?: Function; - onMapReady?: Function; - onRegionChange?: Function; - onRegionChangeComplete?: Function; - onPress?: Function; - onLayout?: Function; - onLongPress?: Function; - onPanDrag?: Function; - onMarkerPress?: Function; - onMarkerSelect?: Function; - onMarkerDeselect?: Function; - onCalloutPress?: Function; - onMarkerDragStart?: Function; - onMarkerDrag?: Function; - onMarkerDragEnd?: Function; - minZoomLevel?: number; - maxZoomLevel?: number; - } +declare namespace MapView { + + type LineCapType = 'butt' | 'round' | 'square'; + type LineJoinType = 'miter' | 'round' | 'bevel'; - export interface MarkerProperties { + interface MarkerProps { identifier?: string; reuseIdentifier?: string; title?: string; @@ -81,9 +84,10 @@ declare module "react-native-maps" { onDragStart?: Function; onDrag?: Function; onDragEnd?: Function; + zIndex?: number; } - export interface MapPolylineProperties { + interface MapPolylineProps { coordinates?: { latitude: number; longitude: number; }[]; onPress?: Function; tappable?: boolean; @@ -99,7 +103,7 @@ declare module "react-native-maps" { lineDashPattern?: number[]; } - export interface MapPolygonProperties { + interface MapPolygonProps { coordinates?: { latitude: number; longitude: number; }[]; holes?: { latitude: number; longitude: number; }[][]; onPress?: Function; @@ -116,7 +120,7 @@ declare module "react-native-maps" { lineDashPattern?: number[]; } - export interface MapCircleProperties { + interface MapCircleProps { center: { latitude: number; longitude: number }; radius: number; onPress?: Function; @@ -131,29 +135,22 @@ declare module "react-native-maps" { lineDashPattern?: number[]; } - export interface MapUrlTitleProperties { + interface MapUrlTitleProps { urlTemplate: string; zIndex?: number; } - export interface MapCalloutProperties { + interface MapCalloutProps { tooltip?: boolean; onPress?: Function; } - class MapView extends React.Component { - static Animated: any; - static AnimatedRegion: any; - } - - namespace MapView { - class Marker extends React.Component {} - class Polyline extends React.Component {} - class Polygon extends React.Component {} - class Circle extends React.Component {} - class UrlTile extends React.Component {} - class Callout extends React.Component {} - } - - export default MapView; + export class Marker extends React.Component {} + export class Polyline extends React.Component {} + export class Polygon extends React.Component {} + export class Circle extends React.Component {} + export class UrlTile extends React.Component {} + export class Callout extends React.Component {} } + +export = MapView; From 9fd1055c2b1321ed1b830cd5de6434a5a06f773a Mon Sep 17 00:00:00 2001 From: Christopher Dro Date: Wed, 11 Oct 2017 11:42:27 -0700 Subject: [PATCH 0317/1148] v0.17.0 --- CHANGELOG.md | 8 ++++++++ lib/android/gradle.properties | 2 +- package.json | 2 +- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5952fe825..5678d8052 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Change Log +## 0.17.0 (October 11, 2017) +* iOS: [#1527](https://github.com/airbnb/react-native-maps/pull/1527) Added [iOS / Google Maps] support for showsIndoorLevelPicker +* iOS/Android: [#1544](https://github.com/airbnb/react-native-maps/pull/1544) Adds support to animateToBearing and animateToViewingAngle ( IOS + Android ) +* JS: [#1503](https://github.com/airbnb/react-native-maps/pull/1503) Remove caret from "react": "^16.0.0-alpha.12 +* Android: [#1521](https://github.com/airbnb/react-native-maps/pull/1521) Fix rare android crashes when map size is 0 +* Common: [#1610](https://github.com/airbnb/react-native-maps/pull/1610) Added Typescript Definitions +* Android: [#1612](https://github.com/airbnb/react-native-maps/pull/1612) Remove legalNotice from android AirMapModule + ## 0.16.4 (September 13, 2017) * Android: [#1643](https://github.com/airbnb/react-native-maps/pull/1643) [MapMarker] fix android release crash on custom marker diff --git a/lib/android/gradle.properties b/lib/android/gradle.properties index a6b4e78ee..7047e93ba 100644 --- a/lib/android/gradle.properties +++ b/lib/android/gradle.properties @@ -1,5 +1,5 @@ VERSION_CODE=4 -VERSION_NAME=0.16.4 +VERSION_NAME=0.17.0 GROUP=com.airbnb.android POM_DESCRIPTION=React Native Map view component for Android diff --git a/package.json b/package.json index a50930ab8..66e8be298 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "description": "React Native Mapview component for iOS + Android", "main": "index.js", "author": "Leland Richardson ", - "version": "0.16.4", + "version": "0.17.0", "scripts": { "start": "node node_modules/react-native/local-cli/cli.js start", "run:packager": "./node_modules/react-native/packager/packager.sh", From a427a81434689253784bfb899278c23ee4723324 Mon Sep 17 00:00:00 2001 From: Michel Albers Date: Wed, 25 Oct 2017 13:26:39 +0200 Subject: [PATCH 0318/1148] Workaround for "GoogleMapsBase not found" issue --- react-native-google-maps.podspec | 1 + 1 file changed, 1 insertion(+) diff --git a/react-native-google-maps.podspec b/react-native-google-maps.podspec index 632da81d5..487cc2320 100644 --- a/react-native-google-maps.podspec +++ b/react-native-google-maps.podspec @@ -14,6 +14,7 @@ Pod::Spec.new do |s| s.source = { :git => "https://github.com/airbnb/react-native-maps.git" } s.source_files = "lib/ios/AirGoogleMaps/**/*.{h,m}" + s.compiler_flags = '-fno-modules' s.dependency 'React' s.dependency 'GoogleMaps', '2.1.1' From 5edaaf47c2132d1283e4453de7e7fd61d6434f69 Mon Sep 17 00:00:00 2001 From: Thibault Malbranche Date: Tue, 31 Oct 2017 16:33:10 +0100 Subject: [PATCH 0319/1148] Fix React Native 0.49 requiresMainQueueSetup --- lib/ios/AirGoogleMaps/AIRGoogleMapManager.m | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/ios/AirGoogleMaps/AIRGoogleMapManager.m b/lib/ios/AirGoogleMaps/AIRGoogleMapManager.m index 12d63e104..867b41803 100644 --- a/lib/ios/AirGoogleMaps/AIRGoogleMapManager.m +++ b/lib/ios/AirGoogleMaps/AIRGoogleMapManager.m @@ -263,6 +263,10 @@ - (NSDictionary *)constantsToExport { return @{ @"legalNotice": [GMSServices openSourceLicenseInfo] }; } ++ (BOOL)requiresMainQueueSetup { + return YES; +} + - (void)mapViewDidFinishTileRendering:(GMSMapView *)mapView { AIRGoogleMap *googleMapView = (AIRGoogleMap *)mapView; [googleMapView didFinishTileRendering]; From 1c47c657b8b3052a576eba76a7ecf33ae08b3bf9 Mon Sep 17 00:00:00 2001 From: Bramus! Date: Tue, 28 Nov 2017 19:13:15 +0100 Subject: [PATCH 0320/1148] Allow fitToCoordinates to be called without options parameter (#1817) Right now it's not possible to call `fitToCoordinates` without an `options` parameter, even though defaults are defined in the function body. This commit set the default value of the `options` parameter of to an empty object, allowing one to call the function without it _(and with respect for the defaults)_. --- lib/components/MapView.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/components/MapView.js b/lib/components/MapView.js index 123d34f60..e88727c13 100644 --- a/lib/components/MapView.js +++ b/lib/components/MapView.js @@ -515,7 +515,7 @@ class MapView extends React.Component { this._runCommand('fitToSuppliedMarkers', [markers, animated]); } - fitToCoordinates(coordinates = [], options) { + fitToCoordinates(coordinates = [], options = {}) { const { edgePadding = { top: 0, right: 0, bottom: 0, left: 0 }, animated = true, From 3c3fc5c07871ba236d0f0beff53716311e6fa6aa Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Tue, 28 Nov 2017 20:15:17 +0200 Subject: [PATCH 0321/1148] Fixed onMapReady event on iOS to resemble onMapReady on Android (Closes #1793) (#1797) Also: Closes #1776, Closes #1696, Closes #1680, Closes #1605) Probably closes more issues related to iOS, panning and scrolling. --- lib/ios/AirGoogleMaps/AIRGoogleMap.h | 2 +- lib/ios/AirGoogleMaps/AIRGoogleMap.m | 2 +- lib/ios/AirGoogleMaps/AIRGoogleMapManager.m | 18 ++++++++++-------- lib/ios/AirMaps/AIRMapManager.m | 14 ++++++++++---- 4 files changed, 22 insertions(+), 14 deletions(-) diff --git a/lib/ios/AirGoogleMaps/AIRGoogleMap.h b/lib/ios/AirGoogleMaps/AIRGoogleMap.h index d2a8e3e6f..fa0293ae3 100644 --- a/lib/ios/AirGoogleMaps/AIRGoogleMap.h +++ b/lib/ios/AirGoogleMaps/AIRGoogleMap.h @@ -42,7 +42,7 @@ @property (nonatomic, assign) BOOL showsMyLocationButton; @property (nonatomic, assign) BOOL showsIndoorLevelPicker; -- (void)didFinishTileRendering; +- (void)didPrepareMap; - (BOOL)didTapMarker:(GMSMarker *)marker; - (void)didTapPolyline:(GMSPolyline *)polyline; - (void)didTapPolygon:(GMSPolygon *)polygon; diff --git a/lib/ios/AirGoogleMaps/AIRGoogleMap.m b/lib/ios/AirGoogleMaps/AIRGoogleMap.m index f10238531..4c1976fe7 100644 --- a/lib/ios/AirGoogleMaps/AIRGoogleMap.m +++ b/lib/ios/AirGoogleMaps/AIRGoogleMap.m @@ -155,7 +155,7 @@ - (void)setRegion:(MKCoordinateRegion)region { self.camera = [AIRGoogleMap makeGMSCameraPositionFromMap:self andMKCoordinateRegion:region]; } -- (void)didFinishTileRendering { +- (void)didPrepareMap { if (self.onMapReady) self.onMapReady(@{}); } diff --git a/lib/ios/AirGoogleMaps/AIRGoogleMapManager.m b/lib/ios/AirGoogleMaps/AIRGoogleMapManager.m index 867b41803..559b6be3d 100644 --- a/lib/ios/AirGoogleMaps/AIRGoogleMapManager.m +++ b/lib/ios/AirGoogleMaps/AIRGoogleMapManager.m @@ -32,7 +32,10 @@ @interface AIRGoogleMapManager() - +{ + BOOL didCallOnMapReady; +} + @end @implementation AIRGoogleMapManager @@ -263,13 +266,12 @@ - (NSDictionary *)constantsToExport { return @{ @"legalNotice": [GMSServices openSourceLicenseInfo] }; } -+ (BOOL)requiresMainQueueSetup { - return YES; -} - -- (void)mapViewDidFinishTileRendering:(GMSMapView *)mapView { - AIRGoogleMap *googleMapView = (AIRGoogleMap *)mapView; - [googleMapView didFinishTileRendering]; +- (void)mapViewDidStartTileRendering:(GMSMapView *)mapView { + if (didCallOnMapReady) return; + didCallOnMapReady = YES; + + AIRGoogleMap *googleMapView = (AIRGoogleMap *)mapView; + [googleMapView didPrepareMap]; } - (BOOL)mapView:(GMSMapView *)mapView didTapMarker:(GMSMarker *)marker { diff --git a/lib/ios/AirMaps/AIRMapManager.m b/lib/ios/AirMaps/AIRMapManager.m index 483834369..1124c440c 100644 --- a/lib/ios/AirMaps/AIRMapManager.m +++ b/lib/ios/AirMaps/AIRMapManager.m @@ -36,7 +36,10 @@ @interface AIRMapManager() @end @implementation AIRMapManager - +{ + BOOL didCallOnMapReady; +} + RCT_EXPORT_MODULE() - (UIView *)view @@ -708,6 +711,12 @@ - (void)mapView:(AIRMap *)mapView regionDidChangeAnimated:(__unused BOOL)animate - (void)mapViewWillStartRenderingMap:(AIRMap *)mapView { + if (!didCallOnMapReady) + { + didCallOnMapReady = YES; + mapView.onMapReady(@{}); + } + mapView.hasStartedRendering = YES; [mapView beginLoading]; [self _emitRegionChangeEvent:mapView continuous:NO]; @@ -716,9 +725,6 @@ - (void)mapViewWillStartRenderingMap:(AIRMap *)mapView - (void)mapViewDidFinishRenderingMap:(AIRMap *)mapView fullyRendered:(BOOL)fullyRendered { [mapView finishLoading]; - [mapView cacheViewIfNeeded]; - - mapView.onMapReady(@{}); } #pragma mark Private From d11a778133b0f9663e3f6ac3eb887103c107b95e Mon Sep 17 00:00:00 2001 From: John Date: Wed, 29 Nov 2017 02:16:38 +0800 Subject: [PATCH 0322/1148] Update Podfile (#1816) fix `The name of the given podspec `yoga` doesn't match the expected one `Yoga`` --- example/ios/Podfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/example/ios/Podfile b/example/ios/Podfile index fd01b85a0..37326fb7d 100644 --- a/example/ios/Podfile +++ b/example/ios/Podfile @@ -7,7 +7,7 @@ platform :ios, '8.0' target 'AirMapsExplorer' do rn_path = '../../node_modules/react-native' - pod 'Yoga', path: "#{rn_path}/ReactCommon/yoga/Yoga.podspec" + pod 'yoga', path: "#{rn_path}/ReactCommon/yoga/yoga.podspec" pod 'React', path: rn_path, subspecs: [ 'Core', 'RCTActionSheet', From be1b6ded3913d09fe8462cdec741171ce9d939b4 Mon Sep 17 00:00:00 2001 From: androidseb Date: Tue, 28 Nov 2017 13:21:34 -0500 Subject: [PATCH 0323/1148] fixed the MapView onMarkerPress callback not sending the ID of the marker (#1741) --- lib/components/MapView.js | 9 +++++++++ lib/ios/AirGoogleMaps/AIRGoogleMapManager.m | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/lib/components/MapView.js b/lib/components/MapView.js index e88727c13..eec576291 100644 --- a/lib/components/MapView.js +++ b/lib/components/MapView.js @@ -415,6 +415,7 @@ class MapView extends React.Component { }; this._onMapReady = this._onMapReady.bind(this); + this._onMarkerPress = this._onMarkerPress.bind(this); this._onChange = this._onChange.bind(this); this._onLayout = this._onLayout.bind(this); } @@ -480,6 +481,12 @@ class MapView extends React.Component { } } + _onMarkerPress(event) { + if (this.props.onMarkerPress) { + this.props.onMarkerPress(event.nativeEvent); + } + } + _onChange(event) { this.__lastRegion = event.nativeEvent.region; if (event.nativeEvent.continuous) { @@ -638,6 +645,7 @@ class MapView extends React.Component { ...this.props, region: null, initialRegion: null, + onMarkerPress: this._onMarkerPress, onChange: this._onChange, onMapReady: this._onMapReady, onLayout: this._onLayout, @@ -652,6 +660,7 @@ class MapView extends React.Component { style: this.props.style, region: null, initialRegion: null, + onMarkerPress: this._onMarkerPress, onChange: this._onChange, onMapReady: this._onMapReady, onLayout: this._onLayout, diff --git a/lib/ios/AirGoogleMaps/AIRGoogleMapManager.m b/lib/ios/AirGoogleMaps/AIRGoogleMapManager.m index 559b6be3d..043841305 100644 --- a/lib/ios/AirGoogleMaps/AIRGoogleMapManager.m +++ b/lib/ios/AirGoogleMaps/AIRGoogleMapManager.m @@ -67,7 +67,7 @@ - (UIView *)view RCT_EXPORT_VIEW_PROPERTY(onPress, RCTBubblingEventBlock) RCT_EXPORT_VIEW_PROPERTY(onLongPress, RCTBubblingEventBlock) RCT_EXPORT_VIEW_PROPERTY(onChange, RCTBubblingEventBlock) -RCT_EXPORT_VIEW_PROPERTY(onMarkerPress, RCTDirectEventBlock) +RCT_EXPORT_VIEW_PROPERTY(onMarkerPress, RCTBubblingEventBlock) RCT_EXPORT_VIEW_PROPERTY(onRegionChange, RCTDirectEventBlock) RCT_EXPORT_VIEW_PROPERTY(onRegionChangeComplete, RCTDirectEventBlock) RCT_EXPORT_VIEW_PROPERTY(mapType, GMSMapViewType) From 89e96788043ecb37b764101cdc56976c37222428 Mon Sep 17 00:00:00 2001 From: Paito Anderson Date: Tue, 28 Nov 2017 13:22:29 -0500 Subject: [PATCH 0324/1148] Added style prop to MapCalloutProps in Typings (#1759) * Added style prop to MapCalloutProps in Typings Fixes @marcmo issue in #1687 * Update index.d.ts Added style on MapView.Marker --- index.d.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/index.d.ts b/index.d.ts index 9a770c3fc..75e976ee1 100644 --- a/index.d.ts +++ b/index.d.ts @@ -85,6 +85,7 @@ declare namespace MapView { onDrag?: Function; onDragEnd?: Function; zIndex?: number; + style?: any; } interface MapPolylineProps { @@ -143,6 +144,7 @@ declare namespace MapView { interface MapCalloutProps { tooltip?: boolean; onPress?: Function; + style?: any; } export class Marker extends React.Component {} From 15ba9cbd6d4bf0d4abe3fdf00d23cd9cacb45a76 Mon Sep 17 00:00:00 2001 From: ashour Date: Tue, 28 Nov 2017 20:23:11 +0200 Subject: [PATCH 0325/1148] Added explicit instructions to copy `AirGoogleMaps` files (#1734) If the files are not copied during dragging the folder, your iOS project will fail to build --- docs/installation.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/installation.md b/docs/installation.md index ad9d4b383..acd1f4657 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -25,10 +25,10 @@ react-native link react-native-maps (If you do not need `GoogleMaps` support for iOS, then you can probably completely skip this step.) 1. Open your project in Xcode workspace 1. If you need `GoogleMaps` support also - - Drag this folder `node_modules/react-native-maps/lib/ios/AirGoogleMaps/` into your project, and choose `Create groups` in the popup window. + - Drag this folder `node_modules/react-native-maps/lib/ios/AirGoogleMaps/` into your project, and choose `Create groups` and `Copy items if needed` in the popup window. - In `AppDelegate.m`, add `@import GoogleMaps;` before `@implementation AppDelegate`. In `- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions`, add `[GMSServices provideAPIKey:@"YOUR_GOOGLE_MAP_API_KEY"];` - In your project's `Build Settings` > `Header Search Paths`, double click the value field. In the popup, add `$(SRCROOT)/../node_modules/react-native-maps/lib/ios/AirMaps` and change `non-recursive` to `recursive`. (Dragging the folder `node_modules/react-native-maps/lib/ios/AirMaps/` into your project introduces duplicate symbols. We should not do it.) - + Note: We recommend using a version of React Native >= .40. Newer versions (>= .40) require `package.json` to be set to `"react-native-maps": "^0.13.0"`, while older versions require `"react-native-maps": "^0.12.4"`. ### Option 2: CocoaPods @@ -195,7 +195,7 @@ You have to link dependencies with rnpm and re-run the build: - Extras / Google Play services - Extras / Google Repository - Android 6.0 (API 23) / Google APIs Intel x86 Atom System Image Rev. 19 - - Android SDK Build-tools 23.0.3 + - Android SDK Build-tools 23.0.3 1. Check manual installation steps if you didn't run "react-native link react-native-maps" 1. Go to [Google API Console](https://console.developers.google.com/flows/enableapi?apiid=maps_android_backend) and select your project, or create one. Then, once enabled, select `Go to credentials`. From 8ec93e4c4ecf8752b60cd43346959ebac1de82d2 Mon Sep 17 00:00:00 2001 From: Seivan Heidari Date: Tue, 28 Nov 2017 19:23:23 +0100 Subject: [PATCH 0326/1148] Update CHANGELOG.md (#1720) Ignore this if the changelog is generated from commits or something. --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5678d8052..f61819749 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ * iOS/Android: [#1544](https://github.com/airbnb/react-native-maps/pull/1544) Adds support to animateToBearing and animateToViewingAngle ( IOS + Android ) * JS: [#1503](https://github.com/airbnb/react-native-maps/pull/1503) Remove caret from "react": "^16.0.0-alpha.12 * Android: [#1521](https://github.com/airbnb/react-native-maps/pull/1521) Fix rare android crashes when map size is 0 -* Common: [#1610](https://github.com/airbnb/react-native-maps/pull/1610) Added Typescript Definitions +* Common: [#1601](https://github.com/airbnb/react-native-maps/pull/1610) Added Typescript Definitions * Android: [#1612](https://github.com/airbnb/react-native-maps/pull/1612) Remove legalNotice from android AirMapModule ## 0.16.4 (September 13, 2017) From e4ecbd3ecee89836431cc0e8e13bf7742709b6b7 Mon Sep 17 00:00:00 2001 From: "A.T" Date: Tue, 28 Nov 2017 19:23:47 +0100 Subject: [PATCH 0327/1148] Fixed Podfile (#1718) --- .../AirMapsExplorer.xcodeproj/project.pbxproj | 8 +++++++- example/ios/Podfile | 4 ---- example/ios/Podfile.lock | 20 +++++++++---------- 3 files changed, 17 insertions(+), 15 deletions(-) diff --git a/example/ios/AirMapsExplorer.xcodeproj/project.pbxproj b/example/ios/AirMapsExplorer.xcodeproj/project.pbxproj index efeabceb4..21d588c64 100644 --- a/example/ios/AirMapsExplorer.xcodeproj/project.pbxproj +++ b/example/ios/AirMapsExplorer.xcodeproj/project.pbxproj @@ -289,9 +289,12 @@ files = ( ); inputPaths = ( + "${SRCROOT}/Pods/Target Support Files/Pods-AirMapsExplorer/Pods-AirMapsExplorer-resources.sh", + "${PODS_ROOT}/GoogleMaps/Maps/Frameworks/GoogleMaps.framework/Versions/A/Resources/GoogleMaps.bundle", ); name = "[CP] Copy Pods Resources"; outputPaths = ( + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; @@ -304,13 +307,16 @@ files = ( ); inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", ); name = "[CP] Check Pods Manifest.lock"; outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-AirMapsExplorer-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n"; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; /* End PBXShellScriptBuildPhase section */ diff --git a/example/ios/Podfile b/example/ios/Podfile index 37326fb7d..aeefe611a 100644 --- a/example/ios/Podfile +++ b/example/ios/Podfile @@ -35,9 +35,5 @@ post_install do |installer| config.build_settings['CLANG_ENABLE_MODULES'] = 'No' end end - - if target.name == "React" - target.remove_from_project - end end end diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index 3eec18fee..6fc414fe3 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -6,10 +6,10 @@ PODS: - GoogleMaps/Base - React (0.45.1): - React/Core (= 0.45.1) - - react-native-google-maps (0.15.2): + - react-native-google-maps (0.17.0): - GoogleMaps (= 2.1.1) - React - - react-native-maps (0.15.2): + - react-native-maps (0.17.0): - React - React/BatchedBridge (0.45.1): - React/Core @@ -62,21 +62,21 @@ DEPENDENCIES: EXTERNAL SOURCES: React: - :path: "../../node_modules/react-native" + :path: ../../node_modules/react-native react-native-google-maps: - :path: "../../" + :path: ../../ react-native-maps: - :path: "../../" + :path: ../../ Yoga: - :path: "../../node_modules/react-native/ReactCommon/yoga/Yoga.podspec" + :path: ../../node_modules/react-native/ReactCommon/yoga/Yoga.podspec SPEC CHECKSUMS: GoogleMaps: a5b5bbe47734e2443bde781a6aa64e69fdb6d785 React: 0c9191a8b0c843d7004f950ac6b5f6cba9d125c7 - react-native-google-maps: d0b8772eb76e1615ea32c73bc9d573360b8c0817 - react-native-maps: fe2e4680b4d3fcfd84d636ccedd470fe358d55e1 + react-native-google-maps: 73a7f74a00d36c74df41388ebb8394ceba81ef0e + react-native-maps: ee0bb36520eb49dfc2bf11754a486a4fa5c5f883 Yoga: 89c8738d42a0b46a113acb4e574336d61cba2985 -PODFILE CHECKSUM: 8b3eb68ef6553bf1fcb8a467e0e63000b37ec692 +PODFILE CHECKSUM: c069397afd4c9ecf6886b7c00e7d7264dced43a4 -COCOAPODS: 1.2.0 +COCOAPODS: 1.3.1 From ae228ae09442ccb7fa7bfcaf035b7f82cd4eac4a Mon Sep 17 00:00:00 2001 From: Hein Rutjes Date: Tue, 28 Nov 2017 19:28:39 +0100 Subject: [PATCH 0328/1148] Added support for new Android camera movement APIs (#1710) `OnCameraChangeListener` is deprecated and should no longer be used. This PR adds support for new more powerful APIs and removes the old hacky region detection code. This fixes various issues and paves the way for distinguishing between gestures and manual/programatic animations the same time. https://developers.google.com/android/reference/com/google/android/gms/maps/GoogleMap.OnCameraChangeListener --- .../airbnb/android/react/maps/AirMapView.java | 104 +++++------------- .../android/react/maps/RegionChangeEvent.java | 5 +- 2 files changed, 28 insertions(+), 81 deletions(-) diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java index 836fe0e35..fa2f63646 100644 --- a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java @@ -13,7 +13,6 @@ import android.support.v4.view.MotionEventCompat; import android.view.GestureDetector; import android.view.MotionEvent; -import android.view.ScaleGestureDetector; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; @@ -65,12 +64,12 @@ public class AirMapView extends MapView implements GoogleMap.InfoWindowAdapter, private LatLngBounds boundsToMove; private boolean showUserLocation = false; - private boolean isMonitoringRegion = false; - private boolean isTouchDown = false; private boolean handlePanDrag = false; private boolean moveOnMarkerPress = true; private boolean cacheEnabled = false; private boolean initialRegionSet = false; + private LatLngBounds cameraLastIdleBounds; + private int cameraMoveReason = 0; private static final String[] PERMISSIONS = new String[]{ "android.permission.ACCESS_FINE_LOCATION", "android.permission.ACCESS_COARSE_LOCATION"}; @@ -79,7 +78,6 @@ public class AirMapView extends MapView implements GoogleMap.InfoWindowAdapter, private final Map markerMap = new HashMap<>(); private final Map polylineMap = new HashMap<>(); private final Map polygonMap = new HashMap<>(); - private final ScaleGestureDetector scaleDetector; private final GestureDetectorCompat gestureDetector; private final AirMapManager manager; private LifecycleEventListener lifecycleListener; @@ -133,23 +131,9 @@ public AirMapView(ThemedReactContext reactContext, ReactApplicationContext appCo super.getMapAsync(this); final AirMapView view = this; - scaleDetector = - new ScaleGestureDetector(reactContext, - new ScaleGestureDetector.SimpleOnScaleGestureListener() { - @Override - public boolean onScaleBegin(ScaleGestureDetector detector) { - view.startMonitoringRegion(); - return true; // stop recording this gesture. let mapview handle it. - } - }); gestureDetector = new GestureDetectorCompat(reactContext, new GestureDetector.SimpleOnGestureListener() { - @Override - public boolean onDoubleTap(MotionEvent e) { - view.startMonitoringRegion(); - return false; - } @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, @@ -157,7 +141,6 @@ public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, if (handlePanDrag) { onPanDrag(e2); } - view.startMonitoringRegion(); return false; } }); @@ -272,14 +255,32 @@ public void onMapLongClick(LatLng point) { } }); - map.setOnCameraChangeListener(new GoogleMap.OnCameraChangeListener() { + map.setOnCameraMoveStartedListener(new GoogleMap.OnCameraMoveStartedListener() { + @Override + public void onCameraMoveStarted(int reason) { + cameraMoveReason = reason; + } + }); + + map.setOnCameraMoveListener(new GoogleMap.OnCameraMoveListener() { @Override - public void onCameraChange(CameraPosition position) { + public void onCameraMove() { LatLngBounds bounds = map.getProjection().getVisibleRegion().latLngBounds; - LatLng center = position.target; - lastBoundsEmitted = bounds; - eventDispatcher.dispatchEvent(new RegionChangeEvent(getId(), bounds, center, isTouchDown)); - view.stopMonitoringRegion(); + cameraLastIdleBounds = null; + eventDispatcher.dispatchEvent(new RegionChangeEvent(getId(), bounds, true)); + } + }); + + map.setOnCameraIdleListener(new GoogleMap.OnCameraIdleListener() { + @Override + public void onCameraIdle() { + LatLngBounds bounds = map.getProjection().getVisibleRegion().latLngBounds; + if ((cameraMoveReason != 0) && + ((cameraLastIdleBounds == null) || + LatLngBoundsUtils.BoundsAreDifferent(bounds, cameraLastIdleBounds))) { + cameraLastIdleBounds = bounds; + eventDispatcher.dispatchEvent(new RegionChangeEvent(getId(), bounds, false)); + } } }); @@ -566,14 +567,12 @@ public void updateExtraData(Object extraData) { public void animateToRegion(LatLngBounds bounds, int duration) { if (map != null) { - startMonitoringRegion(); map.animateCamera(CameraUpdateFactory.newLatLngBounds(bounds, 0), duration, null); } } public void animateToViewingAngle(float angle, int duration) { if (map != null) { - startMonitoringRegion(); CameraPosition cameraPosition = new CameraPosition.Builder(map.getCameraPosition()) .tilt(angle) .build(); @@ -583,7 +582,6 @@ public void animateToViewingAngle(float angle, int duration) { public void animateToBearing(float bearing, int duration) { if (map != null) { - startMonitoringRegion(); CameraPosition cameraPosition = new CameraPosition.Builder(map.getCameraPosition()) .bearing(bearing) .build(); @@ -593,7 +591,6 @@ public void animateToBearing(float bearing, int duration) { public void animateToCoordinate(LatLng coordinate, int duration) { if (map != null) { - startMonitoringRegion(); map.animateCamera(CameraUpdateFactory.newLatLng(coordinate), duration, null); } } @@ -615,7 +612,6 @@ public void fitToElements(boolean animated) { LatLngBounds bounds = builder.build(); CameraUpdate cu = CameraUpdateFactory.newLatLngBounds(bounds, baseMapPadding); if (animated) { - startMonitoringRegion(); map.animateCamera(cu); } else { map.moveCamera(cu); @@ -650,7 +646,6 @@ public void fitToSuppliedMarkers(ReadableArray markerIDsArray, boolean animated) LatLngBounds bounds = builder.build(); CameraUpdate cu = CameraUpdateFactory.newLatLngBounds(bounds, baseMapPadding); if (animated) { - startMonitoringRegion(); map.animateCamera(cu); } else { map.moveCamera(cu); @@ -678,7 +673,6 @@ public void fitToCoordinates(ReadableArray coordinatesArray, ReadableMap edgePad } if (animated) { - startMonitoringRegion(); map.animateCamera(cu); } else { map.moveCamera(cu); @@ -703,7 +697,6 @@ public View getInfoContents(Marker marker) { @Override public boolean dispatchTouchEvent(MotionEvent ev) { - scaleDetector.onTouchEvent(ev); gestureDetector.onTouchEvent(ev); int action = MotionEventCompat.getActionMasked(ev); @@ -712,61 +705,16 @@ public boolean dispatchTouchEvent(MotionEvent ev) { case (MotionEvent.ACTION_DOWN): this.getParent().requestDisallowInterceptTouchEvent( map != null && map.getUiSettings().isScrollGesturesEnabled()); - isTouchDown = true; - break; - case (MotionEvent.ACTION_MOVE): - startMonitoringRegion(); break; case (MotionEvent.ACTION_UP): // Clear this regardless, since isScrollGesturesEnabled() may have been updated this.getParent().requestDisallowInterceptTouchEvent(false); - isTouchDown = false; break; } super.dispatchTouchEvent(ev); return true; } - // Timer Implementation - - public void startMonitoringRegion() { - if (map == null || isMonitoringRegion) return; - timerHandler.postDelayed(timerRunnable, 100); - isMonitoringRegion = true; - } - - public void stopMonitoringRegion() { - if (map == null || !isMonitoringRegion) return; - timerHandler.removeCallbacks(timerRunnable); - isMonitoringRegion = false; - } - - private LatLngBounds lastBoundsEmitted; - - Handler timerHandler = new Handler(); - Runnable timerRunnable = new Runnable() { - - @Override - public void run() { - - if (map != null) { - Projection projection = map.getProjection(); - VisibleRegion region = (projection != null) ? projection.getVisibleRegion() : null; - LatLngBounds bounds = (region != null) ? region.latLngBounds : null; - - if ((bounds != null) && - (lastBoundsEmitted == null || - LatLngBoundsUtils.BoundsAreDifferent(bounds, lastBoundsEmitted))) { - LatLng center = map.getCameraPosition().target; - lastBoundsEmitted = bounds; - eventDispatcher.dispatchEvent(new RegionChangeEvent(getId(), bounds, center, true)); - } - } - - timerHandler.postDelayed(this, 100); - } - }; - @Override public void onMarkerDragStart(Marker marker) { WritableMap event = makeClickEventData(marker.getPosition()); diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/RegionChangeEvent.java b/lib/android/src/main/java/com/airbnb/android/react/maps/RegionChangeEvent.java index 43b1f678e..675eb4106 100644 --- a/lib/android/src/main/java/com/airbnb/android/react/maps/RegionChangeEvent.java +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/RegionChangeEvent.java @@ -9,13 +9,11 @@ public class RegionChangeEvent extends Event { private final LatLngBounds bounds; - private final LatLng center; private final boolean continuous; - public RegionChangeEvent(int id, LatLngBounds bounds, LatLng center, boolean continuous) { + public RegionChangeEvent(int id, LatLngBounds bounds, boolean continuous) { super(id); this.bounds = bounds; - this.center = center; this.continuous = continuous; } @@ -36,6 +34,7 @@ public void dispatch(RCTEventEmitter rctEventEmitter) { event.putBoolean("continuous", continuous); WritableMap region = new WritableNativeMap(); + LatLng center = bounds.getCenter(); region.putDouble("latitude", center.latitude); region.putDouble("longitude", center.longitude); region.putDouble("latitudeDelta", bounds.northeast.latitude - bounds.southwest.latitude); From 1713d1a7226a82b7eec0dc795f22457e249bf238 Mon Sep 17 00:00:00 2001 From: Nick McIntosh Date: Wed, 29 Nov 2017 05:34:06 +1100 Subject: [PATCH 0329/1148] Enable control of Google Maps Marker tracksViewChanges property. (#1705) Fixes issue #1031, enabling use of custom marker images and views in Google Maps on iOS and android. As detailed in the Google Maps Marker documentation (kudos to @hughvidos), map markers track view changes by default. This has meant however that custom marker images or views on iOS and android, when using Google Maps, cause high continuous CPU load. The recommended use of tracksViewChanges is to enable when the marker is being rendered or animated, then to disable it. An example of use of tracksViewChanges would be to set it to false once onMapReady has fired. This can be accomplished by toggling a state property (e.g. `initialized`), and passing it to the child map markers in their `tracksViewChanges` prop. Markers would then render correctly on map load; CPU use falls off once the tracking ceases. --- lib/components/MapMarker.js | 12 +++++++++++- lib/ios/AirGoogleMaps/AIRGoogleMapMarker.h | 1 + lib/ios/AirGoogleMaps/AIRGoogleMapMarker.m | 9 +++++++++ lib/ios/AirGoogleMaps/AIRGoogleMapMarkerManager.m | 1 + 4 files changed, 22 insertions(+), 1 deletion(-) diff --git a/lib/components/MapMarker.js b/lib/components/MapMarker.js index b81bab87a..ecacc0a43 100644 --- a/lib/components/MapMarker.js +++ b/lib/components/MapMarker.js @@ -165,6 +165,14 @@ const propTypes = { draggable: PropTypes.bool, + /** + * Sets whether this marker should track view changes true. + * + * @platform ios + */ + + tracksViewChanges: PropTypes.bool, + /** * Callback that is called when the user presses on the marker */ @@ -264,7 +272,9 @@ class MapMarker extends React.Component { return ( { this.marker = ref; }} + ref={ref => { + this.marker = ref; + }} {...this.props} image={image} style={[styles.marker, this.props.style]} diff --git a/lib/ios/AirGoogleMaps/AIRGoogleMapMarker.h b/lib/ios/AirGoogleMaps/AIRGoogleMapMarker.h index 298884f7d..1cb4d2659 100644 --- a/lib/ios/AirGoogleMaps/AIRGoogleMapMarker.h +++ b/lib/ios/AirGoogleMaps/AIRGoogleMapMarker.h @@ -31,6 +31,7 @@ @property (nonatomic, assign) NSInteger zIndex; @property (nonatomic, assign) double opacity; @property (nonatomic, assign) BOOL draggable; +@property (nonatomic, assign) BOOL tracksViewChanges; - (void)showCalloutView; - (void)hideCalloutView; diff --git a/lib/ios/AirGoogleMaps/AIRGoogleMapMarker.m b/lib/ios/AirGoogleMaps/AIRGoogleMapMarker.m index c41be55bb..42cf016a9 100644 --- a/lib/ios/AirGoogleMaps/AIRGoogleMapMarker.m +++ b/lib/ios/AirGoogleMaps/AIRGoogleMapMarker.m @@ -36,6 +36,7 @@ - (instancetype)init if ((self = [super init])) { _realMarker = [[AIRGMSMarker alloc] init]; _realMarker.fakeMarker = self; + _realMarker.tracksViewChanges = true; } return self; } @@ -295,4 +296,12 @@ - (BOOL)draggable { return _realMarker.draggable; } +- (void)setTracksViewChanges:(BOOL)tracksViewChanges { + _realMarker.tracksViewChanges = tracksViewChanges; +} + +- (BOOL)tracksViewChanges { + return _realMarker.tracksViewChanges; +} + @end diff --git a/lib/ios/AirGoogleMaps/AIRGoogleMapMarkerManager.m b/lib/ios/AirGoogleMaps/AIRGoogleMapMarkerManager.m index b5572bf9d..6b9c8f64b 100644 --- a/lib/ios/AirGoogleMaps/AIRGoogleMapMarkerManager.m +++ b/lib/ios/AirGoogleMaps/AIRGoogleMapMarkerManager.m @@ -37,6 +37,7 @@ - (UIView *)view RCT_EXPORT_VIEW_PROPERTY(anchor, CGPoint) RCT_EXPORT_VIEW_PROPERTY(zIndex, NSInteger) RCT_EXPORT_VIEW_PROPERTY(draggable, BOOL) +RCT_EXPORT_VIEW_PROPERTY(tracksViewChanges, BOOL) RCT_EXPORT_VIEW_PROPERTY(opacity, double) RCT_EXPORT_VIEW_PROPERTY(onDragStart, RCTDirectEventBlock) RCT_EXPORT_VIEW_PROPERTY(onDrag, RCTDirectEventBlock) From 9b6946ab66de989d908fec4a7dba213cb95e44d2 Mon Sep 17 00:00:00 2001 From: Hein Rutjes Date: Tue, 28 Nov 2017 19:42:41 +0100 Subject: [PATCH 0330/1148] Added new iOS `mutedStandard` map-type (#1824) * Added new iOS `mutedStandard` map-type * Update MapView.js --- docs/mapview.md | 2 +- index.d.ts | 2 +- lib/components/MapView.js | 1 + lib/ios/AirMaps/RCTConvert+AirMap.m | 3 +++ 4 files changed, 6 insertions(+), 2 deletions(-) diff --git a/docs/mapview.md b/docs/mapview.md index 2aa6a7086..6bd430839 100644 --- a/docs/mapview.md +++ b/docs/mapview.md @@ -8,7 +8,7 @@ | `region` | `Region` | | The region to be displayed by the map.

The region is defined by the center coordinates and the span of coordinates to display. | `initialRegion` | `Region` | | The initial region to be displayed by the map. Use this prop instead of `region` only if you don't want to control the viewport of the map besides the initial region.

Changing this prop after the component has mounted will not result in a region change.

This is similar to the `initialValue` prop of a text input. | `liteMode` | `Boolean` | `false` | Enable lite mode. **Note**: Android only. -| `mapType` | `String` | `"standard"` | The map type to be displayed.

- standard: standard road map (default)
- satellite: satellite view
- hybrid: satellite view with roads and points of interest overlayed
- terrain: (Android only) topographic view +| `mapType` | `String` | `"standard"` | The map type to be displayed.

- standard: standard road map (default)
- satellite: satellite view
- hybrid: satellite view with roads and points of interest overlayed
- terrain: (Android only) topographic view
- standardMuted: more subtle, makes markers/lines pop more (iOS only) | `customMapStyle` | `Array` | | Adds custom styling to the map component. See [README](https://github.com/airbnb/react-native-maps#customizing-the-map-style) for more information. | `showsUserLocation` | `Boolean` | `false` | If `true` the app will ask for the user's location. **NOTE**: You need to add `NSLocationWhenInUseUsageDescription` key in Info.plist to enable geolocation, otherwise it is going to *fail silently*! | `userLocationAnnotationTitle` | `String` | | The title of the annotation for current user location. This only works if `showsUserLocation` is true. There is a default value `My Location` set by MapView. **Note**: iOS only. diff --git a/index.d.ts b/index.d.ts index 75e976ee1..bdc2075e4 100644 --- a/index.d.ts +++ b/index.d.ts @@ -26,7 +26,7 @@ interface MapViewProps { showsTraffic?: boolean; showsIndoors?: boolean; showsIndoorLevelPicker?: boolean; - mapType?: 'standard' | 'satellite' | 'hybrid' | 'terrain' | 'none'; + mapType?: 'standard' | 'satellite' | 'hybrid' | 'terrain' | 'none' | 'mutedStandard'; region?: { latitude: number; longitude: number; latitudeDelta: number; longitudeDelta: number; }; initialRegion?: { latitude: number; longitude: number; latitudeDelta: number; longitudeDelta: number; }; liteMode?: boolean; diff --git a/lib/components/MapView.js b/lib/components/MapView.js index eec576291..63eba2cc9 100644 --- a/lib/components/MapView.js +++ b/lib/components/MapView.js @@ -32,6 +32,7 @@ const MAP_TYPES = { HYBRID: 'hybrid', TERRAIN: 'terrain', NONE: 'none', + MUTEDSTANDARD: 'mutedStandard', }; const GOOGLE_MAPS_ONLY_TYPES = [ diff --git a/lib/ios/AirMaps/RCTConvert+AirMap.m b/lib/ios/AirMaps/RCTConvert+AirMap.m index cfdbb17ce..42c916193 100644 --- a/lib/ios/AirMaps/RCTConvert+AirMap.m +++ b/lib/ios/AirMaps/RCTConvert+AirMap.m @@ -31,6 +31,9 @@ + (MKCoordinateRegion)MKCoordinateRegion:(id)json @"standard": @(MKMapTypeStandard), @"satellite": @(MKMapTypeSatellite), @"hybrid": @(MKMapTypeHybrid), + @"satelliteFlyover": @(MKMapTypeSatelliteFlyover), + @"hybridFlyover": @(MKMapTypeHybridFlyover), + @"mutedStandard": @(MKMapTypeMutedStandard) }), MKMapTypeStandard, integerValue) // NOTE(lmr): From 07994f0a4c604247147ca40067bc06c27d4cc74e Mon Sep 17 00:00:00 2001 From: brunsy Date: Wed, 29 Nov 2017 07:46:11 +1300 Subject: [PATCH 0331/1148] added missing parameters to google map screenshot (#1774) --- lib/ios/AirGoogleMaps/AIRGoogleMapManager.m | 63 +++++++++++++++------ 1 file changed, 47 insertions(+), 16 deletions(-) diff --git a/lib/ios/AirGoogleMaps/AIRGoogleMapManager.m b/lib/ios/AirGoogleMaps/AIRGoogleMapManager.m index 043841305..8358bb188 100644 --- a/lib/ios/AirGoogleMaps/AIRGoogleMapManager.m +++ b/lib/ios/AirGoogleMaps/AIRGoogleMapManager.m @@ -231,34 +231,65 @@ - (UIView *)view withWidth:(nonnull NSNumber *)width withHeight:(nonnull NSNumber *)height withRegion:(MKCoordinateRegion)region + format:(nonnull NSString *)format + quality:(nonnull NSNumber *)quality + result:(nonnull NSString *)result withCallback:(RCTResponseSenderBlock)callback) { + NSTimeInterval timeStamp = [[NSDate date] timeIntervalSince1970]; + NSString *pathComponent = [NSString stringWithFormat:@"Documents/snapshot-%.20lf.%@", timeStamp, format]; + NSString *filePath = [NSHomeDirectory() stringByAppendingPathComponent: pathComponent]; + [self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary *viewRegistry) { id view = viewRegistry[reactTag]; if (![view isKindOfClass:[AIRGoogleMap class]]) { - RCTLogError(@"Invalid view returned from registry, expecting AIRMap, got: %@", view); + RCTLogError(@"Invalid view returned from registry, expecting AIRMap, got: %@", view); } else { AIRGoogleMap *mapView = (AIRGoogleMap *)view; - + // TODO: currently we are ignoring width, height, region - + UIGraphicsBeginImageContextWithOptions(mapView.frame.size, YES, 0.0f); [mapView.layer renderInContext:UIGraphicsGetCurrentContext()]; UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); - UIGraphicsEndImageContext(); - - NSTimeInterval timeStamp = [[NSDate date] timeIntervalSince1970]; - NSString *pathComponent = [NSString stringWithFormat:@"Documents/snapshot-%.20lf.png", timeStamp]; - NSString *filePath = [NSHomeDirectory() stringByAppendingPathComponent: pathComponent]; - - NSData *data = UIImagePNGRepresentation(image); - [data writeToFile:filePath atomically:YES]; - NSDictionary *snapshotData = @{ - @"uri": filePath, - @"data": [data base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithCarriageReturn] - }; - callback(@[[NSNull null], snapshotData]); + + NSData *data; + if ([format isEqualToString:@"png"]) { + data = UIImagePNGRepresentation(image); + + } + else if([format isEqualToString:@"jpg"]) { + data = UIImageJPEGRepresentation(image, quality.floatValue); + } + + if ([result isEqualToString:@"file"]) { + [data writeToFile:filePath atomically:YES]; + callback(@[[NSNull null], filePath]); + } + else if ([result isEqualToString:@"base64"]) { + callback(@[[NSNull null], [data base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithCarriageReturn]]); + } + else if ([result isEqualToString:@"legacy"]) { + + // In the initial (iOS only) implementation of takeSnapshot, + // both the uri and the base64 encoded string were returned. + // Returning both is rarely useful and in fact causes a + // performance penalty when only the file URI is desired. + // In that case the base64 encoded string was always marshalled + // over the JS-bridge (which is quite slow). + // A new more flexible API was created to cover this. + // This code should be removed in a future release when the + // old API is fully deprecated. + [data writeToFile:filePath atomically:YES]; + NSDictionary *snapshotData = @{ + @"uri": filePath, + @"data": [data base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithCarriageReturn] + }; + callback(@[[NSNull null], snapshotData]); + } + } + UIGraphicsEndImageContext(); }]; } From 94be5dcdb29a15528b9d2d5b8e6187bb83a467b5 Mon Sep 17 00:00:00 2001 From: Mark Rickert Date: Tue, 28 Nov 2017 12:32:27 -0700 Subject: [PATCH 0332/1148] Fixes issue running on ReactNative 0.42.3 - 'MapMarker' has no propType for native prop 'AIRMapMarker.testId' of native type 'String' (#1792) * Be less specific about react-native version for android * Relax play services dependencies as well * Fixes issue with ReactNative 0.42.3 * Update MapMarker.js * Make all components use ViewPropTypes || View.propTypes --- lib/components/MapCallout.js | 6 +++++- lib/components/MapCircle.js | 6 +++++- lib/components/MapMarker.js | 6 +++++- lib/components/MapPolygon.js | 6 +++++- lib/components/MapPolyline.js | 6 +++++- lib/components/MapUrlTile.js | 6 +++++- lib/components/MapView.js | 2 +- 7 files changed, 31 insertions(+), 7 deletions(-) diff --git a/lib/components/MapCallout.js b/lib/components/MapCallout.js index 226b52fe2..2ef73a096 100644 --- a/lib/components/MapCallout.js +++ b/lib/components/MapCallout.js @@ -3,14 +3,18 @@ import React from 'react'; import { StyleSheet, ViewPropTypes, + View, } from 'react-native'; import decorateMapComponent, { SUPPORTED, USES_DEFAULT_IMPLEMENTATION, } from './decorateMapComponent'; +// if ViewPropTypes is not defined fall back to View.propType (to support RN < 0.44) +const viewPropTypes = ViewPropTypes || View.propTypes; + const propTypes = { - ...ViewPropTypes, + ...viewPropTypes, tooltip: PropTypes.bool, onPress: PropTypes.func, }; diff --git a/lib/components/MapCircle.js b/lib/components/MapCircle.js index acf066b24..c0c23a5ad 100644 --- a/lib/components/MapCircle.js +++ b/lib/components/MapCircle.js @@ -2,14 +2,18 @@ import PropTypes from 'prop-types'; import React from 'react'; import { ViewPropTypes, + View, } from 'react-native'; import decorateMapComponent, { USES_DEFAULT_IMPLEMENTATION, SUPPORTED, } from './decorateMapComponent'; +// if ViewPropTypes is not defined fall back to View.propType (to support RN < 0.44) +const viewPropTypes = ViewPropTypes || View.propTypes; + const propTypes = { - ...ViewPropTypes, + ...viewPropTypes, /** * The coordinate of the center of the circle diff --git a/lib/components/MapMarker.js b/lib/components/MapMarker.js index ecacc0a43..a2f809f58 100644 --- a/lib/components/MapMarker.js +++ b/lib/components/MapMarker.js @@ -7,6 +7,7 @@ import { Animated, findNodeHandle, ViewPropTypes, + View, } from 'react-native'; import resolveAssetSource from 'react-native/Libraries/Image/resolveAssetSource'; @@ -22,8 +23,11 @@ const viewConfig = { }, }; +// if ViewPropTypes is not defined fall back to View.propType (to support RN < 0.44) +const viewPropTypes = ViewPropTypes || View.propTypes; + const propTypes = { - ...ViewPropTypes, + ...viewPropTypes, // TODO(lmr): get rid of these? identifier: PropTypes.string, diff --git a/lib/components/MapPolygon.js b/lib/components/MapPolygon.js index 27f2aa322..c6daeae86 100644 --- a/lib/components/MapPolygon.js +++ b/lib/components/MapPolygon.js @@ -2,14 +2,18 @@ import PropTypes from 'prop-types'; import React from 'react'; import { ViewPropTypes, + View, } from 'react-native'; import decorateMapComponent, { USES_DEFAULT_IMPLEMENTATION, SUPPORTED, } from './decorateMapComponent'; +// if ViewPropTypes is not defined fall back to View.propType (to support RN < 0.44) +const viewPropTypes = ViewPropTypes || View.propTypes; + const propTypes = { - ...ViewPropTypes, + ...viewPropTypes, /** * An array of coordinates to describe the polygon diff --git a/lib/components/MapPolyline.js b/lib/components/MapPolyline.js index af1573eff..2bdfe8d26 100644 --- a/lib/components/MapPolyline.js +++ b/lib/components/MapPolyline.js @@ -2,14 +2,18 @@ import PropTypes from 'prop-types'; import React from 'react'; import { ViewPropTypes, + View, } from 'react-native'; import decorateMapComponent, { USES_DEFAULT_IMPLEMENTATION, SUPPORTED, } from './decorateMapComponent'; +// if ViewPropTypes is not defined fall back to View.propType (to support RN < 0.44) +const viewPropTypes = ViewPropTypes || View.propTypes; + const propTypes = { - ...ViewPropTypes, + ...viewPropTypes, /** * An array of coordinates to describe the polygon diff --git a/lib/components/MapUrlTile.js b/lib/components/MapUrlTile.js index f61c1e0d3..a2b49e960 100644 --- a/lib/components/MapUrlTile.js +++ b/lib/components/MapUrlTile.js @@ -3,6 +3,7 @@ import React from 'react'; import { ViewPropTypes, + View, } from 'react-native'; import decorateMapComponent, { @@ -10,8 +11,11 @@ import decorateMapComponent, { SUPPORTED, } from './decorateMapComponent'; +// if ViewPropTypes is not defined fall back to View.propType (to support RN < 0.44) +const viewPropTypes = ViewPropTypes || View.propTypes; + const propTypes = { - ...ViewPropTypes, + ...viewPropTypes, /** * The url template of the tile server. The patterns {x} {y} {z} will be replaced at runtime diff --git a/lib/components/MapView.js b/lib/components/MapView.js index 63eba2cc9..611701ca1 100644 --- a/lib/components/MapView.js +++ b/lib/components/MapView.js @@ -8,8 +8,8 @@ import { NativeModules, ColorPropType, findNodeHandle, - View, ViewPropTypes, + View, } from 'react-native'; import MapMarker from './MapMarker'; import MapPolyline from './MapPolyline'; From bf40f069f11a1b173a8de44c85fc7808026c8fa2 Mon Sep 17 00:00:00 2001 From: Peter Juras Date: Tue, 28 Nov 2017 21:36:04 +0100 Subject: [PATCH 0333/1148] Add mapPadding property (#1750) * Add mapPadding property * Fix trailing whitespace in MapView comments --- .../android/react/maps/AirMapManager.java | 29 +++++++++++++++++++ lib/components/MapView.js | 9 ++++++ lib/ios/AirGoogleMaps/AIRGoogleMap.h | 1 + lib/ios/AirGoogleMaps/AIRGoogleMap.m | 7 +++++ lib/ios/AirGoogleMaps/AIRGoogleMapManager.m | 1 + 5 files changed, 47 insertions(+) diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java index 6749e9a85..91413f84c 100644 --- a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java @@ -93,6 +93,35 @@ public void setMapStyle(AirMapView view, @Nullable String customMapStyleString) view.map.setMapStyle(new MapStyleOptions(customMapStyleString)); } + @ReactProp(name = "mapPadding") + public void setMapPadding(AirMapView view, @Nullable ReadableMap padding) { + int left = 0; + int top = 0; + int right = 0; + int bottom = 0; + double density = (double) view.getResources().getDisplayMetrics().density; + + if (padding != null) { + if (padding.hasKey("left")) { + left = (int) (padding.getDouble("left") * density); + } + + if (padding.hasKey("top")) { + top = (int) (padding.getDouble("top") * density); + } + + if (padding.hasKey("right")) { + right = (int) (padding.getDouble("right") * density); + } + + if (padding.hasKey("bottom")) { + bottom = (int) (padding.getDouble("bottom") * density); + } + } + + view.map.setPadding(left, top, right, bottom); + } + @ReactProp(name = "showsUserLocation", defaultBoolean = false) public void setShowsUserLocation(AirMapView view, boolean showUserLocation) { view.setShowsUserLocation(showUserLocation); diff --git a/lib/components/MapView.js b/lib/components/MapView.js index 611701ca1..9ebf171a7 100644 --- a/lib/components/MapView.js +++ b/lib/components/MapView.js @@ -303,6 +303,15 @@ const propTypes = { */ liteMode: PropTypes.bool, + /** + * (Google Maps only) + * + * Padding that is used by the Google Map View to position + * the camera, legal labels and buttons + * + */ + mapPadding: EdgeInsetsPropType, + /** * Maximum size of area that can be displayed. * diff --git a/lib/ios/AirGoogleMaps/AIRGoogleMap.h b/lib/ios/AirGoogleMaps/AIRGoogleMap.h index fa0293ae3..29f71a3a4 100644 --- a/lib/ios/AirGoogleMaps/AIRGoogleMap.h +++ b/lib/ios/AirGoogleMaps/AIRGoogleMap.h @@ -18,6 +18,7 @@ @property (nonatomic, assign) MKCoordinateRegion initialRegion; @property (nonatomic, assign) MKCoordinateRegion region; @property (nonatomic, assign) NSString *customMapStyleString; +@property (nonatomic, assign) UIEdgeInsets mapPadding; @property (nonatomic, copy) RCTBubblingEventBlock onMapReady; @property (nonatomic, copy) RCTBubblingEventBlock onPress; @property (nonatomic, copy) RCTBubblingEventBlock onLongPress; diff --git a/lib/ios/AirGoogleMaps/AIRGoogleMap.m b/lib/ios/AirGoogleMaps/AIRGoogleMap.m index 4c1976fe7..c7c57663e 100644 --- a/lib/ios/AirGoogleMaps/AIRGoogleMap.m +++ b/lib/ios/AirGoogleMaps/AIRGoogleMap.m @@ -219,6 +219,13 @@ - (void)idleAtCameraPosition:(GMSCameraPosition *)position { if (self.onChange) self.onChange(event); // complete } +- (void)setMapPadding:(UIEdgeInsets)mapPadding { + self.padding = mapPadding; +} + +- (UIEdgeInsets)mapPadding { + return self.padding; +} - (void)setScrollEnabled:(BOOL)scrollEnabled { self.settings.scrollGestures = scrollEnabled; diff --git a/lib/ios/AirGoogleMaps/AIRGoogleMapManager.m b/lib/ios/AirGoogleMaps/AIRGoogleMapManager.m index 8358bb188..99e16d77c 100644 --- a/lib/ios/AirGoogleMaps/AIRGoogleMapManager.m +++ b/lib/ios/AirGoogleMaps/AIRGoogleMapManager.m @@ -63,6 +63,7 @@ - (UIView *)view RCT_EXPORT_VIEW_PROPERTY(showsMyLocationButton, BOOL) RCT_EXPORT_VIEW_PROPERTY(showsIndoorLevelPicker, BOOL) RCT_EXPORT_VIEW_PROPERTY(customMapStyleString, NSString) +RCT_EXPORT_VIEW_PROPERTY(mapPadding, UIEdgeInsets) RCT_EXPORT_VIEW_PROPERTY(onMapReady, RCTBubblingEventBlock) RCT_EXPORT_VIEW_PROPERTY(onPress, RCTBubblingEventBlock) RCT_EXPORT_VIEW_PROPERTY(onLongPress, RCTBubblingEventBlock) From d23dd6131cadbbec531eb67a03389da679814995 Mon Sep 17 00:00:00 2001 From: Andre Shonubi Date: Tue, 28 Nov 2017 15:38:25 -0500 Subject: [PATCH 0334/1148] Add support to set map boundaries (#1587) * Add setMapBoundaries method iOS * Add setMapBoundaries method android * Add setMapBoundaries method to MapView component * Update MapView docs * Add note to setMapBoundaries method --- docs/mapview.md | 1 + .../android/react/maps/AirMapManager.java | 14 +++++++++++--- .../airbnb/android/react/maps/AirMapView.java | 18 ++++++++++++++++++ lib/components/MapView.js | 4 ++++ lib/ios/AirGoogleMaps/AIRGoogleMapManager.m | 18 ++++++++++++++++++ 5 files changed, 52 insertions(+), 3 deletions(-) diff --git a/docs/mapview.md b/docs/mapview.md index 6bd430839..86ddbff0f 100644 --- a/docs/mapview.md +++ b/docs/mapview.md @@ -66,6 +66,7 @@ To access event data, you will need to use `e.nativeEvent`. For example, `onPres | `animateToCoordinate` | `coordinate: LatLng`, `duration: Number` | | `animateToBearing` | `bearing: Number`, `duration: Number` | | `animateToViewingAngle` | `angle: Number`, `duration: Number` | +| `setMapBoundaries` | `northEast: LatLng`, `southWest: LatLng` | `GoogleMaps only` | `fitToElements` | `animated: Boolean` | | `fitToSuppliedMarkers` | `markerIDs: String[]`, `animated: Boolean` | If you need to use this in `ComponentDidMount`, make sure you put it in a timeout or it will cause performance problems. | `fitToCoordinates` | `coordinates: Array, options: { edgePadding: EdgePadding, animated: Boolean }` | If called in `ComponentDidMount` in android, it will cause an exception. It is recommended to call it from the MapView `onLayout` event. diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java index 91413f84c..9022b1efc 100644 --- a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java @@ -34,6 +34,8 @@ public class AirMapManager extends ViewGroupManager { private static final int FIT_TO_ELEMENTS = 5; private static final int FIT_TO_SUPPLIED_MARKERS = 6; private static final int FIT_TO_COORDINATES = 7; + private static final int SET_MAP_BOUNDARIES = 8; + private final Map MAP_TYPES = MapBuilder.of( "standard", GoogleMap.MAP_TYPE_NORMAL, @@ -263,13 +265,13 @@ public void receiveCommand(AirMapView view, int commandId, @Nullable ReadableArr duration = args.getInt(1); view.animateToViewingAngle(angle, duration); break; - + case ANIMATE_TO_BEARING: bearing = (float)args.getDouble(0); duration = args.getInt(1); view.animateToBearing(bearing, duration); break; - + case FIT_TO_ELEMENTS: view.fitToElements(args.getBoolean(0)); break; @@ -277,9 +279,14 @@ public void receiveCommand(AirMapView view, int commandId, @Nullable ReadableArr case FIT_TO_SUPPLIED_MARKERS: view.fitToSuppliedMarkers(args.getArray(0), args.getBoolean(1)); break; + case FIT_TO_COORDINATES: view.fitToCoordinates(args.getArray(0), args.getMap(1), args.getBoolean(2)); break; + + case SET_MAP_BOUNDARIES: + view.setMapBoundaries(args.getMap(0), args.getMap(1)); + break; } } @@ -316,7 +323,8 @@ public Map getCommandsMap() { "animateToBearing", ANIMATE_TO_BEARING, "fitToElements", FIT_TO_ELEMENTS, "fitToSuppliedMarkers", FIT_TO_SUPPLIED_MARKERS, - "fitToCoordinates", FIT_TO_COORDINATES + "fitToCoordinates", FIT_TO_COORDINATES, + "setMapBoundaries", SET_MAP_BOUNDARIES ); } diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java index fa2f63646..aece720a8 100644 --- a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java @@ -681,6 +681,24 @@ public void fitToCoordinates(ReadableArray coordinatesArray, ReadableMap edgePad 0); // Without this, the Google logo is moved up by the value of edgePadding.bottom } + public void setMapBoundaries(ReadableMap northEast, ReadableMap southWest) { + LatLngBounds.Builder builder = new LatLngBounds.Builder(); + + Double latNE = northEast.getDouble("latitude"); + Double lngNE = northEast.getDouble("longitude"); + builder.include(new LatLng(latNE, lngNE)); + + Double latSW = southWest.getDouble("latitude"); + Double lngSW = southWest.getDouble("longitude"); + builder.include(new LatLng(latSW, lngSW)); + + LatLngBounds bounds = builder.build(); + + if (map != null) { + map.setLatLngBoundsForCameraTarget(bounds); + } + } + // InfoWindowAdapter interface @Override diff --git a/lib/components/MapView.js b/lib/components/MapView.js index 9ebf171a7..74742e018 100644 --- a/lib/components/MapView.js +++ b/lib/components/MapView.js @@ -541,6 +541,10 @@ class MapView extends React.Component { this._runCommand('fitToCoordinates', [coordinates, edgePadding, animated]); } + setMapBoundaries(northEast, southWest) { + this._runCommand('setMapBoundaries', [northEast, southWest]); + } + /** * Takes a snapshot of the map and saves it to a picture * file or returns the image as a base64 encoded string. diff --git a/lib/ios/AirGoogleMaps/AIRGoogleMapManager.m b/lib/ios/AirGoogleMaps/AIRGoogleMapManager.m index 99e16d77c..5045deb75 100644 --- a/lib/ios/AirGoogleMaps/AIRGoogleMapManager.m +++ b/lib/ios/AirGoogleMaps/AIRGoogleMapManager.m @@ -294,6 +294,24 @@ - (UIView *)view }]; } +RCT_EXPORT_METHOD(setMapBoundaries:(nonnull NSNumber *)reactTag + northEast:(CLLocationCoordinate2D)northEast + southWest:(CLLocationCoordinate2D)southWest) +{ + [self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary *viewRegistry) { + id view = viewRegistry[reactTag]; + if (![view isKindOfClass:[AIRGoogleMap class]]) { + RCTLogError(@"Invalid view returned from registry, expecting AIRGoogleMap, got: %@", view); + } else { + AIRGoogleMap *mapView = (AIRGoogleMap *)view; + + GMSCoordinateBounds *bounds = [[GMSCoordinateBounds alloc] initWithCoordinate:northEast coordinate:southWest]; + + mapView.cameraTargetBounds = bounds; + } + }]; +} + - (NSDictionary *)constantsToExport { return @{ @"legalNotice": [GMSServices openSourceLicenseInfo] }; } From 42eba66eaf410b16d62734ffcb8307d6eff75fb4 Mon Sep 17 00:00:00 2001 From: abiduzz420 Date: Wed, 29 Nov 2017 02:10:14 +0530 Subject: [PATCH 0335/1148] Blank map issue, Google Maps API not enabled (#1706) You need to enable Google maps API in the google developer console for android/ios --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 91b22377b..e11e91b88 100644 --- a/README.md +++ b/README.md @@ -452,6 +452,7 @@ Pass an array of coordinates to focus a map region on said coordinates. * Make sure that you have [properly installed](docs/installation.md) react-native-maps. * Check in the logs if there is more informations about the issue. * Try setting the style of the MapView to an absolute position with top, left, right and bottom values set. +* Make sure you have enabled Google Maps API in ![Google developer console](https://console.developers.google.com/apis/library) ```javascript const styles = StyleSheet.create({ From fe2dc2bbadf01fbf522e04d89b6ba14a6d7539d5 Mon Sep 17 00:00:00 2001 From: Christopher Dro Date: Tue, 28 Nov 2017 15:11:08 -0800 Subject: [PATCH 0336/1148] v0.18.0 --- CHANGELOG.md | 16 ++++++++++++++++ example/ios/Podfile.lock | 4 ++-- lib/android/gradle.properties | 2 +- package.json | 2 +- 4 files changed, 20 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f61819749..a5829365b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,21 @@ # Change Log +## 0.18.0 (November 28, 2017) +* Android/iOS: [#1587](https://github.com/airbnb/react-native-maps/pull/1750) Add support to set map boundaries +* Android/iOS: [#1750](https://github.com/airbnb/react-native-maps/pull/1750) Add mapPadding property +* Common: [#1792](https://github.com/airbnb/react-native-maps/pull/1792) Make all components use ViewPropTypes || View.propTypes +* iOS: [#1774](https://github.com/airbnb/react-native-maps/pull/1774) Added missing parameters to google map screenshot +* iOS: [#1824](https://github.com/airbnb/react-native-maps/pull/1824) Add new iOS `mutedStandard` map-type +* iOS: [#1705](https://github.com/airbnb/react-native-maps/pull/1705) Enable control of Google Maps Marker tracksViewChanges property. +* Android: [#1710](https://github.com/airbnb/react-native-maps/pull/1710) Added support for new Android camera movement APIs +* iOS: [#1741](https://github.com/airbnb/react-native-maps/pull/1741) Fixed iOS google MapView.onMarkerPress not receiving the marker identifier +* iOS: [#1816](https://github.com/airbnb/react-native-maps/pull/1816) Fix The name of the given podspec ‘yoga' doesn't match the expected one ‘Yoga' +* iOS: [#1797](https://github.com/airbnb/react-native-maps/pull/1797) Fixed onMapReady event on iOS to resemble onMapReady on Android +* Common: [#1817](https://github.com/airbnb/react-native-maps/pull/1817) Allow fitToCoordinates to be called without options parameter + +## 0.17.1 (October 18, 2017) +* Common: [#1687](https://github.com/airbnb/react-native-maps/pull/1687) Fixed TypeScript definitions + ## 0.17.0 (October 11, 2017) * iOS: [#1527](https://github.com/airbnb/react-native-maps/pull/1527) Added [iOS / Google Maps] support for showsIndoorLevelPicker * iOS/Android: [#1544](https://github.com/airbnb/react-native-maps/pull/1544) Adds support to animateToBearing and animateToViewingAngle ( IOS + Android ) diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index 6fc414fe3..a9e02a814 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -6,10 +6,10 @@ PODS: - GoogleMaps/Base - React (0.45.1): - React/Core (= 0.45.1) - - react-native-google-maps (0.17.0): + - react-native-google-maps (0.18.0): - GoogleMaps (= 2.1.1) - React - - react-native-maps (0.17.0): + - react-native-maps (0.18.0): - React - React/BatchedBridge (0.45.1): - React/Core diff --git a/lib/android/gradle.properties b/lib/android/gradle.properties index 7047e93ba..774b8a1d0 100644 --- a/lib/android/gradle.properties +++ b/lib/android/gradle.properties @@ -1,5 +1,5 @@ VERSION_CODE=4 -VERSION_NAME=0.17.0 +VERSION_NAME=0.18.0 GROUP=com.airbnb.android POM_DESCRIPTION=React Native Map view component for Android diff --git a/package.json b/package.json index 66e8be298..65fb9221d 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "description": "React Native Mapview component for iOS + Android", "main": "index.js", "author": "Leland Richardson ", - "version": "0.17.0", + "version": "0.18.0", "scripts": { "start": "node node_modules/react-native/local-cli/cli.js start", "run:packager": "./node_modules/react-native/packager/packager.sh", From 59ed7812e1e9312215ce8659781b8ce26f18d2a8 Mon Sep 17 00:00:00 2001 From: Christopher Dro Date: Tue, 28 Nov 2017 17:58:41 -0800 Subject: [PATCH 0337/1148] [AirMapManager] Update MapBuilder for getCommandsMap to support all entries (#1828) Related to https://github.com/airbnb/react-native-maps/pull/1587 --- .../android/react/maps/AirMapManager.java | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java index 9022b1efc..03e4597bb 100644 --- a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java @@ -102,7 +102,7 @@ public void setMapPadding(AirMapView view, @Nullable ReadableMap padding) { int right = 0; int bottom = 0; double density = (double) view.getResources().getDisplayMetrics().density; - + if (padding != null) { if (padding.hasKey("left")) { left = (int) (padding.getDouble("left") * density); @@ -312,20 +312,25 @@ public Map getExportedCustomDirectEventTypeConstants() { return map; } - - @Override + @Nullable + @Override public Map getCommandsMap() { - return MapBuilder.of( + Map map = MapBuilder.of( "animateToRegion", ANIMATE_TO_REGION, "animateToCoordinate", ANIMATE_TO_COORDINATE, "animateToViewingAngle", ANIMATE_TO_VIEWING_ANGLE, "animateToBearing", ANIMATE_TO_BEARING, "fitToElements", FIT_TO_ELEMENTS, "fitToSuppliedMarkers", FIT_TO_SUPPLIED_MARKERS, - "fitToCoordinates", FIT_TO_COORDINATES, - "setMapBoundaries", SET_MAP_BOUNDARIES + "fitToCoordinates", FIT_TO_COORDINATES ); + + map.putAll(MapBuilder.of( + "setMapBoundaries", SET_MAP_BOUNDARIES + )); + + return map; } @Override @@ -365,7 +370,6 @@ void pushEvent(ThemedReactContext context, View view, String name, WritableMap d .receiveEvent(view.getId(), name, data); } - @Override public void onDropViewInstance(AirMapView view) { view.doDestroy(); From a31758a12887857216ef1c82951d57f9e6964539 Mon Sep 17 00:00:00 2001 From: Christopher Dro Date: Tue, 28 Nov 2017 18:05:42 -0800 Subject: [PATCH 0338/1148] v0.18.1 --- CHANGELOG.md | 3 +++ example/ios/Podfile.lock | 4 ++-- lib/android/gradle.properties | 2 +- package.json | 2 +- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a5829365b..13beb9b3f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,8 @@ # Change Log +## 0.18.1 (November 28, 2017) +* Android: [#1828](https://github.com/airbnb/react-native-maps/pull/1828) [AirMapManager] Update MapBuilder for getCommandsMap to support all entires + ## 0.18.0 (November 28, 2017) * Android/iOS: [#1587](https://github.com/airbnb/react-native-maps/pull/1750) Add support to set map boundaries * Android/iOS: [#1750](https://github.com/airbnb/react-native-maps/pull/1750) Add mapPadding property diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index a9e02a814..83163ff9b 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -6,10 +6,10 @@ PODS: - GoogleMaps/Base - React (0.45.1): - React/Core (= 0.45.1) - - react-native-google-maps (0.18.0): + - react-native-google-maps (0.18.1): - GoogleMaps (= 2.1.1) - React - - react-native-maps (0.18.0): + - react-native-maps (0.18.1): - React - React/BatchedBridge (0.45.1): - React/Core diff --git a/lib/android/gradle.properties b/lib/android/gradle.properties index 774b8a1d0..64c92ca15 100644 --- a/lib/android/gradle.properties +++ b/lib/android/gradle.properties @@ -1,5 +1,5 @@ VERSION_CODE=4 -VERSION_NAME=0.18.0 +VERSION_NAME=0.18.1 GROUP=com.airbnb.android POM_DESCRIPTION=React Native Map view component for Android diff --git a/package.json b/package.json index 65fb9221d..d159c5e34 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "description": "React Native Mapview component for iOS + Android", "main": "index.js", "author": "Leland Richardson ", - "version": "0.18.0", + "version": "0.18.1", "scripts": { "start": "node node_modules/react-native/local-cli/cli.js start", "run:packager": "./node_modules/react-native/packager/packager.sh", From 458959bbaf1bec5ed51d0ed2994b2e67931bdad2 Mon Sep 17 00:00:00 2001 From: Hein Rutjes Date: Wed, 29 Nov 2017 18:23:04 +0100 Subject: [PATCH 0339/1148] Update mapview.md (#1830) There was a typo in the new iOS mapType `mutedStandard`. It should have been `mutedStandard` instead of `standardMuted` --- docs/mapview.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/mapview.md b/docs/mapview.md index 86ddbff0f..6d3227b4a 100644 --- a/docs/mapview.md +++ b/docs/mapview.md @@ -8,7 +8,7 @@ | `region` | `Region` | | The region to be displayed by the map.

The region is defined by the center coordinates and the span of coordinates to display. | `initialRegion` | `Region` | | The initial region to be displayed by the map. Use this prop instead of `region` only if you don't want to control the viewport of the map besides the initial region.

Changing this prop after the component has mounted will not result in a region change.

This is similar to the `initialValue` prop of a text input. | `liteMode` | `Boolean` | `false` | Enable lite mode. **Note**: Android only. -| `mapType` | `String` | `"standard"` | The map type to be displayed.

- standard: standard road map (default)
- satellite: satellite view
- hybrid: satellite view with roads and points of interest overlayed
- terrain: (Android only) topographic view
- standardMuted: more subtle, makes markers/lines pop more (iOS only) +| `mapType` | `String` | `"standard"` | The map type to be displayed.

- standard: standard road map (default)
- satellite: satellite view
- hybrid: satellite view with roads and points of interest overlayed
- terrain: (Android only) topographic view
- mutedStandard: more subtle, makes markers/lines pop more (iOS only) | `customMapStyle` | `Array` | | Adds custom styling to the map component. See [README](https://github.com/airbnb/react-native-maps#customizing-the-map-style) for more information. | `showsUserLocation` | `Boolean` | `false` | If `true` the app will ask for the user's location. **NOTE**: You need to add `NSLocationWhenInUseUsageDescription` key in Info.plist to enable geolocation, otherwise it is going to *fail silently*! | `userLocationAnnotationTitle` | `String` | | The title of the annotation for current user location. This only works if `showsUserLocation` is true. There is a default value `My Location` set by MapView. **Note**: iOS only. From 76b7c369e477cced0a9bb1033459885f19a633b4 Mon Sep 17 00:00:00 2001 From: Christopher Dro Date: Wed, 29 Nov 2017 10:05:19 -0800 Subject: [PATCH 0340/1148] [AirMapView] Null check map instance on view methods (#1835) --- .../airbnb/android/react/maps/AirMapView.java | 45 ++++++++++--------- 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java index aece720a8..8de9290c8 100644 --- a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java @@ -566,36 +566,35 @@ public void updateExtraData(Object extraData) { } public void animateToRegion(LatLngBounds bounds, int duration) { - if (map != null) { - map.animateCamera(CameraUpdateFactory.newLatLngBounds(bounds, 0), duration, null); - } + if (map == null) return; + map.animateCamera(CameraUpdateFactory.newLatLngBounds(bounds, 0), duration, null); } public void animateToViewingAngle(float angle, int duration) { - if (map != null) { - CameraPosition cameraPosition = new CameraPosition.Builder(map.getCameraPosition()) - .tilt(angle) - .build(); - map.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition), duration, null); - } + if (map == null) return; + + CameraPosition cameraPosition = new CameraPosition.Builder(map.getCameraPosition()) + .tilt(angle) + .build(); + map.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition), duration, null); } public void animateToBearing(float bearing, int duration) { - if (map != null) { - CameraPosition cameraPosition = new CameraPosition.Builder(map.getCameraPosition()) - .bearing(bearing) - .build(); - map.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition), duration, null); - } + if (map == null) return; + CameraPosition cameraPosition = new CameraPosition.Builder(map.getCameraPosition()) + .bearing(bearing) + .build(); + map.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition), duration, null); } public void animateToCoordinate(LatLng coordinate, int duration) { - if (map != null) { - map.animateCamera(CameraUpdateFactory.newLatLng(coordinate), duration, null); - } + if (map == null) return; + map.animateCamera(CameraUpdateFactory.newLatLng(coordinate), duration, null); } public void fitToElements(boolean animated) { + if (map == null) return; + LatLngBounds.Builder builder = new LatLngBounds.Builder(); boolean addedPosition = false; @@ -620,6 +619,8 @@ public void fitToElements(boolean animated) { } public void fitToSuppliedMarkers(ReadableArray markerIDsArray, boolean animated) { + if (map == null) return; + LatLngBounds.Builder builder = new LatLngBounds.Builder(); String[] markerIDs = new String[markerIDsArray.size()]; @@ -655,6 +656,8 @@ public void fitToSuppliedMarkers(ReadableArray markerIDsArray, boolean animated) public void fitToCoordinates(ReadableArray coordinatesArray, ReadableMap edgePadding, boolean animated) { + if (map == null) return; + LatLngBounds.Builder builder = new LatLngBounds.Builder(); for (int i = 0; i < coordinatesArray.size(); i++) { @@ -682,6 +685,8 @@ public void fitToCoordinates(ReadableArray coordinatesArray, ReadableMap edgePad } public void setMapBoundaries(ReadableMap northEast, ReadableMap southWest) { + if (map == null) return; + LatLngBounds.Builder builder = new LatLngBounds.Builder(); Double latNE = northEast.getDouble("latitude"); @@ -694,9 +699,7 @@ public void setMapBoundaries(ReadableMap northEast, ReadableMap southWest) { LatLngBounds bounds = builder.build(); - if (map != null) { - map.setLatLngBoundsForCameraTarget(bounds); - } + map.setLatLngBoundsForCameraTarget(bounds); } // InfoWindowAdapter interface From bb3301e2d8e6955c6e7f236d02c1fc91e9c136ed Mon Sep 17 00:00:00 2001 From: Christopher Dro Date: Wed, 29 Nov 2017 10:07:56 -0800 Subject: [PATCH 0341/1148] v0.18.2 --- CHANGELOG.md | 3 +++ example/ios/Podfile.lock | 4 ++-- lib/android/gradle.properties | 2 +- package.json | 2 +- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 13beb9b3f..1b3bddcdf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,8 @@ # Change Log +## 0.18.2 (November 29, 2017) +* Android: [#1835](https://github.com/airbnb/react-native-maps/pull/1835) [AirMapView] Null check map instance on view methods + ## 0.18.1 (November 28, 2017) * Android: [#1828](https://github.com/airbnb/react-native-maps/pull/1828) [AirMapManager] Update MapBuilder for getCommandsMap to support all entires diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index 83163ff9b..b906a3476 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -6,10 +6,10 @@ PODS: - GoogleMaps/Base - React (0.45.1): - React/Core (= 0.45.1) - - react-native-google-maps (0.18.1): + - react-native-google-maps (0.18.2): - GoogleMaps (= 2.1.1) - React - - react-native-maps (0.18.1): + - react-native-maps (0.18.2): - React - React/BatchedBridge (0.45.1): - React/Core diff --git a/lib/android/gradle.properties b/lib/android/gradle.properties index 64c92ca15..96333559e 100644 --- a/lib/android/gradle.properties +++ b/lib/android/gradle.properties @@ -1,5 +1,5 @@ VERSION_CODE=4 -VERSION_NAME=0.18.1 +VERSION_NAME=0.18.2 GROUP=com.airbnb.android POM_DESCRIPTION=React Native Map view component for Android diff --git a/package.json b/package.json index d159c5e34..941305239 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "description": "React Native Mapview component for iOS + Android", "main": "index.js", "author": "Leland Richardson ", - "version": "0.18.1", + "version": "0.18.2", "scripts": { "start": "node node_modules/react-native/local-cli/cli.js start", "run:packager": "./node_modules/react-native/packager/packager.sh", From 1b78d58b5205b28aaf072de0ed0cd9abd2acb062 Mon Sep 17 00:00:00 2001 From: androidseb Date: Thu, 30 Nov 2017 19:10:18 -0500 Subject: [PATCH 0342/1148] fixed the Google Maps crash on iOS with most recent versions of react-native (#1839) [AirGoogleMapManager] Use RCTDirectEventBlock for onMarkerPress --- lib/ios/AirGoogleMaps/AIRGoogleMapManager.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ios/AirGoogleMaps/AIRGoogleMapManager.m b/lib/ios/AirGoogleMaps/AIRGoogleMapManager.m index 5045deb75..5e6ef9c34 100644 --- a/lib/ios/AirGoogleMaps/AIRGoogleMapManager.m +++ b/lib/ios/AirGoogleMaps/AIRGoogleMapManager.m @@ -68,7 +68,7 @@ - (UIView *)view RCT_EXPORT_VIEW_PROPERTY(onPress, RCTBubblingEventBlock) RCT_EXPORT_VIEW_PROPERTY(onLongPress, RCTBubblingEventBlock) RCT_EXPORT_VIEW_PROPERTY(onChange, RCTBubblingEventBlock) -RCT_EXPORT_VIEW_PROPERTY(onMarkerPress, RCTBubblingEventBlock) +RCT_EXPORT_VIEW_PROPERTY(onMarkerPress, RCTDirectEventBlock) RCT_EXPORT_VIEW_PROPERTY(onRegionChange, RCTDirectEventBlock) RCT_EXPORT_VIEW_PROPERTY(onRegionChangeComplete, RCTDirectEventBlock) RCT_EXPORT_VIEW_PROPERTY(mapType, GMSMapViewType) From e53c7ec28e85d7dbf9de5e16e4bb3b2636b85466 Mon Sep 17 00:00:00 2001 From: Christopher Dro Date: Thu, 30 Nov 2017 16:12:01 -0800 Subject: [PATCH 0343/1148] v0.18.3 --- CHANGELOG.md | 3 +++ example/ios/Podfile.lock | 4 ++-- lib/android/gradle.properties | 2 +- package.json | 2 +- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1b3bddcdf..109091a39 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,8 @@ # Change Log +## 0.18.3 (November 30, 2017) +* Android: [#1839](https://github.com/airbnb/react-native-maps/pull/1839) [AirGoogleMapManager] Use RCTDirectEventBlock for onMarkerPress + ## 0.18.2 (November 29, 2017) * Android: [#1835](https://github.com/airbnb/react-native-maps/pull/1835) [AirMapView] Null check map instance on view methods diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index b906a3476..b17a261de 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -6,10 +6,10 @@ PODS: - GoogleMaps/Base - React (0.45.1): - React/Core (= 0.45.1) - - react-native-google-maps (0.18.2): + - react-native-google-maps (0.18.3): - GoogleMaps (= 2.1.1) - React - - react-native-maps (0.18.2): + - react-native-maps (0.18.3): - React - React/BatchedBridge (0.45.1): - React/Core diff --git a/lib/android/gradle.properties b/lib/android/gradle.properties index 96333559e..e4ea9f69d 100644 --- a/lib/android/gradle.properties +++ b/lib/android/gradle.properties @@ -1,5 +1,5 @@ VERSION_CODE=4 -VERSION_NAME=0.18.2 +VERSION_NAME=0.18.3 GROUP=com.airbnb.android POM_DESCRIPTION=React Native Map view component for Android diff --git a/package.json b/package.json index 941305239..06d3a97bc 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "description": "React Native Mapview component for iOS + Android", "main": "index.js", "author": "Leland Richardson ", - "version": "0.18.2", + "version": "0.18.3", "scripts": { "start": "node node_modules/react-native/local-cli/cli.js start", "run:packager": "./node_modules/react-native/packager/packager.sh", From 0059c18b058130de08c670f3a56281a7fc8736a2 Mon Sep 17 00:00:00 2001 From: dseipp Date: Wed, 6 Dec 2017 09:37:43 -0500 Subject: [PATCH 0344/1148] update GoogleMaps dependency to 2.5.0 (#1854) this is to resolve compile error: Property 'cameraTargetBounds' not found on object of type 'AIRGoogleMap *' --- react-native-google-maps.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/react-native-google-maps.podspec b/react-native-google-maps.podspec index 487cc2320..51dc01da1 100644 --- a/react-native-google-maps.podspec +++ b/react-native-google-maps.podspec @@ -17,5 +17,5 @@ Pod::Spec.new do |s| s.compiler_flags = '-fno-modules' s.dependency 'React' - s.dependency 'GoogleMaps', '2.1.1' + s.dependency 'GoogleMaps', '2.5.0' end From 0d111ac87987516e2c509d2818033678901c78d9 Mon Sep 17 00:00:00 2001 From: Peter Zavadsky Date: Fri, 1 Dec 2017 10:23:34 +0100 Subject: [PATCH 0345/1148] Added Local Tile functionality for Android Added android native AirMapLocalTile and its respective react component similar to UrlTile. Local tile can load localy stored tiles as overlay similarly as UrlTile. --- index.d.ts | 10 +- .../android/react/maps/AirMapLocalTile.java | 139 ++++++++++++++++++ .../react/maps/AirMapLocalTileManager.java | 51 +++++++ .../airbnb/android/react/maps/AirMapView.java | 4 + .../android/react/maps/MapsPackage.java | 6 +- lib/components/MapLocalTile.js | 57 +++++++ lib/components/MapView.js | 2 + 7 files changed, 265 insertions(+), 4 deletions(-) create mode 100644 lib/android/src/main/java/com/airbnb/android/react/maps/AirMapLocalTile.java create mode 100644 lib/android/src/main/java/com/airbnb/android/react/maps/AirMapLocalTileManager.java create mode 100644 lib/components/MapLocalTile.js diff --git a/index.d.ts b/index.d.ts index bdc2075e4..5a978eeee 100644 --- a/index.d.ts +++ b/index.d.ts @@ -136,11 +136,16 @@ declare namespace MapView { lineDashPattern?: number[]; } - interface MapUrlTitleProps { + interface MapUrlTileProps { urlTemplate: string; zIndex?: number; } + interface MapLocalTileProps { + pathTemplate: string; + zIndex?: number; + } + interface MapCalloutProps { tooltip?: boolean; onPress?: Function; @@ -151,7 +156,8 @@ declare namespace MapView { export class Polyline extends React.Component {} export class Polygon extends React.Component {} export class Circle extends React.Component {} - export class UrlTile extends React.Component {} + export class UrlTile extends React.Component {} + export class LocalTile extends React.Component {} export class Callout extends React.Component {} } diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapLocalTile.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapLocalTile.java new file mode 100644 index 000000000..c64038e9e --- /dev/null +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapLocalTile.java @@ -0,0 +1,139 @@ +package com.airbnb.android.react.maps; + +import android.content.Context; +import android.util.Log; + +import com.google.android.gms.maps.GoogleMap; +import com.google.android.gms.maps.model.Tile; +import com.google.android.gms.maps.model.TileOverlay; +import com.google.android.gms.maps.model.TileOverlayOptions; +import com.google.android.gms.maps.model.TileProvider; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; + +public class AirMapLocalTile extends AirMapFeature { + + class AIRMapLocalTileProvider implements TileProvider { + private static final int BUFFER_SIZE = 16 * 1024; + private int width, height; + private String pathTemplate; + + + public AIRMapLocalTileProvider(int width, int height, String pathTemplate) { + this.width = width; + this.height = height; + this.pathTemplate = pathTemplate; + } + + @Override + public Tile getTile(int x, int y, int zoom) { + byte[] image = readTileImage(x, y, zoom); + Log.d("AirMapLocalTile", String.format("getTile(%s, %s, %s) -> %s", x, y, zoom, getTileFilename(x, y, zoom))); + return image == null ? TileProvider.NO_TILE : new Tile(this.width, this.height, image); + } + + public void setPathTemplate(String pathTemplate) { + this.pathTemplate = pathTemplate; + } + + private byte[] readTileImage(int x, int y, int zoom) { + InputStream in = null; + ByteArrayOutputStream buffer = null; + File file = new File(getTileFilename(x, y, zoom)); + + try { + in = new FileInputStream(file); + buffer = new ByteArrayOutputStream(); + + int nRead; + byte[] data = new byte[BUFFER_SIZE]; + + while ((nRead = in.read(data, 0, BUFFER_SIZE)) != -1) { + buffer.write(data, 0, nRead); + } + buffer.flush(); + + return buffer.toByteArray(); + } catch (IOException e) { + e.printStackTrace(); + return null; + } catch (OutOfMemoryError e) { + e.printStackTrace(); + return null; + } finally { + if (in != null) try { in.close(); } catch (Exception ignored) {} + if (buffer != null) try { buffer.close(); } catch (Exception ignored) {} + } + } + + private String getTileFilename(int x, int y, int zoom) { + String s = this.pathTemplate + .replace("{x}", Integer.toString(x)) + .replace("{y}", Integer.toString(y)) + .replace("{z}", Integer.toString(zoom)); + return s; + } + } + + private TileOverlayOptions tileOverlayOptions; + private TileOverlay tileOverlay; + private AirMapLocalTile.AIRMapLocalTileProvider tileProvider; + + private String pathTemplate; + private float zIndex; + + public AirMapLocalTile(Context context) { + super(context); + } + + public void setPathTemplate(String pathTemplate) { + this.pathTemplate = pathTemplate; + if (tileProvider != null) { + tileProvider.setPathTemplate(pathTemplate); + } + if (tileOverlay != null) { + tileOverlay.clearTileCache(); + } + } + + public void setZIndex(float zIndex) { + this.zIndex = zIndex; + if (tileOverlay != null) { + tileOverlay.setZIndex(zIndex); + } + } + + public TileOverlayOptions getTileOverlayOptions() { + if (tileOverlayOptions == null) { + tileOverlayOptions = createTileOverlayOptions(); + } + return tileOverlayOptions; + } + + private TileOverlayOptions createTileOverlayOptions() { + TileOverlayOptions options = new TileOverlayOptions(); + options.zIndex(zIndex); + this.tileProvider = new AirMapLocalTile.AIRMapLocalTileProvider(256, 256, this.pathTemplate); + options.tileProvider(this.tileProvider); + return options; + } + + @Override + public Object getFeature() { + return tileOverlay; + } + + @Override + public void addToMap(GoogleMap map) { + this.tileOverlay = map.addTileOverlay(getTileOverlayOptions()); + } + + @Override + public void removeFromMap(GoogleMap map) { + tileOverlay.remove(); + } +} diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapLocalTileManager.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapLocalTileManager.java new file mode 100644 index 000000000..7ba328965 --- /dev/null +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapLocalTileManager.java @@ -0,0 +1,51 @@ +package com.airbnb.android.react.maps; + +import android.content.Context; +import android.os.Build; +import android.util.DisplayMetrics; +import android.view.WindowManager; + +import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.uimanager.ThemedReactContext; +import com.facebook.react.uimanager.ViewGroupManager; +import com.facebook.react.uimanager.annotations.ReactProp; + +/** + * Created by zavadpe on 30/11/2017. + */ +public class AirMapLocalTileManager extends ViewGroupManager { + private DisplayMetrics metrics; + + public AirMapLocalTileManager(ReactApplicationContext reactContext) { + super(); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { + metrics = new DisplayMetrics(); + ((WindowManager) reactContext.getSystemService(Context.WINDOW_SERVICE)) + .getDefaultDisplay() + .getRealMetrics(metrics); + } else { + metrics = reactContext.getResources().getDisplayMetrics(); + } + } + + @Override + public String getName() { + return "AIRMapLocalTile"; + } + + @Override + public AirMapLocalTile createViewInstance(ThemedReactContext context) { + return new AirMapLocalTile(context); + } + + @ReactProp(name = "pathTemplate") + public void setPathTemplate(AirMapLocalTile view, String pathTemplate) { + view.setPathTemplate(pathTemplate); + } + + @ReactProp(name = "zIndex", defaultFloat = -1.0f) + public void setZIndex(AirMapLocalTile view, float zIndex) { + view.setZIndex(zIndex); + } + +} \ No newline at end of file diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java index 8de9290c8..eb1f1e068 100644 --- a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java @@ -502,6 +502,10 @@ public void addFeature(View child, int index) { AirMapUrlTile urlTileView = (AirMapUrlTile) child; urlTileView.addToMap(map); features.add(index, urlTileView); + } else if (child instanceof AirMapLocalTile) { + AirMapLocalTile localTileView = (AirMapLocalTile) child; + localTileView.addToMap(map); + features.add(index, localTileView); } else { ViewGroup children = (ViewGroup) child; for (int i = 0; i < children.getChildCount(); i++) { diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/MapsPackage.java b/lib/android/src/main/java/com/airbnb/android/react/maps/MapsPackage.java index 6ecc55165..63e55d8ae 100644 --- a/lib/android/src/main/java/com/airbnb/android/react/maps/MapsPackage.java +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/MapsPackage.java @@ -38,7 +38,8 @@ public List createViewManagers(ReactApplicationContext reactContext AirMapCircleManager circleManager = new AirMapCircleManager(reactContext); AirMapManager mapManager = new AirMapManager(reactContext); AirMapLiteManager mapLiteManager = new AirMapLiteManager(reactContext); - AirMapUrlTileManager tileManager = new AirMapUrlTileManager(reactContext); + AirMapUrlTileManager urlTileManager = new AirMapUrlTileManager(reactContext); + AirMapLocalTileManager localTileManager = new AirMapLocalTileManager(reactContext); return Arrays.asList( calloutManager, @@ -48,6 +49,7 @@ public List createViewManagers(ReactApplicationContext reactContext circleManager, mapManager, mapLiteManager, - tileManager); + urlTileManager, + localTileManager); } } diff --git a/lib/components/MapLocalTile.js b/lib/components/MapLocalTile.js new file mode 100644 index 000000000..5c87f123b --- /dev/null +++ b/lib/components/MapLocalTile.js @@ -0,0 +1,57 @@ +import PropTypes from 'prop-types'; +import React from 'react'; + +import { + ViewPropTypes, + View, +} from 'react-native'; + +import decorateMapComponent, { + USES_DEFAULT_IMPLEMENTATION, + SUPPORTED, +} from './decorateMapComponent'; + +// if ViewPropTypes is not defined fall back to View.propType (to support RN < 0.44) +const viewPropTypes = ViewPropTypes || View.propTypes; + +const propTypes = { + ...viewPropTypes, + + /** + * The path template of the local tile source. The patterns {x} {y} {z} will be replaced at runtime + * For example, file::///storage/emulated/0/tiles/{z}/{x}/{y}.png + */ + pathTemplate: PropTypes.string.isRequired, + + /** + * The order in which this tile overlay is drawn with respect to other overlays. An overlay + * with a larger z-index is drawn over overlays with smaller z-indices. The order of overlays + * with the same z-index is arbitrary. The default zIndex is -1. + * + * @platform android + */ + zIndex: PropTypes.number, +}; + +class MapLocalTile extends React.Component { + render() { + const AIRMapLocalTile = this.getAirComponent(); + return ( + + ); + } +} + +MapLocalTile.propTypes = propTypes; + +module.exports = decorateMapComponent(MapLocalTile, { + componentType: 'LocalTile', + providers: { + google: { + ios: SUPPORTED, + android: USES_DEFAULT_IMPLEMENTATION, + }, + }, +}); diff --git a/lib/components/MapView.js b/lib/components/MapView.js index 74742e018..842225a81 100644 --- a/lib/components/MapView.js +++ b/lib/components/MapView.js @@ -17,6 +17,7 @@ import MapPolygon from './MapPolygon'; import MapCircle from './MapCircle'; import MapCallout from './MapCallout'; import MapUrlTile from './MapUrlTile'; +import MapLocalTile from './MapLocalTile'; import AnimatedRegion from './AnimatedRegion'; import { contextTypes as childContextTypes, @@ -739,6 +740,7 @@ MapView.Polyline = MapPolyline; MapView.Polygon = MapPolygon; MapView.Circle = MapCircle; MapView.UrlTile = MapUrlTile; +MapView.LocalTile = MapLocalTile; MapView.Callout = MapCallout; Object.assign(MapView, ProviderConstants); MapView.ProviderPropType = PropTypes.oneOf(Object.values(ProviderConstants)); From 3fe718afdbb56ba962881dc4f151055cc97e8a4f Mon Sep 17 00:00:00 2001 From: Peter Zavadsky Date: Mon, 4 Dec 2017 15:49:55 +0100 Subject: [PATCH 0346/1148] Added Local Tile functionality for iOS Added ios sources to project Added ios sources to project --- index.d.ts | 1 + .../android/react/maps/AirMapLocalTile.java | 23 ++++-- .../react/maps/AirMapLocalTileManager.java | 5 ++ lib/components/MapLocalTile.js | 2 + lib/ios/AirMaps.xcodeproj/project.pbxproj | 16 +++++ lib/ios/AirMaps/AIRMap.m | 7 ++ lib/ios/AirMaps/AIRMapLocalTile.h | 36 ++++++++++ lib/ios/AirMaps/AIRMapLocalTile.m | 71 +++++++++++++++++++ lib/ios/AirMaps/AIRMapLocalTileManager.h | 13 ++++ lib/ios/AirMaps/AIRMapLocalTileManager.m | 38 ++++++++++ lib/ios/AirMaps/AIRMapLocalTileOverlay.h | 12 ++++ lib/ios/AirMaps/AIRMapLocalTileOverlay.m | 33 +++++++++ lib/ios/AirMaps/AIRMapManager.m | 3 + 13 files changed, 254 insertions(+), 6 deletions(-) create mode 100644 lib/ios/AirMaps/AIRMapLocalTile.h create mode 100644 lib/ios/AirMaps/AIRMapLocalTile.m create mode 100644 lib/ios/AirMaps/AIRMapLocalTileManager.h create mode 100644 lib/ios/AirMaps/AIRMapLocalTileManager.m create mode 100644 lib/ios/AirMaps/AIRMapLocalTileOverlay.h create mode 100644 lib/ios/AirMaps/AIRMapLocalTileOverlay.m diff --git a/index.d.ts b/index.d.ts index 5a978eeee..91efce2e8 100644 --- a/index.d.ts +++ b/index.d.ts @@ -143,6 +143,7 @@ declare namespace MapView { interface MapLocalTileProps { pathTemplate: string; + tileSize: number; zIndex?: number; } diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapLocalTile.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapLocalTile.java index c64038e9e..e366a8e8d 100644 --- a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapLocalTile.java +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapLocalTile.java @@ -19,13 +19,12 @@ public class AirMapLocalTile extends AirMapFeature { class AIRMapLocalTileProvider implements TileProvider { private static final int BUFFER_SIZE = 16 * 1024; - private int width, height; + private float tileSize; private String pathTemplate; - public AIRMapLocalTileProvider(int width, int height, String pathTemplate) { - this.width = width; - this.height = height; + public AIRMapLocalTileProvider(float tileSizet, String pathTemplate) { + this.tileSize = tileSizet; this.pathTemplate = pathTemplate; } @@ -33,13 +32,17 @@ public AIRMapLocalTileProvider(int width, int height, String pathTemplate) { public Tile getTile(int x, int y, int zoom) { byte[] image = readTileImage(x, y, zoom); Log.d("AirMapLocalTile", String.format("getTile(%s, %s, %s) -> %s", x, y, zoom, getTileFilename(x, y, zoom))); - return image == null ? TileProvider.NO_TILE : new Tile(this.width, this.height, image); + return image == null ? TileProvider.NO_TILE : new Tile((int)this.tileSize, (int)this.tileSize, image); } public void setPathTemplate(String pathTemplate) { this.pathTemplate = pathTemplate; } + public void setTileSize(float tileSize) { + this.tileSize = tileSize; + } + private byte[] readTileImage(int x, int y, int zoom) { InputStream in = null; ByteArrayOutputStream buffer = null; @@ -84,6 +87,7 @@ private String getTileFilename(int x, int y, int zoom) { private AirMapLocalTile.AIRMapLocalTileProvider tileProvider; private String pathTemplate; + private float tileSize; private float zIndex; public AirMapLocalTile(Context context) { @@ -107,6 +111,13 @@ public void setZIndex(float zIndex) { } } + public void setTileSize(float tileSize) { + this.tileSize = tileSize; + if (tileProvider != null) { + tileProvider.setTileSize(tileSize); + } + } + public TileOverlayOptions getTileOverlayOptions() { if (tileOverlayOptions == null) { tileOverlayOptions = createTileOverlayOptions(); @@ -117,7 +128,7 @@ public TileOverlayOptions getTileOverlayOptions() { private TileOverlayOptions createTileOverlayOptions() { TileOverlayOptions options = new TileOverlayOptions(); options.zIndex(zIndex); - this.tileProvider = new AirMapLocalTile.AIRMapLocalTileProvider(256, 256, this.pathTemplate); + this.tileProvider = new AirMapLocalTile.AIRMapLocalTileProvider(this.tileSize, this.pathTemplate); options.tileProvider(this.tileProvider); return options; } diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapLocalTileManager.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapLocalTileManager.java index 7ba328965..3e4d17ae3 100644 --- a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapLocalTileManager.java +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapLocalTileManager.java @@ -43,6 +43,11 @@ public void setPathTemplate(AirMapLocalTile view, String pathTemplate) { view.setPathTemplate(pathTemplate); } + @ReactProp(name = "zIndex", defaultFloat = 256f) + public void setTileSize(AirMapLocalTile view, float tileSize) { + view.setTileSize(tileSize); + } + @ReactProp(name = "zIndex", defaultFloat = -1.0f) public void setZIndex(AirMapLocalTile view, float zIndex) { view.setZIndex(zIndex); diff --git a/lib/components/MapLocalTile.js b/lib/components/MapLocalTile.js index 5c87f123b..891c1d409 100644 --- a/lib/components/MapLocalTile.js +++ b/lib/components/MapLocalTile.js @@ -31,6 +31,8 @@ const propTypes = { * @platform android */ zIndex: PropTypes.number, + + tileSize: PropTypes.number, }; class MapLocalTile extends React.Component { diff --git a/lib/ios/AirMaps.xcodeproj/project.pbxproj b/lib/ios/AirMaps.xcodeproj/project.pbxproj index ac641aff7..4c959ad9f 100644 --- a/lib/ios/AirMaps.xcodeproj/project.pbxproj +++ b/lib/ios/AirMaps.xcodeproj/project.pbxproj @@ -22,6 +22,9 @@ 1125B2E61C4AD3DA007D0023 /* AIRMapPolylineManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 1125B2D61C4AD3DA007D0023 /* AIRMapPolylineManager.m */; }; 1125B2F21C4AD445007D0023 /* SMCalloutView.m in Sources */ = {isa = PBXBuildFile; fileRef = 1125B2F11C4AD445007D0023 /* SMCalloutView.m */; }; 19DABC7F1E7C9D3C00F41150 /* RCTConvert+AirMap.m in Sources */ = {isa = PBXBuildFile; fileRef = 19DABC7E1E7C9D3C00F41150 /* RCTConvert+AirMap.m */; }; + 628F81201FD16DF80058313A /* AIRMapLocalTile.m in Sources */ = {isa = PBXBuildFile; fileRef = 628F811F1FD16DF80058313A /* AIRMapLocalTile.m */; }; + 628F81231FD16EFA0058313A /* AIRMapLocalTileManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 628F81221FD16EFA0058313A /* AIRMapLocalTileManager.m */; }; + 62AEC4D41FD5A0AA003225E0 /* AIRMapLocalTileOverlay.m in Sources */ = {isa = PBXBuildFile; fileRef = 62AEC4D31FD5A0AA003225E0 /* AIRMapLocalTileOverlay.m */; }; DA6C26381C9E2AFE0035349F /* AIRMapUrlTile.m in Sources */ = {isa = PBXBuildFile; fileRef = DA6C26371C9E2AFE0035349F /* AIRMapUrlTile.m */; }; DA6C263E1C9E324A0035349F /* AIRMapUrlTileManager.m in Sources */ = {isa = PBXBuildFile; fileRef = DA6C263D1C9E324A0035349F /* AIRMapUrlTileManager.m */; }; /* End PBXBuildFile section */ @@ -70,6 +73,11 @@ 11FA5C511C4A1296003AC2EE /* libAirMaps.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libAirMaps.a; sourceTree = BUILT_PRODUCTS_DIR; }; 19DABC7D1E7C9D3C00F41150 /* RCTConvert+AirMap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "RCTConvert+AirMap.h"; sourceTree = ""; }; 19DABC7E1E7C9D3C00F41150 /* RCTConvert+AirMap.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "RCTConvert+AirMap.m"; sourceTree = ""; }; + 628F811E1FD16D780058313A /* AIRMapLocalTile.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AIRMapLocalTile.h; sourceTree = ""; }; + 628F811F1FD16DF80058313A /* AIRMapLocalTile.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AIRMapLocalTile.m; sourceTree = ""; }; + 628F81211FD16EAB0058313A /* AIRMapLocalTileManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AIRMapLocalTileManager.h; sourceTree = ""; }; + 628F81221FD16EFA0058313A /* AIRMapLocalTileManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AIRMapLocalTileManager.m; sourceTree = ""; }; + 62AEC4D31FD5A0AA003225E0 /* AIRMapLocalTileOverlay.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = AIRMapLocalTileOverlay.m; path = AirMaps/AIRMapLocalTileOverlay.m; sourceTree = ""; }; DA6C26361C9E2AFE0035349F /* AIRMapUrlTile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRMapUrlTile.h; sourceTree = ""; }; DA6C26371C9E2AFE0035349F /* AIRMapUrlTile.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRMapUrlTile.m; sourceTree = ""; }; DA6C263C1C9E324A0035349F /* AIRMapUrlTileManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRMapUrlTileManager.h; sourceTree = ""; }; @@ -90,6 +98,7 @@ 11FA5C481C4A1296003AC2EE = { isa = PBXGroup; children = ( + 62AEC4D31FD5A0AA003225E0 /* AIRMapLocalTileOverlay.m */, 11FA5C531C4A1296003AC2EE /* AirMaps */, 11FA5C521C4A1296003AC2EE /* Products */, ); @@ -140,6 +149,10 @@ DA6C26371C9E2AFE0035349F /* AIRMapUrlTile.m */, DA6C263C1C9E324A0035349F /* AIRMapUrlTileManager.h */, DA6C263D1C9E324A0035349F /* AIRMapUrlTileManager.m */, + 628F811E1FD16D780058313A /* AIRMapLocalTile.h */, + 628F811F1FD16DF80058313A /* AIRMapLocalTile.m */, + 628F81211FD16EAB0058313A /* AIRMapLocalTileManager.h */, + 628F81221FD16EFA0058313A /* AIRMapLocalTileManager.m */, ); path = AirMaps; sourceTree = ""; @@ -200,6 +213,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 62AEC4D41FD5A0AA003225E0 /* AIRMapLocalTileOverlay.m in Sources */, 1125B2E31C4AD3DA007D0023 /* AIRMapPolygon.m in Sources */, 1125B2E41C4AD3DA007D0023 /* AIRMapPolygonManager.m in Sources */, 1125B2DB1C4AD3DA007D0023 /* AIRMapCallout.m in Sources */, @@ -209,12 +223,14 @@ 19DABC7F1E7C9D3C00F41150 /* RCTConvert+AirMap.m in Sources */, 1125B2E51C4AD3DA007D0023 /* AIRMapPolyline.m in Sources */, DA6C263E1C9E324A0035349F /* AIRMapUrlTileManager.m in Sources */, + 628F81201FD16DF80058313A /* AIRMapLocalTile.m in Sources */, 1125B2DA1C4AD3DA007D0023 /* AIRMap.m in Sources */, 1125B2DF1C4AD3DA007D0023 /* AIRMapCoordinate.m in Sources */, 1125B2F21C4AD445007D0023 /* SMCalloutView.m in Sources */, 1125B2E11C4AD3DA007D0023 /* AIRMapMarker.m in Sources */, 1125B2E21C4AD3DA007D0023 /* AIRMapMarkerManager.m in Sources */, DA6C26381C9E2AFE0035349F /* AIRMapUrlTile.m in Sources */, + 628F81231FD16EFA0058313A /* AIRMapLocalTileManager.m in Sources */, 1125B2DE1C4AD3DA007D0023 /* AIRMapCircleManager.m in Sources */, 1125B2DC1C4AD3DA007D0023 /* AIRMapCalloutManager.m in Sources */, ); diff --git a/lib/ios/AirMaps/AIRMap.m b/lib/ios/AirMaps/AIRMap.m index 647be4b8a..d1203bd61 100644 --- a/lib/ios/AirMaps/AIRMap.m +++ b/lib/ios/AirMaps/AIRMap.m @@ -17,6 +17,7 @@ #import "AIRMapCircle.h" #import #import "AIRMapUrlTile.h" +#import "AIRMapLocalTile.h" const CLLocationDegrees AIRMapDefaultSpan = 0.005; const NSTimeInterval AIRMapRegionChangeObserveInterval = 0.1; @@ -62,6 +63,7 @@ @implementation AIRMap - (instancetype)init { + NSLog(@"AirMap.init................"); if ((self = [super init])) { _hasStartedRendering = NO; _reactSubviews = [NSMutableArray new]; @@ -110,6 +112,9 @@ - (void)insertReactSubview:(id)subview atIndex:(NSInteger)atIndex } else if ([subview isKindOfClass:[AIRMapUrlTile class]]) { ((AIRMapUrlTile *)subview).map = self; [self addOverlay:(id)subview]; + } else if ([subview isKindOfClass:[AIRMapLocalTile class]]) { + ((AIRMapLocalTile *)subview).map = self; + [self addOverlay:(id)subview]; } else { NSArray> *childSubviews = [subview reactSubviews]; for (int i = 0; i < childSubviews.count; i++) { @@ -135,6 +140,8 @@ - (void)removeReactSubview:(id)subview { [self removeOverlay:(id ) subview]; } else if ([subview isKindOfClass:[AIRMapUrlTile class]]) { [self removeOverlay:(id ) subview]; + } else if ([subview isKindOfClass:[AIRMapLocalTile class]]) { + [self removeOverlay:(id ) subview]; } else { NSArray> *childSubviews = [subview reactSubviews]; for (int i = 0; i < childSubviews.count; i++) { diff --git a/lib/ios/AirMaps/AIRMapLocalTile.h b/lib/ios/AirMaps/AIRMapLocalTile.h new file mode 100644 index 000000000..d03d7b1ee --- /dev/null +++ b/lib/ios/AirMaps/AIRMapLocalTile.h @@ -0,0 +1,36 @@ +// +// AIRMapLocalTile.h +// AirMaps +// +// Created by Peter Zavadsky on 01/12/2017. +// Copyright © 2017 Christopher. All rights reserved. +// + +#import +#import +#import + +#import +#import +#import "AIRMapCoordinate.h" +#import "AIRMap.h" +#import "RCTConvert+AirMap.h" + +@interface AIRMapLocalTile : MKAnnotationView + +@property (nonatomic, weak) AIRMap *map; + +@property (nonatomic, strong) MKTileOverlay *tileOverlay; +@property (nonatomic, strong) MKTileOverlayRenderer *renderer; + +@property (nonatomic, copy) NSString *pathTemplate; +@property (nonatomic, assign) CGFloat tileSize; + +#pragma mark MKOverlay protocol + +@property(nonatomic, readonly) CLLocationCoordinate2D coordinate; +@property(nonatomic, readonly) MKMapRect boundingMapRect; +//- (BOOL)intersectsMapRect:(MKMapRect)mapRect; +- (BOOL)canReplaceMapContent; + +@end diff --git a/lib/ios/AirMaps/AIRMapLocalTile.m b/lib/ios/AirMaps/AIRMapLocalTile.m new file mode 100644 index 000000000..a9e337afa --- /dev/null +++ b/lib/ios/AirMaps/AIRMapLocalTile.m @@ -0,0 +1,71 @@ +// +// AIRMapLocalTile.m +// AirMaps +// +// Created by Peter Zavadsky on 01/12/2017. +// Copyright © 2017 Christopher. All rights reserved. +// + +#import "AIRMapLocalTile.h" +#import +#import "AIRMapLocalTileOverlay.h" + +@implementation AIRMapLocalTile { + BOOL _pathTemplateSet; + BOOL _tileSizeSet; +} + + +- (void)setPathTemplate:(NSString *)pathTemplate{ + NSLog(@"setPathTemplate %@", pathTemplate); + _pathTemplate = pathTemplate; + _pathTemplateSet = YES; + [self createTileOverlayAndRendererIfPossible]; + [self update]; +} + +- (void)setTileSize:(CGFloat)tileSize{ + NSLog(@"setTileSize %f", tileSize); + _tileSize = tileSize; + _tileSizeSet = YES; + [self createTileOverlayAndRendererIfPossible]; + [self update]; +} + +- (void) createTileOverlayAndRendererIfPossible +{ + NSLog(@"createTileOverlayAndRendererIfPossible"); + if (!_pathTemplateSet || !_tileSizeSet) return; + self.tileOverlay = [[AIRMapLocalTileOverlay alloc] initWithURLTemplate:self.pathTemplate]; + self.tileOverlay.canReplaceMapContent = YES; + self.tileOverlay.tileSize = CGSizeMake(_tileSize, _tileSize); + self.renderer = [[MKTileOverlayRenderer alloc] initWithTileOverlay:self.tileOverlay]; +} + +- (void) update +{ + if (!_renderer) return; + + if (_map == nil) return; + [_map removeOverlay:self]; + [_map addOverlay:self level:MKOverlayLevelAboveLabels]; +} + +#pragma mark MKOverlay implementation + +- (CLLocationCoordinate2D) coordinate +{ + return self.tileOverlay.coordinate; +} + +- (MKMapRect) boundingMapRect +{ + return self.tileOverlay.boundingMapRect; +} + +- (BOOL)canReplaceMapContent +{ + return self.tileOverlay.canReplaceMapContent; +} + +@end diff --git a/lib/ios/AirMaps/AIRMapLocalTileManager.h b/lib/ios/AirMaps/AIRMapLocalTileManager.h new file mode 100644 index 000000000..c6ee32695 --- /dev/null +++ b/lib/ios/AirMaps/AIRMapLocalTileManager.h @@ -0,0 +1,13 @@ +// +// AIRMapLocalTileManager.h +// AirMaps +// +// Created by Peter Zavadsky on 01/12/2017. +// Copyright © 2017 Christopher. All rights reserved. +// + +#import + +@interface AIRMapLocalTileManager : RCTViewManager + +@end diff --git a/lib/ios/AirMaps/AIRMapLocalTileManager.m b/lib/ios/AirMaps/AIRMapLocalTileManager.m new file mode 100644 index 000000000..a7997bfe0 --- /dev/null +++ b/lib/ios/AirMaps/AIRMapLocalTileManager.m @@ -0,0 +1,38 @@ +// +// AIRMapLocalTileManager.m +// AirMaps +// +// Created by Peter Zavadsky on 01/12/2017. +// Copyright © 2017 Christopher. All rights reserved. +// + +#import +#import +#import +#import +#import +#import +#import "AIRMapMarker.h" +#import "AIRMapLocalTile.h" + +#import "AIRMapLocalTileManager.h" + +@interface AIRMapLocalTileManager() + +@end + +@implementation AIRMapLocalTileManager + + +RCT_EXPORT_MODULE() + +- (UIView *)view +{ + AIRMapLocalTile *tile = [AIRMapLocalTile new]; + return tile; +} + +RCT_EXPORT_VIEW_PROPERTY(pathTemplate, NSString) +RCT_EXPORT_VIEW_PROPERTY(tileSize, CGFloat) + +@end diff --git a/lib/ios/AirMaps/AIRMapLocalTileOverlay.h b/lib/ios/AirMaps/AIRMapLocalTileOverlay.h new file mode 100644 index 000000000..f588e102f --- /dev/null +++ b/lib/ios/AirMaps/AIRMapLocalTileOverlay.h @@ -0,0 +1,12 @@ +// +// AIRMapLocalTileOverlay.h +// Pods +// +// Created by Peter Zavadsky on 04/12/2017. +// + +#import + +@interface AIRMapLocalTileOverlay : MKTileOverlay + +@end diff --git a/lib/ios/AirMaps/AIRMapLocalTileOverlay.m b/lib/ios/AirMaps/AIRMapLocalTileOverlay.m new file mode 100644 index 000000000..58a384e1f --- /dev/null +++ b/lib/ios/AirMaps/AIRMapLocalTileOverlay.m @@ -0,0 +1,33 @@ +// +// AIRMapLocalTileOverlay.m +// Pods-AirMapsExplorer +// +// Created by Peter Zavadsky on 04/12/2017. +// + +#import "AIRMapLocalTileOverlay.h" + +@interface AIRMapLocalTileOverlay () + +@end + +@implementation AIRMapLocalTileOverlay + + +-(void)loadTileAtPath:(MKTileOverlayPath)path result:(void (^)(NSData *, NSError *))result { + NSLog(@">>>Loading tile x/y/z: %ld/%ld/%ld %@",(long)path.x,(long)path.y,(long)path.z, self.URLTemplate); + NSMutableString *tileFilePath = [self.URLTemplate mutableCopy]; + [tileFilePath replaceOccurrencesOfString: @"{x}" withString:[NSString stringWithFormat:@"%i", path.x] options:NULL range:NSMakeRange(0, tileFilePath.length)]; + [tileFilePath replaceOccurrencesOfString:@"{y}" withString:[NSString stringWithFormat:@"%i", path.y] options:NULL range:NSMakeRange(0, tileFilePath.length)]; + [tileFilePath replaceOccurrencesOfString:@"{z}" withString:[NSString stringWithFormat:@"%i", path.z] options:NULL range:NSMakeRange(0, tileFilePath.length)]; + NSLog(@">>>tile file path %@", tileFilePath); + if ([[NSFileManager defaultManager] fileExistsAtPath:tileFilePath]) { + NSData* tile = [NSData dataWithContentsOfFile:tileFilePath]; + result(tile,nil); + } else { + result(nil, nil); + } +} + + +@end diff --git a/lib/ios/AirMaps/AIRMapManager.m b/lib/ios/AirMaps/AIRMapManager.m index 1124c440c..94283963a 100644 --- a/lib/ios/AirMaps/AIRMapManager.m +++ b/lib/ios/AirMaps/AIRMapManager.m @@ -23,6 +23,7 @@ #import "AIRMapCircle.h" #import "SMCalloutView.h" #import "AIRMapUrlTile.h" +#import "AIRMapLocalTile.h" #import "AIRMapSnapshot.h" #import "RCTConvert+AirMap.h" @@ -537,6 +538,8 @@ - (MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id Date: Tue, 5 Dec 2017 10:42:54 +0100 Subject: [PATCH 0347/1148] Fixed tileSize on android --- .../airbnb/android/react/maps/AirMapLocalTile.java | 12 ++++++------ .../android/react/maps/AirMapLocalTileManager.java | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapLocalTile.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapLocalTile.java index e366a8e8d..a5f235523 100644 --- a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapLocalTile.java +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapLocalTile.java @@ -19,11 +19,11 @@ public class AirMapLocalTile extends AirMapFeature { class AIRMapLocalTileProvider implements TileProvider { private static final int BUFFER_SIZE = 16 * 1024; - private float tileSize; + private int tileSize; private String pathTemplate; - public AIRMapLocalTileProvider(float tileSizet, String pathTemplate) { + public AIRMapLocalTileProvider(int tileSizet, String pathTemplate) { this.tileSize = tileSizet; this.pathTemplate = pathTemplate; } @@ -32,14 +32,14 @@ public AIRMapLocalTileProvider(float tileSizet, String pathTemplate) { public Tile getTile(int x, int y, int zoom) { byte[] image = readTileImage(x, y, zoom); Log.d("AirMapLocalTile", String.format("getTile(%s, %s, %s) -> %s", x, y, zoom, getTileFilename(x, y, zoom))); - return image == null ? TileProvider.NO_TILE : new Tile((int)this.tileSize, (int)this.tileSize, image); + return image == null ? TileProvider.NO_TILE : new Tile(this.tileSize, this.tileSize, image); } public void setPathTemplate(String pathTemplate) { this.pathTemplate = pathTemplate; } - public void setTileSize(float tileSize) { + public void setTileSize(int tileSize) { this.tileSize = tileSize; } @@ -114,7 +114,7 @@ public void setZIndex(float zIndex) { public void setTileSize(float tileSize) { this.tileSize = tileSize; if (tileProvider != null) { - tileProvider.setTileSize(tileSize); + tileProvider.setTileSize((int)tileSize); } } @@ -128,7 +128,7 @@ public TileOverlayOptions getTileOverlayOptions() { private TileOverlayOptions createTileOverlayOptions() { TileOverlayOptions options = new TileOverlayOptions(); options.zIndex(zIndex); - this.tileProvider = new AirMapLocalTile.AIRMapLocalTileProvider(this.tileSize, this.pathTemplate); + this.tileProvider = new AirMapLocalTile.AIRMapLocalTileProvider((int)this.tileSize, this.pathTemplate); options.tileProvider(this.tileProvider); return options; } diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapLocalTileManager.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapLocalTileManager.java index 3e4d17ae3..c9647888b 100644 --- a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapLocalTileManager.java +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapLocalTileManager.java @@ -43,7 +43,7 @@ public void setPathTemplate(AirMapLocalTile view, String pathTemplate) { view.setPathTemplate(pathTemplate); } - @ReactProp(name = "zIndex", defaultFloat = 256f) + @ReactProp(name = "tileSize", defaultFloat = 256f) public void setTileSize(AirMapLocalTile view, float tileSize) { view.setTileSize(tileSize); } From 7822544baa5196cf2088ea87c0f0ab130afb4676 Mon Sep 17 00:00:00 2001 From: Peter Zavadsky Date: Thu, 7 Dec 2017 14:28:52 +0100 Subject: [PATCH 0348/1148] Added LocalTile example --- example/examples/CustomTilesLocal.js | 110 +++++++++++++++++++++++++++ 1 file changed, 110 insertions(+) create mode 100644 example/examples/CustomTilesLocal.js diff --git a/example/examples/CustomTilesLocal.js b/example/examples/CustomTilesLocal.js new file mode 100644 index 000000000..fa5173ac1 --- /dev/null +++ b/example/examples/CustomTilesLocal.js @@ -0,0 +1,110 @@ +import React from 'react'; +import { + StyleSheet, + View, + Text, + Dimensions, +} from 'react-native'; + +import MapView, { MAP_TYPES, PROVIDER_DEFAULT } from 'react-native-maps'; + +const { width, height } = Dimensions.get('window'); + +const ASPECT_RATIO = width / height; +const LATITUDE = 37.78825; +const LONGITUDE = -122.4324; +const LATITUDE_DELTA = 0.0922; +const LONGITUDE_DELTA = LATITUDE_DELTA * ASPECT_RATIO; + +class CustomTiles extends React.Component { + constructor(props, context) { + super(props, context); + + this.state = { + region: { + latitude: LATITUDE, + longitude: LONGITUDE, + latitudeDelta: LATITUDE_DELTA, + longitudeDelta: LONGITUDE_DELTA, + }, + }; + } + + get mapType() { + // MapKit does not support 'none' as a base map + return this.props.provider === PROVIDER_DEFAULT ? + MAP_TYPES.STANDARD : MAP_TYPES.NONE; + } + + render() { + const { region } = this.state; + return ( + + + + + + + Custom Tiles Local + + + + ); + } +} + +CustomTiles.propTypes = { + provider: MapView.ProviderPropType, +}; + +const styles = StyleSheet.create({ + container: { + position: 'absolute', + top: 0, + left: 0, + right: 0, + bottom: 0, + justifyContent: 'flex-end', + alignItems: 'center', + }, + map: { + position: 'absolute', + top: 0, + left: 0, + right: 0, + bottom: 0, + }, + bubble: { + flex: 1, + backgroundColor: 'rgba(255,255,255,0.7)', + paddingHorizontal: 18, + paddingVertical: 12, + borderRadius: 20, + }, + latlng: { + width: 200, + alignItems: 'stretch', + }, + button: { + width: 80, + paddingHorizontal: 12, + alignItems: 'center', + marginHorizontal: 10, + }, + buttonContainer: { + flexDirection: 'row', + marginVertical: 20, + backgroundColor: 'transparent', + }, +}); + +module.exports = CustomTiles; From 42c544cbf463f42a3b04e845af33ea0408568661 Mon Sep 17 00:00:00 2001 From: yatagan Date: Sat, 9 Dec 2017 19:06:54 +0200 Subject: [PATCH 0349/1148] onPress event for Polygon doesn't work on iOS (#1861) Because there is an undocumented props `tappable` --- docs/polygon.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/polygon.md b/docs/polygon.md index 085b31a18..f13f50755 100644 --- a/docs/polygon.md +++ b/docs/polygon.md @@ -14,6 +14,7 @@ | `geodesic` | `Boolean` | | Boolean to indicate whether to draw each segment of the line as a geodesic as opposed to straight lines on the Mercator projection. A geodesic is the shortest path between two points on the Earth's surface. The geodesic curve is constructed assuming the Earth is a sphere. | `lineDashPhase` | `Number` | `0` | (iOS only) The offset (in points) at which to start drawing the dash pattern. Use this property to start drawing a dashed line partway through a segment or gap. For example, a phase value of 6 for the patter 5-2-3-2 would cause drawing to begin in the middle of the first gap. | `lineDashPattern` | `Array` | `null` | (iOS only) An array of numbers specifying the dash pattern to use for the path. The array contains one or more numbers that indicate the lengths (measured in points) of the line segments and gaps in the pattern. The values in the array alternate, starting with the first line segment length, followed by the first gap length, followed by the second line segment length, and so on. +| `tappable` | `Bool` | false (for iOS) | Boolean to allow a polygon to be tappable and use the onPress function. ## Events From 6220583a19cf62f942b4166927aafeeeb1003a81 Mon Sep 17 00:00:00 2001 From: Alexander Veligurov Date: Mon, 11 Dec 2017 18:21:45 -0300 Subject: [PATCH 0350/1148] Fix 1153 (Not a ViewGroup element cast) --- .../main/java/com/airbnb/android/react/maps/AirMapView.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java index 8de9290c8..0277345be 100644 --- a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java @@ -502,11 +502,13 @@ public void addFeature(View child, int index) { AirMapUrlTile urlTileView = (AirMapUrlTile) child; urlTileView.addToMap(map); features.add(index, urlTileView); - } else { + } else if (child instanceof ViewGroup) { ViewGroup children = (ViewGroup) child; for (int i = 0; i < children.getChildCount(); i++) { addFeature(children.getChildAt(i), index); } + } else { + addView(child, index); } } From 732def910da249bfae1fd048a172d744349f2d99 Mon Sep 17 00:00:00 2001 From: Alexander Veligurov Date: Tue, 12 Dec 2017 17:58:13 -0300 Subject: [PATCH 0351/1148] fix 1690. Add requiresMainQueueSetup --- lib/ios/AirGoogleMaps/AIRGoogleMapManager.m | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/ios/AirGoogleMaps/AIRGoogleMapManager.m b/lib/ios/AirGoogleMaps/AIRGoogleMapManager.m index 5e6ef9c34..0d5e1d5c4 100644 --- a/lib/ios/AirGoogleMaps/AIRGoogleMapManager.m +++ b/lib/ios/AirGoogleMaps/AIRGoogleMapManager.m @@ -312,6 +312,10 @@ - (UIView *)view }]; } ++ (BOOL)requiresMainQueueSetup { + return YES; +} + - (NSDictionary *)constantsToExport { return @{ @"legalNotice": [GMSServices openSourceLicenseInfo] }; } From 656c2771bd1f673ca809c70a5090631e2b3a3df8 Mon Sep 17 00:00:00 2001 From: Peter Zavadsky Date: Wed, 13 Dec 2017 09:50:15 +0100 Subject: [PATCH 0352/1148] Removed unnecessary logs --- .../java/com/airbnb/android/react/maps/AirMapLocalTile.java | 2 -- lib/ios/AirMaps/AIRMapLocalTile.m | 3 --- 2 files changed, 5 deletions(-) diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapLocalTile.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapLocalTile.java index a5f235523..159a1cca2 100644 --- a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapLocalTile.java +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapLocalTile.java @@ -1,7 +1,6 @@ package com.airbnb.android.react.maps; import android.content.Context; -import android.util.Log; import com.google.android.gms.maps.GoogleMap; import com.google.android.gms.maps.model.Tile; @@ -31,7 +30,6 @@ public AIRMapLocalTileProvider(int tileSizet, String pathTemplate) { @Override public Tile getTile(int x, int y, int zoom) { byte[] image = readTileImage(x, y, zoom); - Log.d("AirMapLocalTile", String.format("getTile(%s, %s, %s) -> %s", x, y, zoom, getTileFilename(x, y, zoom))); return image == null ? TileProvider.NO_TILE : new Tile(this.tileSize, this.tileSize, image); } diff --git a/lib/ios/AirMaps/AIRMapLocalTile.m b/lib/ios/AirMaps/AIRMapLocalTile.m index a9e337afa..17e38822d 100644 --- a/lib/ios/AirMaps/AIRMapLocalTile.m +++ b/lib/ios/AirMaps/AIRMapLocalTile.m @@ -17,7 +17,6 @@ @implementation AIRMapLocalTile { - (void)setPathTemplate:(NSString *)pathTemplate{ - NSLog(@"setPathTemplate %@", pathTemplate); _pathTemplate = pathTemplate; _pathTemplateSet = YES; [self createTileOverlayAndRendererIfPossible]; @@ -25,7 +24,6 @@ - (void)setPathTemplate:(NSString *)pathTemplate{ } - (void)setTileSize:(CGFloat)tileSize{ - NSLog(@"setTileSize %f", tileSize); _tileSize = tileSize; _tileSizeSet = YES; [self createTileOverlayAndRendererIfPossible]; @@ -34,7 +32,6 @@ - (void)setTileSize:(CGFloat)tileSize{ - (void) createTileOverlayAndRendererIfPossible { - NSLog(@"createTileOverlayAndRendererIfPossible"); if (!_pathTemplateSet || !_tileSizeSet) return; self.tileOverlay = [[AIRMapLocalTileOverlay alloc] initWithURLTemplate:self.pathTemplate]; self.tileOverlay.canReplaceMapContent = YES; From b3af6b69d4acbcc9f241d92ece88e2f3f4115a82 Mon Sep 17 00:00:00 2001 From: Peter Zavadsky Date: Wed, 13 Dec 2017 10:58:51 +0100 Subject: [PATCH 0353/1148] Fixed codestyle issues --- lib/components/MapLocalTile.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/lib/components/MapLocalTile.js b/lib/components/MapLocalTile.js index 891c1d409..27f70f984 100644 --- a/lib/components/MapLocalTile.js +++ b/lib/components/MapLocalTile.js @@ -18,8 +18,9 @@ const propTypes = { ...viewPropTypes, /** - * The path template of the local tile source. The patterns {x} {y} {z} will be replaced at runtime - * For example, file::///storage/emulated/0/tiles/{z}/{x}/{y}.png + * The path template of the local tile source. + * The patterns {x} {y} {z} will be replaced at runtime, + * for example, /storage/emulated/0/tiles/{z}/{x}/{y}.png. */ pathTemplate: PropTypes.string.isRequired, @@ -31,7 +32,10 @@ const propTypes = { * @platform android */ zIndex: PropTypes.number, - + + /** + * Size of tile images. + */ tileSize: PropTypes.number, }; From e330e7a53c34bb7461d4b1d718838f96efec4515 Mon Sep 17 00:00:00 2001 From: Peter Zavadsky Date: Wed, 13 Dec 2017 11:08:19 +0100 Subject: [PATCH 0354/1148] Removed another trailing space --- lib/components/MapLocalTile.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/components/MapLocalTile.js b/lib/components/MapLocalTile.js index 27f70f984..508da5676 100644 --- a/lib/components/MapLocalTile.js +++ b/lib/components/MapLocalTile.js @@ -18,7 +18,7 @@ const propTypes = { ...viewPropTypes, /** - * The path template of the local tile source. + * The path template of the local tile source. * The patterns {x} {y} {z} will be replaced at runtime, * for example, /storage/emulated/0/tiles/{z}/{x}/{y}.png. */ From 9d4768ffb215301934704e4a8b19a8af0d6499cb Mon Sep 17 00:00:00 2001 From: Peter Zavadsky Date: Wed, 13 Dec 2017 13:48:15 +0100 Subject: [PATCH 0355/1148] Removed all unnecessary logs --- lib/ios/AirMaps/AIRMap.m | 1 - lib/ios/AirMaps/AIRMapLocalTileOverlay.m | 2 -- 2 files changed, 3 deletions(-) diff --git a/lib/ios/AirMaps/AIRMap.m b/lib/ios/AirMaps/AIRMap.m index d1203bd61..cf194363a 100644 --- a/lib/ios/AirMaps/AIRMap.m +++ b/lib/ios/AirMaps/AIRMap.m @@ -63,7 +63,6 @@ @implementation AIRMap - (instancetype)init { - NSLog(@"AirMap.init................"); if ((self = [super init])) { _hasStartedRendering = NO; _reactSubviews = [NSMutableArray new]; diff --git a/lib/ios/AirMaps/AIRMapLocalTileOverlay.m b/lib/ios/AirMaps/AIRMapLocalTileOverlay.m index 58a384e1f..26262e083 100644 --- a/lib/ios/AirMaps/AIRMapLocalTileOverlay.m +++ b/lib/ios/AirMaps/AIRMapLocalTileOverlay.m @@ -15,12 +15,10 @@ @implementation AIRMapLocalTileOverlay -(void)loadTileAtPath:(MKTileOverlayPath)path result:(void (^)(NSData *, NSError *))result { - NSLog(@">>>Loading tile x/y/z: %ld/%ld/%ld %@",(long)path.x,(long)path.y,(long)path.z, self.URLTemplate); NSMutableString *tileFilePath = [self.URLTemplate mutableCopy]; [tileFilePath replaceOccurrencesOfString: @"{x}" withString:[NSString stringWithFormat:@"%i", path.x] options:NULL range:NSMakeRange(0, tileFilePath.length)]; [tileFilePath replaceOccurrencesOfString:@"{y}" withString:[NSString stringWithFormat:@"%i", path.y] options:NULL range:NSMakeRange(0, tileFilePath.length)]; [tileFilePath replaceOccurrencesOfString:@"{z}" withString:[NSString stringWithFormat:@"%i", path.z] options:NULL range:NSMakeRange(0, tileFilePath.length)]; - NSLog(@">>>tile file path %@", tileFilePath); if ([[NSFileManager defaultManager] fileExistsAtPath:tileFilePath]) { NSData* tile = [NSData dataWithContentsOfFile:tileFilePath]; result(tile,nil); From a246f5fd3dc3cf22fd006268467ebe96ce4cfb9b Mon Sep 17 00:00:00 2001 From: Dan Tamas Date: Wed, 13 Dec 2017 18:19:27 +0100 Subject: [PATCH 0356/1148] add issue_template.md (#1878) * add issue_template.md * improve Target Platform examples * ask to specify the usage of Apple/Google for iOS --- .github/ISSUE_TEMPLATE.md | 109 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE.md diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md new file mode 100644 index 000000000..47a23e5f4 --- /dev/null +++ b/.github/ISSUE_TEMPLATE.md @@ -0,0 +1,109 @@ + + +### Is this a bug report? + +(write your answer here) + + + +### Have you read the [Installation Instructions](https://github.com/react-community/react-native-maps/blob/master/docs/installation.md)? + +(Write your answer here.) + +### Environment + + + +### Steps to Reproduce + + + +(Write your steps here:) + +1. 2. 3. + +### Expected Behavior + + + +(Write what you thought would happen.) + +### Actual Behavior + + + +(Write what happened. Add screenshots!) + +### Reproducible Demo + + + +(Paste the link to an example project and exact instructions to reproduce the issue.) + + From a7bbfacf0dbd0b81aaf192123822df9cf15ae049 Mon Sep 17 00:00:00 2001 From: Peter Zavadsky Date: Thu, 14 Dec 2017 14:47:03 +0100 Subject: [PATCH 0357/1148] Updated documentation in main README file --- README.md | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index e11e91b88..518959f65 100644 --- a/README.md +++ b/README.md @@ -151,8 +151,10 @@ render() { ### Using a custom Tile Overlay +#### Tile Overlay using tile server + ```jsx - @@ -172,6 +174,33 @@ For Android: add the following line in your AndroidManifest.xml ``` For IOS: configure [App Transport Security](https://developer.apple.com/library/content/documentation/General/Reference/InfoPlistKeyReference/Articles/CocoaKeys.html#//apple_ref/doc/uid/TP40009251-SW33) in your app +#### Tile Overlay using local tiles + +Tiles can be stored locally within device using xyz tiling scheme and displayed as tile overlay as well. This is usefull especially for offline map usage when tiles are available for selected map region within device storage. + +```jsx + + + +``` + +For Android: if original (for example Google) tiles are not desirable (no need to download them when using offline tiles), set mapType to 'none'. + +See [OSM Wiki](https://wiki.openstreetmap.org/wiki/Category:Tile_downloading) for how to download tiles for offline usage. + ### Customizing the map style Create the json object, or download a generated one from the [google style generator](https://mapstyle.withgoogle.com/). From 6e10573cdeb22e6f1b0a92752ef25a5f610b9621 Mon Sep 17 00:00:00 2001 From: Peter Zavadsky Date: Thu, 14 Dec 2017 15:23:57 +0100 Subject: [PATCH 0358/1148] More thorough explanation for Android mapType='none' --- README.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 518959f65..f0235f94a 100644 --- a/README.md +++ b/README.md @@ -197,7 +197,12 @@ Tiles can be stored locally within device using xyz tiling scheme and displayed ``` -For Android: if original (for example Google) tiles are not desirable (no need to download them when using offline tiles), set mapType to 'none'. +For Android: LocalTile is still just overlay over original map tiles. It means that if device is online, underlying tiles will be still downloaded. If original tiles download/display is not desirable set mapType to 'none'. For example: +``` + +``` See [OSM Wiki](https://wiki.openstreetmap.org/wiki/Category:Tile_downloading) for how to download tiles for offline usage. From 3f0bf044cbeaea98b8c8e65332013b7b637efd2b Mon Sep 17 00:00:00 2001 From: Dan Tamas Date: Thu, 14 Dec 2017 16:39:17 +0100 Subject: [PATCH 0359/1148] update install instructions (#1884) --- docs/installation.md | 142 +++++++++++++++++++++++++++---------------- 1 file changed, 88 insertions(+), 54 deletions(-) diff --git a/docs/installation.md b/docs/installation.md index acd1f4657..3263b5cb1 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -6,68 +6,87 @@ First, download the library from npm: npm install react-native-maps --save ``` -Second, install the native dependencies: You can use `rnpm` (now part of `react-native` core via `link`) to -add native dependencies automatically then continue the directions below depending on your target OS. -``` -react-native link react-native-maps -``` +## Get a map developer key + +Go to https://developers.google.com/maps/documentation/ios-sdk/get-api-key and get your key. + +Without this key the map won't render anything. + + + +## IMPORTANT!! - >This installation should work in physical devices. For Genymotion, be sure to check Android installation about Google Play Services +**!! DO NOT USE !!** `react-native link` -## iOS +## iOS - CocoaPods -> These options may not be necessary if you ran "react-native link" +Setup your `Podfile` (found at `/ios/Podfile` as below, replace all references to `AirMapsExplorer` with your project name, and then run `pod install` while in the `ios` folder. -### Option 1: CocoaPods - Same as the included AirMapsExplorer example +~~~ +# Uncomment the next line to define a global platform for your project +# platform :ios, '9.0' -1. Setup your `Podfile` like the included [example/ios/Podfile](../example/ios/Podfile), replace all references to `AirMapsExplorer` with your project name, and then run `pod install`. - (If you do not need `GoogleMaps` support for iOS, then you can probably completely skip this step.) -1. Open your project in Xcode workspace -1. If you need `GoogleMaps` support also - - Drag this folder `node_modules/react-native-maps/lib/ios/AirGoogleMaps/` into your project, and choose `Create groups` and `Copy items if needed` in the popup window. - - In `AppDelegate.m`, add `@import GoogleMaps;` before `@implementation AppDelegate`. In `- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions`, add `[GMSServices provideAPIKey:@"YOUR_GOOGLE_MAP_API_KEY"];` - - In your project's `Build Settings` > `Header Search Paths`, double click the value field. In the popup, add `$(SRCROOT)/../node_modules/react-native-maps/lib/ios/AirMaps` and change `non-recursive` to `recursive`. (Dragging the folder `node_modules/react-native-maps/lib/ios/AirMaps/` into your project introduces duplicate symbols. We should not do it.) +target 'AirMapsExplorer' do + rn_path = '../node_modules/react-native' -Note: We recommend using a version of React Native >= .40. Newer versions (>= .40) require `package.json` to be set to `"react-native-maps": "^0.13.0"`, while older versions require `"react-native-maps": "^0.12.4"`. + pod 'yoga', path: "#{rn_path}/ReactCommon/yoga/yoga.podspec" + pod 'React', path: rn_path, subspecs: [ + 'Core', + 'RCTActionSheet', + 'RCTAnimation', + 'RCTGeolocation', + 'RCTImage', + 'RCTLinkingIOS', + 'RCTNetwork', + 'RCTSettings', + 'RCTText', + 'RCTVibration', + 'RCTWebSocket', + 'BatchedBridge' + ] -### Option 2: CocoaPods -This is now considered the **old way** because it will only work if you **don't** have -`use_frameworks!` in your `Podfile`. + pod 'GoogleMaps' # Remove this line if you don't want to support GoogleMaps on iOS + pod 'react-native-maps', path: '../node_modules/react-native-maps' + pod 'react-native-google-maps', path: '../node_modules/react-native-maps' # Remove this line if you don't want to support GoogleMaps on iOS +end -To install using Cocoapods, simply insert the following line into your `Podfile`: +post_install do |installer| + installer.pods_project.targets.each do |target| + if target.name == 'react-native-google-maps' + target.build_configurations.each do |config| + config.build_settings['CLANG_ENABLE_MODULES'] = 'No' + end + end + if target.name == "React" + target.remove_from_project + end + end +end +~~~ - pod 'react-native-maps', :path => '../node_modules/react-native-maps' -If you need `GoogleMaps` support in iOS also add this line: +## If you want to Google maps - pod 'react-native-google-maps', :path => '../node_modules/react-native-maps' +Add to `ios/_YOUR_PROJECT_NAME_/AppDelegate.m: -Now if you need `GoogleMaps` support you will also have to add a bunch of other stuff to your -`Podfile`. See the **comments* in the included [example/ios/Podfile](../example/ios/Podfile) which explain the rest. +``` ++ @import GoogleMaps; //add this line if you +@implementation AppDelegate +... + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions +{ + ++ [GMSServices provideAPIKey:@"_YOUR_API_KEY"]; // add this line using the api key obtained from Google Console +``` -After your `Podfile` is setup properly, run `pod install`. -### Option 3: Manually - >This was already done for you if you ran "react-native link" -1. Open your project in Xcode, right click on `Libraries` and click `Add - Files to "Your Project Name"` Look under `node_modules/react-native-maps/lib/ios` and add `AIRMaps.xcodeproj`. -1. Add `libAIRMaps.a` to `Build Phases -> Link Binary With Libraries. -1. Click on `AIRMaps.xcodeproj` in `Libraries` and go the `Build - Settings` tab. Double click the text to the right of `Header Search - Paths` and verify that it has `$(SRCROOT)/../../react-native/React` as well as `$(SRCROOT)/../../react-native/Libraries/Image` - if they - aren't, then add them. This is so Xcode is able to find the headers that - the `AIRMaps` source files are referring to by pointing to the - header files installed within the `react-native` `node_modules` - directory. -1. Whenever you want to use it within React code now you can: `var MapView = - require('react-native-maps');` ## Android 1. In your `android/app/build.gradle` add: - >This step is not necessary if you ran "react-native link react-native-maps" ```groovy ... @@ -92,8 +111,7 @@ After your `Podfile` is setup properly, run `pod install`. } ``` -1. In your `android/settings.gradle` add: - >This step is not necessary if you ran "react-native link" +2. In your `android/settings.gradle` add: ```groovy ... @@ -101,8 +119,7 @@ After your `Podfile` is setup properly, run `pod install`. project(':react-native-maps').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-maps/lib/android') ``` -1. Specify your Google Maps API Key: - > For development, you need to get a ***API Key***. Go to https://console.developers.google.com/apis/credentials to check your credentials. +3. Specify your Google Maps API Key: Add your API key to your manifest file (`android\app\src\main\AndroidManifest.xml`): @@ -117,27 +134,45 @@ After your `Podfile` is setup properly, run `pod install`. > Note: As shown above, com.google.android.geo.API_KEY is the recommended metadata name for the API key. A key with this name can be used to authenticate to multiple Google Maps-based APIs on the Android platform, including the Google Maps Android API. For backwards compatibility, the API also supports the name com.google.android.maps.v2.API_KEY. This legacy name allows authentication to the Android Maps API v2 only. An application can specify only one of the API key metadata names. If both are specified, the API throws an exception. Source: https://developers.google.com/maps/documentation/android-api/signup -1. Ensure that you have Google Play Services installed: + +4. Add `new MapsPackage()` in your `MainApplication.java` : + + ``` + import com.airbnb.android.react.maps.MapsPackage; + ... + @Override + protected List getPackages() { + return Arrays.asList( + new MainReactPackage(), + new MapsPackage() + ); + } + ``` + + +5. Ensure that you have Google Play Services installed: * For Genymotion you can follow [these instructions](https://www.genymotion.com/help/desktop/faq/#google-play-services). * For a physical device you need to search on Google for 'Google Play Services'. There will be a link that takes you to the Play Store and from there you will see a button to update it (do not search within the Play Store). ## Troubleshooting -If you get the error `duplicate symbols for architecture x86_64` when building for iOS, you may need to reconfigure your linking and Podfile as [described in detail in this comment on issue #718](https://github.com/airbnb/react-native-maps/issues/718#issuecomment-295585410) - If you have a blank map issue, ([#118](https://github.com/airbnb/react-native-maps/issues/118), [#176](https://github.com/airbnb/react-native-maps/issues/176), [#684](https://github.com/airbnb/react-native-maps/issues/684)), try the following lines : ### On iOS: -You have to link dependencies with rnpm and re-run the build: +If you have ran 'react-native link` by mistake: -1. `react-native link react-native-maps` -1. `react-native run-ios` +1. delete node_modules +2. delete ios/Pods +3. delete ios/Podfile.lock +4. open Xcode and delete `AIRMaps.xcodeproj` from Libraries if it exists +5. in Build Phases -> Link Binary With Libraries delete `libAIRMaps.a` if it exists +6. delete ios/build folder +7. start again with the installation steps ### On Android: 1. Be sure to have `new MapsPackage()` in your `MainApplication.java` : - >This step is not necessary if you ran "react-native link react-native-maps" ``` import com.airbnb.android.react.maps.MapsPackage; @@ -196,7 +231,6 @@ You have to link dependencies with rnpm and re-run the build: - Extras / Google Repository - Android 6.0 (API 23) / Google APIs Intel x86 Atom System Image Rev. 19 - Android SDK Build-tools 23.0.3 -1. Check manual installation steps if you didn't run "react-native link react-native-maps" 1. Go to [Google API Console](https://console.developers.google.com/flows/enableapi?apiid=maps_android_backend) and select your project, or create one. Then, once enabled, select `Go to credentials`. Select `Google Maps Android API` and create a new key. From e0a7218fce30f7d00db32e893e454b53f26d6ab8 Mon Sep 17 00:00:00 2001 From: Dan Tamas Date: Thu, 14 Dec 2017 16:39:58 +0100 Subject: [PATCH 0360/1148] Fix podfile, example and setup instructions so the example runs (#1879) * fix podfile and example setup instructions so the example runs * update react, reactnative and pods deps * simplify example setup to use existent scripts * remove SyntheticEvent - react 16+ seems not to have it exposed anymore * import PropTypes from prop-types * migrate createClass to es6 Component in PanContrioler * upgrade build.gradle to use react-native:0.51.+ --- Gemfile | 3 +- Gemfile.lock | 58 +++++++------ docs/examples-setup.md | 28 +++++-- example/android/app/build.gradle | 2 +- example/examples/AnimatedPriceMarker.js | 4 +- example/examples/CustomCallout.js | 4 +- .../examples/CustomOverlayXMarksTheSpot.js | 4 +- example/examples/EventListener.js | 8 +- example/examples/MyLocationMapMarker.js | 4 +- example/examples/PanController.js | 82 ++++++++----------- example/examples/PriceMarker.js | 4 +- .../AirMapsExplorer.xcodeproj/project.pbxproj | 2 +- example/ios/Podfile.lock | 69 ++++++++-------- package.json | 11 +-- 14 files changed, 146 insertions(+), 137 deletions(-) diff --git a/Gemfile b/Gemfile index e696ba58e..830868486 100644 --- a/Gemfile +++ b/Gemfile @@ -1,3 +1,2 @@ source 'https://rubygems.org' -ruby '2.2.4' -gem 'cocoapods', '1.2.0' +gem 'cocoapods' diff --git a/Gemfile.lock b/Gemfile.lock index 9265653cd..18a2c40a5 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,34 +1,34 @@ GEM remote: https://rubygems.org/ specs: - CFPropertyList (2.3.5) - activesupport (4.2.8) + CFPropertyList (2.3.6) + activesupport (4.2.10) i18n (~> 0.7) minitest (~> 5.1) thread_safe (~> 0.3, >= 0.3.4) tzinfo (~> 1.1) - claide (1.0.1) - cocoapods (1.2.0) + claide (1.0.2) + cocoapods (1.3.1) activesupport (>= 4.0.2, < 5) - claide (>= 1.0.1, < 2.0) - cocoapods-core (= 1.2.0) + claide (>= 1.0.2, < 2.0) + cocoapods-core (= 1.3.1) cocoapods-deintegrate (>= 1.0.1, < 2.0) cocoapods-downloader (>= 1.1.3, < 2.0) cocoapods-plugins (>= 1.0.0, < 2.0) cocoapods-search (>= 1.0.0, < 2.0) cocoapods-stats (>= 1.0.0, < 2.0) - cocoapods-trunk (>= 1.1.2, < 2.0) + cocoapods-trunk (>= 1.2.0, < 2.0) cocoapods-try (>= 1.1.0, < 2.0) - colored (~> 1.2) + colored2 (~> 3.1) escape (~> 0.0.4) fourflusher (~> 2.0.1) gh_inspector (~> 1.0) - molinillo (~> 0.5.5) + molinillo (~> 0.5.7) nap (~> 1.0) - ruby-macho (~> 0.2.5) - xcodeproj (>= 1.4.1, < 2.0) - cocoapods-core (1.2.0) - activesupport (>= 4.0.2, < 5) + ruby-macho (~> 1.1) + xcodeproj (>= 1.5.1, < 2.0) + cocoapods-core (1.3.1) + activesupport (>= 4.0.2, < 6) fuzzy_match (~> 2.0.4) nap (~> 1.0) cocoapods-deintegrate (1.0.1) @@ -37,40 +37,38 @@ GEM nap cocoapods-search (1.0.0) cocoapods-stats (1.0.0) - cocoapods-trunk (1.1.2) + cocoapods-trunk (1.3.0) nap (>= 0.8, < 2.0) - netrc (= 0.7.8) + netrc (~> 0.11) cocoapods-try (1.1.0) - colored (1.2) + colored2 (3.1.2) + concurrent-ruby (1.0.5) escape (0.0.4) fourflusher (2.0.1) fuzzy_match (2.0.4) gh_inspector (1.0.3) - i18n (0.8.1) - minitest (5.10.1) + i18n (0.9.1) + concurrent-ruby (~> 1.0) + minitest (5.10.3) molinillo (0.5.7) nanaimo (0.2.3) nap (1.1.0) - netrc (0.7.8) - ruby-macho (0.2.6) + netrc (0.11.0) + ruby-macho (1.1.0) thread_safe (0.3.6) - tzinfo (1.2.3) + tzinfo (1.2.4) thread_safe (~> 0.1) - xcodeproj (1.4.2) + xcodeproj (1.5.3) CFPropertyList (~> 2.3.3) - activesupport (>= 3) - claide (>= 1.0.1, < 2.0) - colored (~> 1.2) + claide (>= 1.0.2, < 2.0) + colored2 (~> 3.1) nanaimo (~> 0.2.3) PLATFORMS ruby DEPENDENCIES - cocoapods (= 1.2.0) - -RUBY VERSION - ruby 2.2.4p230 + cocoapods BUNDLED WITH - 1.14.6 + 1.15.4 diff --git a/docs/examples-setup.md b/docs/examples-setup.md index 048dd46e7..951a4505a 100644 --- a/docs/examples-setup.md +++ b/docs/examples-setup.md @@ -11,23 +11,33 @@ gem install bundler 2. Install dependencies and open the workspace: ``` -cd example npm install -cd ios -bundle install -bundle exec pod install -open AirMapsExplorer.xcworkspace +rpm run build:ios +rpm run run:ios ``` -3. Make sure the `AirMapsExplorer` target is selected and click `Run` +or + +``` +yarn install +yarn build:ios +yarn run:ios +``` ## android 1. Start your emulator -2. Install via gradle: +2. Install dependencies and run the example: + +``` +npm install +npm run run:android +``` + +or ``` -# from the example/ dir: -react-native run-android +yarn install +yarn run:android ``` diff --git a/example/android/app/build.gradle b/example/android/app/build.gradle index 7a8e8b7dd..d2b475051 100644 --- a/example/android/app/build.gradle +++ b/example/android/app/build.gradle @@ -127,7 +127,7 @@ android { } dependencies { - compile 'com.facebook.react:react-native:0.45.+' + compile 'com.facebook.react:react-native:0.51.+' compile 'com.android.support:appcompat-v7:25.3.0' compile 'com.android.support:support-annotations:25.3.0' compile project(':react-native-maps-lib') diff --git a/example/examples/AnimatedPriceMarker.js b/example/examples/AnimatedPriceMarker.js index 9e39acbc1..2d876c0ae 100644 --- a/example/examples/AnimatedPriceMarker.js +++ b/example/examples/AnimatedPriceMarker.js @@ -1,4 +1,6 @@ -import React, { PropTypes } from 'react'; +import React from 'react'; +import PropTypes from 'prop-types'; + import { StyleSheet, Text, diff --git a/example/examples/CustomCallout.js b/example/examples/CustomCallout.js index 719f04a96..55cb9eb0f 100644 --- a/example/examples/CustomCallout.js +++ b/example/examples/CustomCallout.js @@ -1,4 +1,6 @@ -import React, { PropTypes } from 'react'; +import React from 'react'; +import PropTypes from 'prop-types'; + import { StyleSheet, View, diff --git a/example/examples/CustomOverlayXMarksTheSpot.js b/example/examples/CustomOverlayXMarksTheSpot.js index ada19da9c..b9957a81d 100644 --- a/example/examples/CustomOverlayXMarksTheSpot.js +++ b/example/examples/CustomOverlayXMarksTheSpot.js @@ -1,4 +1,6 @@ -import React, { PropTypes } from 'react'; +import React from 'react'; +import PropTypes from 'prop-types'; + import { View } from 'react-native'; import MapView from 'react-native-maps'; diff --git a/example/examples/EventListener.js b/example/examples/EventListener.js index 19a393063..459f087b5 100644 --- a/example/examples/EventListener.js +++ b/example/examples/EventListener.js @@ -1,4 +1,6 @@ -import React, { PropTypes } from 'react'; +import React from 'react'; +import PropTypes from 'prop-types'; + import { StyleSheet, View, @@ -7,7 +9,6 @@ import { ScrollView, } from 'react-native'; // eslint-disable-next-line max-len -import SyntheticEvent from 'react-native/Libraries/Renderer/src/renderers/shared/shared/event/SyntheticEvent'; import MapView from 'react-native-maps'; import PriceMarker from './PriceMarker'; @@ -67,9 +68,6 @@ class EventListener extends React.Component { recordEvent(name) { return e => { - if (e instanceof SyntheticEvent && typeof e.persist === 'function') { - e.persist(); - } this.setState(prevState => ({ events: [ this.makeEvent(e, name), diff --git a/example/examples/MyLocationMapMarker.js b/example/examples/MyLocationMapMarker.js index fff3f2b37..56fc10f80 100644 --- a/example/examples/MyLocationMapMarker.js +++ b/example/examples/MyLocationMapMarker.js @@ -1,4 +1,6 @@ -import React, { PropTypes } from 'react'; +import React from 'react'; +import PropTypes from 'prop-types'; + import { StyleSheet, Text, diff --git a/example/examples/PanController.js b/example/examples/PanController.js index 4857ea099..ac8e4a119 100644 --- a/example/examples/PanController.js +++ b/example/examples/PanController.js @@ -1,6 +1,8 @@ /* eslint-disable */ -import React, { PropTypes } from 'react'; +import React from 'react'; +import PropTypes from 'prop-types'; + import { View, Animated, @@ -11,9 +13,9 @@ const ModePropType = PropTypes.oneOf(['decay', 'snap', 'spring-origin']); const OvershootPropType = PropTypes.oneOf(['spring', 'clamp']); const AnimatedPropType = PropTypes.any; -const PanController = React.createClass({ +class PanController extends React.Component{ - propTypes: { + static propTypes = { // Component Config lockDirection: PropTypes.bool, horizontal: PropTypes.bool, @@ -46,30 +48,7 @@ const PanController = React.createClass({ onRelease: PropTypes.func, //...PanResponderPropTypes, - }, - - getDefaultProps() { - return { - horizontal: false, - vertical: false, - lockDirection: true, - overshootX: 'spring', - overshootY: 'spring', - panX: new Animated.Value(0), - panY: new Animated.Value(0), - xBounds: [-Infinity, Infinity], - yBounds: [-Infinity, Infinity], - yMode: 'decay', - xMode: 'decay', - overshootSpringConfig: { friction: 7, tension: 40 }, - momentumDecayConfig: { deceleration: 0.993 }, - springOriginConfig: { friction: 7, tension: 40 }, - overshootReductionFactor: 3, - directionLockDistance: 10, - onStartShouldSetPanResponder: () => true, - onMoveShouldSetPanResponder: () => true, - }; - }, + } // getInitialState() { // //TODO: @@ -84,9 +63,20 @@ const PanController = React.createClass({ // }; // }, - _responder: null, - _listener: null, - _direction: null, + _responder = null + _listener = null + _direction = null + + constructor(props) { + super(props) + + this.deceleration = 0.997; + if (props.momentumDecayConfig && this.props.momentumDecayConfig.deceleration) { + this.deceleration = this.props.momentumDecayConfig.deceleration; + } + } + + componentWillMount() { this._responder = PanResponder.create({ @@ -192,7 +182,7 @@ const PanController = React.createClass({ this._direction = horizontal && !vertical ? 'x' : (vertical && !horizontal ? 'y' : null); }, }); - }, + } handleResponderMove(anim, delta, min, max, overshoot) { let val = anim._offset + delta; @@ -219,7 +209,7 @@ const PanController = React.createClass({ } val = val - anim._offset; anim.setValue(val); - }, + } handleResponderRelease(anim, min, max, velocity, overshoot, mode, snapSpacing) { anim.flattenOffset(); @@ -276,7 +266,7 @@ const PanController = React.createClass({ break; } } - }, + } handleResponderGrant(anim, mode) { switch (mode) { @@ -289,7 +279,7 @@ const PanController = React.createClass({ anim.setValue(0); break; } - }, + } handleMomentumScroll(anim, min, max, velocity, overshoot) { Animated.decay(anim, { @@ -336,7 +326,7 @@ const PanController = React.createClass({ } } }); - }, + } handleSnappedScroll(anim, min, max, velocity, spacing) { let endX = this.momentumCenter(anim._value, velocity, spacing); @@ -360,23 +350,22 @@ const PanController = React.createClass({ }).start(() => { anim.removeListener(this._listener); }); - }, + } closestCenter(x, spacing) { const plus = (x % spacing) < spacing / 2 ? 0 : spacing; return Math.round(x / spacing) * spacing + plus; - }, + } momentumCenter(x0, vx, spacing) { let t = 0; - const deceleration = this.props.momentumDecayConfig.deceleration || 0.997; let x1 = x0; let x = x1; while (true) { t += 16; - x = x0 + (vx / (1 - deceleration)) * - (1 - Math.exp(-(1 - deceleration) * t)); + x = x0 + (vx / (1 - this.deceleration)) * + (1 - Math.exp(-(1 - this.deceleration) * t)); if (Math.abs(x - x1) < 0.1) { x1 = x; break; @@ -384,18 +373,17 @@ const PanController = React.createClass({ x1 = x; } return this.closestCenter(x1, spacing); - }, + } velocityAtBounds(x0, vx, bounds) { let t = 0; - const deceleration = this.props.momentumDecayConfig.deceleration || 0.997; let x1 = x0; let x = x1; let vf; while (true) { t += 16; - x = x0 + (vx / (1 - deceleration)) * - (1 - Math.exp(-(1 - deceleration) * t)); + x = x0 + (vx / (1 - this.deceleration)) * + (1 - Math.exp(-(1 - this.deceleration) * t)); vf = (x - x1) / 16; if (x > bounds[0] && x < bounds[1]) { break; @@ -406,7 +394,7 @@ const PanController = React.createClass({ x1 = x; } return vf; - }, + } // componentDidMount() { // //TODO: we may need to measure the children width/height here? @@ -422,7 +410,7 @@ const PanController = React.createClass({ render() { return ; - }, -}); + } +}; module.exports = PanController; diff --git a/example/examples/PriceMarker.js b/example/examples/PriceMarker.js index ba40ac10b..a1b1591d7 100644 --- a/example/examples/PriceMarker.js +++ b/example/examples/PriceMarker.js @@ -1,4 +1,6 @@ -import React, { PropTypes } from 'react'; +import React from 'react'; +import PropTypes from 'prop-types'; + import { StyleSheet, View, diff --git a/example/ios/AirMapsExplorer.xcodeproj/project.pbxproj b/example/ios/AirMapsExplorer.xcodeproj/project.pbxproj index 21d588c64..dc9fb85bd 100644 --- a/example/ios/AirMapsExplorer.xcodeproj/project.pbxproj +++ b/example/ios/AirMapsExplorer.xcodeproj/project.pbxproj @@ -290,7 +290,7 @@ ); inputPaths = ( "${SRCROOT}/Pods/Target Support Files/Pods-AirMapsExplorer/Pods-AirMapsExplorer-resources.sh", - "${PODS_ROOT}/GoogleMaps/Maps/Frameworks/GoogleMaps.framework/Versions/A/Resources/GoogleMaps.bundle", + "${PODS_ROOT}/GoogleMaps/Maps/Frameworks/GoogleMaps.framework/Resources/GoogleMaps.bundle", ); name = "[CP] Copy Pods Resources"; outputPaths = ( diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index b17a261de..ec77fdbb4 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -1,46 +1,51 @@ PODS: - - GoogleMaps (2.1.1): - - GoogleMaps/Maps (= 2.1.1) - - GoogleMaps/Base (2.1.1) - - GoogleMaps/Maps (2.1.1): + - GoogleMaps (2.5.0): + - GoogleMaps/Maps (= 2.5.0) + - GoogleMaps/Base (2.5.0) + - GoogleMaps/Maps (2.5.0): - GoogleMaps/Base - - React (0.45.1): - - React/Core (= 0.45.1) + - React (0.51.0): + - React/Core (= 0.51.0) - react-native-google-maps (0.18.3): - - GoogleMaps (= 2.1.1) + - GoogleMaps (= 2.5.0) - React - react-native-maps (0.18.3): - React - - React/BatchedBridge (0.45.1): + - React/BatchedBridge (0.51.0): - React/Core - React/cxxreact_legacy - - React/Core (0.45.1): - - Yoga (= 0.45.1.React) - - React/cxxreact_legacy (0.45.1): + - React/Core (0.51.0): + - yoga (= 0.51.0.React) + - React/cxxreact_legacy (0.51.0): - React/jschelpers_legacy - - React/jschelpers_legacy (0.45.1) - - React/RCTActionSheet (0.45.1): + - React/fishhook (0.51.0) + - React/jschelpers_legacy (0.51.0) + - React/RCTActionSheet (0.51.0): - React/Core - - React/RCTAnimation (0.45.1): + - React/RCTAnimation (0.51.0): - React/Core - - React/RCTGeolocation (0.45.1): + - React/RCTBlob (0.51.0): - React/Core - - React/RCTImage (0.45.1): + - React/RCTGeolocation (0.51.0): + - React/Core + - React/RCTImage (0.51.0): - React/Core - React/RCTNetwork - - React/RCTLinkingIOS (0.45.1): + - React/RCTLinkingIOS (0.51.0): - React/Core - - React/RCTNetwork (0.45.1): + - React/RCTNetwork (0.51.0): - React/Core - - React/RCTSettings (0.45.1): + - React/RCTSettings (0.51.0): - React/Core - - React/RCTText (0.45.1): + - React/RCTText (0.51.0): - React/Core - - React/RCTVibration (0.45.1): + - React/RCTVibration (0.51.0): - React/Core - - React/RCTWebSocket (0.45.1): + - React/RCTWebSocket (0.51.0): - React/Core - - Yoga (0.45.1.React) + - React/fishhook + - React/RCTBlob + - yoga (0.51.0.React) DEPENDENCIES: - GoogleMaps @@ -58,7 +63,7 @@ DEPENDENCIES: - React/RCTText (from `../../node_modules/react-native`) - React/RCTVibration (from `../../node_modules/react-native`) - React/RCTWebSocket (from `../../node_modules/react-native`) - - Yoga (from `../../node_modules/react-native/ReactCommon/yoga/Yoga.podspec`) + - yoga (from `../../node_modules/react-native/ReactCommon/yoga/yoga.podspec`) EXTERNAL SOURCES: React: @@ -67,16 +72,16 @@ EXTERNAL SOURCES: :path: ../../ react-native-maps: :path: ../../ - Yoga: - :path: ../../node_modules/react-native/ReactCommon/yoga/Yoga.podspec + yoga: + :path: ../../node_modules/react-native/ReactCommon/yoga/yoga.podspec SPEC CHECKSUMS: - GoogleMaps: a5b5bbe47734e2443bde781a6aa64e69fdb6d785 - React: 0c9191a8b0c843d7004f950ac6b5f6cba9d125c7 - react-native-google-maps: 73a7f74a00d36c74df41388ebb8394ceba81ef0e - react-native-maps: ee0bb36520eb49dfc2bf11754a486a4fa5c5f883 - Yoga: 89c8738d42a0b46a113acb4e574336d61cba2985 + GoogleMaps: c087b8e5dfe87ca6ebf59adb9b4894a4146bec4f + React: 352f02f1db6e4744f9a758527e13e3fdefbbd6ba + react-native-google-maps: 57af8d96a008489af2657caaeb074e7448451ff8 + react-native-maps: 016cff46e0ae7ad4c1b1143a1aa2044e9983a544 + yoga: b5d96400ca8b2936965a7a6516da7c1177f432a3 -PODFILE CHECKSUM: c069397afd4c9ecf6886b7c00e7d7264dced43a4 +PODFILE CHECKSUM: 3785dd4599f2a790496347330ebfcc43450c1692 COCOAPODS: 1.3.1 diff --git a/package.json b/package.json index 06d3a97bc..dc9b05641 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,8 @@ "lint": "eslint ./", "build": "npm run build:js && npm run build:android && npm run build:ios", "build:js": "exit 0", - "build:ios": "bundle install --binstubs ./examples/ios && bundle exec pod install --project-directory=./example/ios/", + "build:ios": + "bundle install --binstubs ./examples/ios && bundle exec pod install --project-directory=./example/ios/", "build:android": "./gradlew :react-native-maps:assembleDebug", "ci": "npm run lint", "preversion": "./scripts/update-version.js" @@ -32,8 +33,8 @@ "mapkit" ], "peerDependencies": { - "react": ">=15.4.0 || ^16.0.0-alpha", - "react-native": ">=0.40", + "react": "16.0.0", + "react-native": "0.51.0", "prop-types": "^15.5.10" }, "devDependencies": { @@ -50,8 +51,8 @@ "gitbook-cli": "^2.3.0", "lodash": "^4.17.2", "prop-types": "^15.5.10", - "react": "16.0.0-alpha.12", - "react-native": "^0.45.1" + "react": "16.0.0", + "react-native": "0.51.0" }, "rnpm": { "android": { From 19c30b2ef0ac288cac3c2af808e44f0ac936f549 Mon Sep 17 00:00:00 2001 From: "A.T" Date: Thu, 14 Dec 2017 17:07:48 +0100 Subject: [PATCH 0361/1148] fixed region/initialRegion null overrides of this.props (#1715) * fixed region/initialRegion null overrides of this.props * Update MapView.js --- lib/components/MapView.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/components/MapView.js b/lib/components/MapView.js index 842225a81..c476696b7 100644 --- a/lib/components/MapView.js +++ b/lib/components/MapView.js @@ -657,13 +657,13 @@ class MapView extends React.Component { if (this.state.isReady) { props = { - ...this.props, region: null, initialRegion: null, onMarkerPress: this._onMarkerPress, onChange: this._onChange, onMapReady: this._onMapReady, onLayout: this._onLayout, + ...this.props, }; if (Platform.OS === 'ios' && props.provider === ProviderConstants.PROVIDER_DEFAULT && GOOGLE_MAPS_ONLY_TYPES.includes(props.mapType)) { From 85bb84f73ff5679207729ec57b46bd94fccfe727 Mon Sep 17 00:00:00 2001 From: Dan Tamas Date: Thu, 14 Dec 2017 18:32:20 +0100 Subject: [PATCH 0362/1148] Revert "Merge pull request #1 from react-community/master" From a51f0d5ed1c7dc7d82cd28170bb6b2d3883f74b8 Mon Sep 17 00:00:00 2001 From: Dan Tamas Date: Thu, 14 Dec 2017 23:09:21 +0100 Subject: [PATCH 0363/1148] Fix main install docs (#1887) * update install instructions * small addition to install docs --- docs/installation.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/installation.md b/docs/installation.md index 3263b5cb1..2250aefd9 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -71,7 +71,7 @@ end Add to `ios/_YOUR_PROJECT_NAME_/AppDelegate.m: ``` -+ @import GoogleMaps; //add this line if you ++ @import GoogleMaps; //add this line if you want to use GoogleMaps @implementation AppDelegate ... @@ -135,7 +135,7 @@ Add to `ios/_YOUR_PROJECT_NAME_/AppDelegate.m: Source: https://developers.google.com/maps/documentation/android-api/signup -4. Add `new MapsPackage()` in your `MainApplication.java` : +4. Add `import com.airbnb.android.react.maps.MapsPackage;` and `new MapsPackage()` in your `MainApplication.java` : ``` import com.airbnb.android.react.maps.MapsPackage; From 8d15576d95fd7a794a8bf0dce00c3cf460c1cd78 Mon Sep 17 00:00:00 2001 From: Christopher Dro Date: Thu, 14 Dec 2017 14:18:21 -0800 Subject: [PATCH 0364/1148] Update examples-setup.md (#1888) --- docs/examples-setup.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/examples-setup.md b/docs/examples-setup.md index 951a4505a..89dfc3362 100644 --- a/docs/examples-setup.md +++ b/docs/examples-setup.md @@ -12,8 +12,8 @@ gem install bundler ``` npm install -rpm run build:ios -rpm run run:ios +npm run build:ios +npm run run:ios ``` or From c45131096fda44383335099bee80c2cd2136c231 Mon Sep 17 00:00:00 2001 From: Christopher Dro Date: Thu, 14 Dec 2017 14:32:49 -0800 Subject: [PATCH 0365/1148] v0.19.0 --- .github/ISSUE_TEMPLATE.md | 2 +- CHANGELOG.md | 5 +++++ example/ios/Podfile.lock | 4 ++-- lib/android/gradle.properties | 2 +- package.json | 2 +- 5 files changed, 10 insertions(+), 5 deletions(-) diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index 47a23e5f4..9cc3d0cdb 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -32,7 +32,7 @@ react-native: 0.51.0 react: 16.0.0 - react-native-maps: 0.18.3 or "git+ssh://git@github.com/react-community/react-native-maps.git" + react-native-maps: 0.19.0 or "git+ssh://git@github.com/react-community/react-native-maps.git" ***Make sure you are on v0.48.0 or greater of react-native, otherwise you may get this error: diff --git a/CHANGELOG.md b/CHANGELOG.md index 109091a39..67449849b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Change Log +## 0.19.0 (December 14, 2017) +* Common: [#1715](https://github.com/airbnb/react-native-maps/pull/1715) Fixed region/initialRegion null overrides of this.props +* Common: [#1876](https://github.com/airbnb/react-native-maps/pull/1876) Added support for locally stored tile overlay +* iOS: [#1854](https://github.com/airbnb/react-native-maps/pull/1854) Update GoogleMaps dependency to 2.5.0 + ## 0.18.3 (November 30, 2017) * Android: [#1839](https://github.com/airbnb/react-native-maps/pull/1839) [AirGoogleMapManager] Use RCTDirectEventBlock for onMarkerPress diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index ec77fdbb4..5f60a8294 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -6,10 +6,10 @@ PODS: - GoogleMaps/Base - React (0.51.0): - React/Core (= 0.51.0) - - react-native-google-maps (0.18.3): + - react-native-google-maps (0.19.0): - GoogleMaps (= 2.5.0) - React - - react-native-maps (0.18.3): + - react-native-maps (0.19.0): - React - React/BatchedBridge (0.51.0): - React/Core diff --git a/lib/android/gradle.properties b/lib/android/gradle.properties index e4ea9f69d..97093a06a 100644 --- a/lib/android/gradle.properties +++ b/lib/android/gradle.properties @@ -1,5 +1,5 @@ VERSION_CODE=4 -VERSION_NAME=0.18.3 +VERSION_NAME=0.19.0 GROUP=com.airbnb.android POM_DESCRIPTION=React Native Map view component for Android diff --git a/package.json b/package.json index dc9b05641..87b595397 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "description": "React Native Mapview component for iOS + Android", "main": "index.js", "author": "Leland Richardson ", - "version": "0.18.3", + "version": "0.19.0", "scripts": { "start": "node node_modules/react-native/local-cli/cli.js start", "run:packager": "./node_modules/react-native/packager/packager.sh", From fe389e53703241e62f87138d6f5fe5f7eb7ee484 Mon Sep 17 00:00:00 2001 From: "Tim O. Peters" Date: Fri, 15 Dec 2017 11:56:48 +0100 Subject: [PATCH 0366/1148] Update for Animated.Region #24 Fix on the AnimatedMarkers Example (#1889) * Update for #24 Fix Fix for 'Animated.Region undefined constructor' in recent react-native version. Solved by using MapView.AnimatedRegion instead of Animated.Region * Change Animated.Region #24 on AnimatedMarkers Example Fix for 'Animated.Region undefined constructor' in recent react-native version. Solved by using MapView.AnimatedRegion instead of Animated.Region --- example/examples/AnimatedMarkers.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/example/examples/AnimatedMarkers.js b/example/examples/AnimatedMarkers.js index 8c5150e6f..2c8337e72 100644 --- a/example/examples/AnimatedMarkers.js +++ b/example/examples/AnimatedMarkers.js @@ -5,7 +5,6 @@ import { Text, Dimensions, TouchableOpacity, - Animated, } from 'react-native'; import MapView from 'react-native-maps'; @@ -23,7 +22,7 @@ class AnimatedMarkers extends React.Component { super(props); this.state = { - coordinate: new Animated.Region({ + coordinate: new MapView.AnimatedRegion({ latitude: LATITUDE, longitude: LONGITUDE, }), From 37b61be2fc6916956bc5e6271fb1ceb06a92c069 Mon Sep 17 00:00:00 2001 From: MartinCamen Date: Fri, 15 Dec 2017 15:18:20 +0100 Subject: [PATCH 0367/1148] Update installation.md (#1892) Add missing word (`use`) --- docs/installation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/installation.md b/docs/installation.md index 2250aefd9..c1e4ebc02 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -66,7 +66,7 @@ end ~~~ -## If you want to Google maps +## If you want to use Google maps Add to `ios/_YOUR_PROJECT_NAME_/AppDelegate.m: From c51b0822f5f481d7b32141e37c026280bf882916 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaroslav=20Kub=C3=AD=C4=8Dek?= Date: Fri, 15 Dec 2017 15:39:21 +0100 Subject: [PATCH 0368/1148] Fix example with animated markers (#1840) - AnimatedRegion is property of MapView - make sure animate method is executed in correct context --- example/examples/AnimatedMarkers.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/example/examples/AnimatedMarkers.js b/example/examples/AnimatedMarkers.js index 2c8337e72..31cfafac4 100644 --- a/example/examples/AnimatedMarkers.js +++ b/example/examples/AnimatedMarkers.js @@ -56,7 +56,7 @@ class AnimatedMarkers extends React.Component { this.animate()} style={[styles.bubble, styles.button]} > Animate From fff00efd622149752820b2c0df4161c455573386 Mon Sep 17 00:00:00 2001 From: Hein Rutjes Date: Fri, 15 Dec 2017 17:40:24 +0100 Subject: [PATCH 0369/1148] Fixed onMapReady no longer getting called on iOS (#1853) --- lib/ios/AirMaps/AIRMapManager.m | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/lib/ios/AirMaps/AIRMapManager.m b/lib/ios/AirMaps/AIRMapManager.m index 94283963a..faee9c357 100644 --- a/lib/ios/AirMaps/AIRMapManager.m +++ b/lib/ios/AirMaps/AIRMapManager.m @@ -37,9 +37,6 @@ @interface AIRMapManager() @end @implementation AIRMapManager -{ - BOOL didCallOnMapReady; -} RCT_EXPORT_MODULE() @@ -714,13 +711,10 @@ - (void)mapView:(AIRMap *)mapView regionDidChangeAnimated:(__unused BOOL)animate - (void)mapViewWillStartRenderingMap:(AIRMap *)mapView { - if (!didCallOnMapReady) - { - didCallOnMapReady = YES; - mapView.onMapReady(@{}); + if (!mapView.hasStartedRendering) { + mapView.onMapReady(@{}); + mapView.hasStartedRendering = YES; } - - mapView.hasStartedRendering = YES; [mapView beginLoading]; [self _emitRegionChangeEvent:mapView continuous:NO]; } From dccc4849df1db7c19bea28cc940a0ac7a5d5e932 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85radsson?= Date: Mon, 18 Dec 2017 18:24:11 +0100 Subject: [PATCH 0370/1148] Corrected doc text for Polyline (#1899) The type for `lineJoin` was wrong, the default value was missing and the text for `lineJoin` and `lineCap` did not explain the possible values. --- docs/polyline.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/polyline.md b/docs/polyline.md index 89ef9de25..5a2b1f38b 100644 --- a/docs/polyline.md +++ b/docs/polyline.md @@ -7,8 +7,8 @@ | `coordinates` | `Array` | (Required) | An array of coordinates to describe the polyline | `strokeWidth` | `Number` | `1` | The stroke width to use for the path. | `strokeColor` | `String` | `#000` | The stroke color to use for the path. -| `lineCap` | `String` | `round` | The line cap style to apply to the open ends of the path. -| `lineJoin` | `Array` | | The line join style to apply to corners of the path. +| `lineCap` | `String` | `round` | The line cap style to apply to the open ends of the path. Possible values are `butt`, `round` or `square`. +| `lineJoin` | `String` | `round` | The line join style to apply to corners of the path. Possible values are `miter`, `round` or `bevel`. | `miterLimit` | `Number` | | The limiting value that helps avoid spikes at junctions between connected line segments. The miter limit helps you avoid spikes in paths that use the `miter` `lineJoin` style. If the ratio of the miter length—that is, the diagonal length of the miter join—to the line thickness exceeds the miter limit, the joint is converted to a bevel join. The default miter limit is 10, which results in the conversion of miters whose angle at the joint is less than 11 degrees. | `geodesic` | `Boolean` | | Boolean to indicate whether to draw each segment of the line as a geodesic as opposed to straight lines on the Mercator projection. A geodesic is the shortest path between two points on the Earth's surface. The geodesic curve is constructed assuming the Earth is a sphere. | `lineDashPhase` | `Number` | `0` | (iOS only) The offset (in points) at which to start drawing the dash pattern. Use this property to start drawing a dashed line partway through a segment or gap. For example, a phase value of 6 for the patter 5-2-3-2 would cause drawing to begin in the middle of the first gap. From 3a23f7e82a9654644ae24fd1a7ea03483b00b670 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85radsson?= Date: Mon, 18 Dec 2017 18:24:38 +0100 Subject: [PATCH 0371/1148] corrected default value to ``round`` (#1898) ``lineJoin`` and ``lineCap`` should have default value ``round``, according to docs. --- lib/components/MapPolyline.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/components/MapPolyline.js b/lib/components/MapPolyline.js index 2bdfe8d26..8ea9b4295 100644 --- a/lib/components/MapPolyline.js +++ b/lib/components/MapPolyline.js @@ -137,6 +137,8 @@ const propTypes = { const defaultProps = { strokeColor: '#000', strokeWidth: 1, + lineJoin: 'round', + lineCap: 'round', }; class MapPolyline extends React.Component { From 3f615fdbc1245fbebf2465089d4c162339ba736f Mon Sep 17 00:00:00 2001 From: satori-ytolstoguzov <31261230+satori-ytolstoguzov@users.noreply.github.com> Date: Thu, 21 Dec 2017 04:41:24 -0800 Subject: [PATCH 0372/1148] Fixed minor styling issues in installation guide (#1905) --- docs/installation.md | 63 +++++++++++++++++++++++++------------------- 1 file changed, 36 insertions(+), 27 deletions(-) diff --git a/docs/installation.md b/docs/installation.md index c1e4ebc02..048e01ef9 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -7,11 +7,11 @@ npm install react-native-maps --save ``` -## Get a map developer key +## Get a Google Maps API key Go to https://developers.google.com/maps/documentation/ios-sdk/get-api-key and get your key. -Without this key the map won't render anything. +Without this key the Google Maps map won't render anything. @@ -19,36 +19,42 @@ Without this key the map won't render anything. **!! DO NOT USE !!** `react-native link` +Have ran it already? Read [this](#on-ios). + ## iOS - CocoaPods -Setup your `Podfile` (found at `/ios/Podfile` as below, replace all references to `AirMapsExplorer` with your project name, and then run `pod install` while in the `ios` folder. +Setup your `Podfile` (found at `/ios/Podfile` as below, replace all references to `_YOUR_PROJECT_TARGET_` with your project target (it's the same as project name by default), and then run `pod install` while in the `ios` folder. + +Please make sure to use `.xcworkspace`, not `.xcproject` after that. ~~~ # Uncomment the next line to define a global platform for your project # platform :ios, '9.0' -target 'AirMapsExplorer' do +target '_YOUR_PROJECT_TARGET_' do rn_path = '../node_modules/react-native' - - pod 'yoga', path: "#{rn_path}/ReactCommon/yoga/yoga.podspec" - pod 'React', path: rn_path, subspecs: [ - 'Core', - 'RCTActionSheet', - 'RCTAnimation', - 'RCTGeolocation', - 'RCTImage', - 'RCTLinkingIOS', - 'RCTNetwork', - 'RCTSettings', - 'RCTText', - 'RCTVibration', - 'RCTWebSocket', - 'BatchedBridge' - ] - - pod 'GoogleMaps' # Remove this line if you don't want to support GoogleMaps on iOS - pod 'react-native-maps', path: '../node_modules/react-native-maps' - pod 'react-native-google-maps', path: '../node_modules/react-native-maps' # Remove this line if you don't want to support GoogleMaps on iOS + rn_maps_path = '../node_modules/react-native-maps' + + pod 'yoga', path: "#{rn_path}/ReactCommon/yoga/yoga.podspec" + pod 'React', path: rn_path, subspecs: [ + 'Core', + 'RCTActionSheet', + 'RCTAnimation', + 'RCTGeolocation', + 'RCTImage', + 'RCTLinkingIOS', + 'RCTNetwork', + 'RCTSettings', + 'RCTText', + 'RCTVibration', + 'RCTWebSocket', + 'BatchedBridge' + ] + + pod 'react-native-maps', path: rn_maps_path + + pod 'GoogleMaps' # Remove this line if you don't want to support Google Maps on iOS + pod 'react-native-google-maps', path: rn_maps_path # Remove this line if you don't want to support Google Maps on iOS end post_install do |installer| @@ -71,14 +77,15 @@ end Add to `ios/_YOUR_PROJECT_NAME_/AppDelegate.m: ``` -+ @import GoogleMaps; //add this line if you want to use GoogleMaps ++ @import GoogleMaps; //add this line if you want to use Google Maps + @implementation AppDelegate ... - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { - -+ [GMSServices provideAPIKey:@"_YOUR_API_KEY"]; // add this line using the api key obtained from Google Console ++ [GMSServices provideAPIKey:@"_YOUR_API_KEY_"]; // add this line using the api key obtained from Google Console +... ``` @@ -170,6 +177,8 @@ If you have ran 'react-native link` by mistake: 6. delete ios/build folder 7. start again with the installation steps +If you use Xcode with version less than 9 you may get `use of undeclared identifier 'MKMapTypeMutedStandard'` error. In this case you have to update your Xcode. + ### On Android: 1. Be sure to have `new MapsPackage()` in your `MainApplication.java` : From 7a394982f0a7769f57d2bd485f5a4833d307f0e7 Mon Sep 17 00:00:00 2001 From: "Tim O. Peters" Date: Thu, 21 Dec 2017 16:10:34 +0100 Subject: [PATCH 0373/1148] Manage Zoom Controls visibility on the map (#1906) * Manage Zoom Controls visibility on the map * Manage Zoom Controls visibility on the map * Manage Zoom Controls visibility on the map * Manage Zoom Controls visibility on the map * Manage Zoom Controls visibility on the map * Manage Zoom Controls visibility on the map * Manage Zoom Controls visibility on the map * Manage Zoom Controls not available on iOS SDK --- docs/mapview.md | 1 + index.d.ts | 1 + .../java/com/airbnb/android/react/maps/AirMapManager.java | 5 +++++ lib/components/MapView.js | 8 ++++++++ 4 files changed, 15 insertions(+) diff --git a/docs/mapview.md b/docs/mapview.md index 6d3227b4a..b2c021414 100644 --- a/docs/mapview.md +++ b/docs/mapview.md @@ -22,6 +22,7 @@ | `showsIndoors` | `Boolean` | `true` | A Boolean indicating whether indoor maps should be enabled. | `showsIndoorLevelPicker` | `Boolean` | `false` | A Boolean indicating whether indoor level picker should be enabled. **Note:** Google Maps only (either Android or iOS with `PROVIDER_GOOGLE`). | `zoomEnabled` | `Boolean` | `true` | If `false` the user won't be able to pinch/zoom the map. +| `zoomControlEnabled` | `Boolean` | `true` | If `false` the zoom control at the bottom right of the map won't be visible **Note:** Android only. | `minZoomLevel` | `Number` | `0` | Minimum zoom value for the map, must be between 0 and 20 | `maxZoomLevel` | `Number` | `20` | Maximum zoom value for the map, must be between 0 and 20 | `rotateEnabled` | `Boolean` | `true` | If `false` the user won't be able to pinch/rotate the map. diff --git a/index.d.ts b/index.d.ts index 91efce2e8..28574faa6 100644 --- a/index.d.ts +++ b/index.d.ts @@ -12,6 +12,7 @@ interface MapViewProps { showsPointsOfInterest?: boolean; showsCompass?: boolean; zoomEnabled?: boolean; + zoomControlEnabled?: boolean; rotateEnabled?: boolean; cacheEnabled?: boolean; loadingEnabled?: boolean; diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java index 03e4597bb..0770d48a7 100644 --- a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java @@ -181,6 +181,11 @@ public void setZoomEnabled(AirMapView view, boolean zoomEnabled) { view.map.getUiSettings().setZoomGesturesEnabled(zoomEnabled); } + @ReactProp(name = "zoomControlEnabled", defaultBoolean = true) + public void setZoomControlEnabled(AirMapView view, boolean zoomControlEnabled) { + view.map.getUiSettings().setZoomControlsEnabled(zoomControlEnabled); + } + @ReactProp(name = "rotateEnabled", defaultBoolean = false) public void setRotateEnabled(AirMapView view, boolean rotateEnabled) { view.map.getUiSettings().setRotateGesturesEnabled(rotateEnabled); diff --git a/lib/components/MapView.js b/lib/components/MapView.js index c476696b7..8c3ccadbe 100644 --- a/lib/components/MapView.js +++ b/lib/components/MapView.js @@ -142,6 +142,14 @@ const propTypes = { zoomEnabled: PropTypes.bool, /** + *If `false` the user won't be able to zoom the map + * Default value is `true`. + * + *@platform android + */ + zoomControlEnabled: PropTypes.bool, + + /** * If `false` the user won't be able to pinch/rotate the map. * Default value is `true`. * From e0fbac8d63081646357a6dbaf78f32c8cadeeeb3 Mon Sep 17 00:00:00 2001 From: Yuriy Tolstoguzov Date: Thu, 21 Dec 2017 13:38:37 -0800 Subject: [PATCH 0374/1148] Updated installation guide with Xcode 8 possible error --- docs/installation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/installation.md b/docs/installation.md index 048e01ef9..9af69f623 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -177,7 +177,7 @@ If you have ran 'react-native link` by mistake: 6. delete ios/build folder 7. start again with the installation steps -If you use Xcode with version less than 9 you may get `use of undeclared identifier 'MKMapTypeMutedStandard'` error. In this case you have to update your Xcode. +If you use Xcode with version less than 9 you may get `use of undeclared identifier 'MKMapTypeMutedStandard'` or `Entry, ":CFBundleIdentifier", Does Not Exist` errors. In this case you have to update your Xcode. ### On Android: From 9ebde73ff107d248a7c88fac21351a04c69e605a Mon Sep 17 00:00:00 2001 From: youpin Date: Fri, 22 Dec 2017 01:14:25 +0300 Subject: [PATCH 0375/1148] change name of project (#1910) --- example/android/app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/example/android/app/build.gradle b/example/android/app/build.gradle index d2b475051..3dd571052 100644 --- a/example/android/app/build.gradle +++ b/example/android/app/build.gradle @@ -130,5 +130,5 @@ dependencies { compile 'com.facebook.react:react-native:0.51.+' compile 'com.android.support:appcompat-v7:25.3.0' compile 'com.android.support:support-annotations:25.3.0' - compile project(':react-native-maps-lib') + compile project(':react-native-maps') } From 8b28c64226e6bf5f1fe2940a1d9544da02871184 Mon Sep 17 00:00:00 2001 From: Dan Tamas Date: Fri, 22 Dec 2017 17:44:42 +0100 Subject: [PATCH 0376/1148] Update issues template with no_template warning (#1917) It seems that some people still don't use the template, so moved the warning on top and made it a little more aggressive :) --- .github/ISSUE_TEMPLATE.md | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index 9cc3d0cdb..2d56161cc 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -1,5 +1,22 @@ ### Is this a bug report? @@ -92,18 +109,3 @@ (Paste the link to an example project and exact instructions to reproduce the issue.) - From fef05cdec5d82721050aeba2359b355af544d1d6 Mon Sep 17 00:00:00 2001 From: Hein Rutjes Date: Sat, 23 Dec 2017 14:05:13 +0100 Subject: [PATCH 0377/1148] Add gradient/multi-color polyline support for iOS (MapKit) (#1911) * Add multi/gradient polyline support for iOS (MapKit) * Fixed MapExplorer not building with RN51 * Renamed color/color2 to startColor & endColor for new Polyline renderer * Fixed gradient line sometimes not visible on certain zoom resolutions --- README.md | 8 + docs/polyline.md | 32 +++ example/App.js | 2 + example/examples/GradientPolylines.js | 77 ++++++ .../AirMapsExplorer.xcodeproj/project.pbxproj | 2 +- lib/components/MapPolyline.js | 5 + lib/ios/AirMaps.xcodeproj/project.pbxproj | 6 + lib/ios/AirMaps/AIRMapPolyline.h | 3 +- lib/ios/AirMaps/AIRMapPolyline.m | 89 +++---- lib/ios/AirMaps/AIRMapPolylineManager.m | 1 + lib/ios/AirMaps/AIRMapPolylineRenderer.h | 19 ++ lib/ios/AirMaps/AIRMapPolylineRenderer.m | 244 ++++++++++++++++++ 12 files changed, 442 insertions(+), 46 deletions(-) create mode 100644 example/examples/GradientPolylines.js create mode 100644 lib/ios/AirMaps/AIRMapPolylineRenderer.h create mode 100644 lib/ios/AirMaps/AIRMapPolylineRenderer.m diff --git a/README.md b/README.md index f0235f94a..76df69603 100644 --- a/README.md +++ b/README.md @@ -316,6 +316,14 @@ So far, ``, ``, and `` are available to pass in +### Gradient Polylines (iOS MapKit only) + +Gradient polylines can be created using the `strokeColors` prop of the `` component. + +![](https://i.imgur.com/P7UeqAm.png?1) + + + ### Default Markers Default markers will be rendered unless a custom marker is specified. One can optionally adjust the diff --git a/docs/polyline.md b/docs/polyline.md index 5a2b1f38b..b00ecf0d9 100644 --- a/docs/polyline.md +++ b/docs/polyline.md @@ -7,6 +7,7 @@ | `coordinates` | `Array` | (Required) | An array of coordinates to describe the polyline | `strokeWidth` | `Number` | `1` | The stroke width to use for the path. | `strokeColor` | `String` | `#000` | The stroke color to use for the path. +| `strokeColors` | `Array` | `null` | The stroke colors to use for the path (iOS only). Must be the same length as `coordinates`. | `lineCap` | `String` | `round` | The line cap style to apply to the open ends of the path. Possible values are `butt`, `round` or `square`. | `lineJoin` | `String` | `round` | The line join style to apply to corners of the path. Possible values are `miter`, `round` or `bevel`. | `miterLimit` | `Number` | | The limiting value that helps avoid spikes at junctions between connected line segments. The miter limit helps you avoid spikes in paths that use the `miter` `lineJoin` style. If the ratio of the miter length—that is, the diagonal length of the miter join—to the line thickness exceeds the miter limit, the joint is converted to a bevel join. The default miter limit is 10, which results in the conversion of miters whose angle at the joint is less than 11 degrees. @@ -28,3 +29,34 @@ type LatLng { longitude: Number, } ``` + +## Gradient Polylines (iOS MapKit only) + +Gradient polylines can be created by using the `strokeColors` prop. `strokeColors` must be an array with the same number of elements as `coordinates`. + +Example: + +```js + + + +``` \ No newline at end of file diff --git a/example/App.js b/example/App.js index dadbea056..cddb5b7dc 100644 --- a/example/App.js +++ b/example/App.js @@ -16,6 +16,7 @@ import MarkerTypes from './examples/MarkerTypes'; import DraggableMarkers from './examples/DraggableMarkers'; import PolygonCreator from './examples/PolygonCreator'; import PolylineCreator from './examples/PolylineCreator'; +import GradientPolylines from './examples/GradientPolylines'; import AnimatedViews from './examples/AnimatedViews'; import AnimatedMarkers from './examples/AnimatedMarkers'; import Callouts from './examples/Callouts'; @@ -131,6 +132,7 @@ class App extends React.Component { [DraggableMarkers, 'Draggable Markers', true], [PolygonCreator, 'Polygon Creator', true], [PolylineCreator, 'Polyline Creator', true], + [GradientPolylines, 'Gradient Polylines', true], [AnimatedViews, 'Animating with MapViews'], [AnimatedMarkers, 'Animated Marker Position'], [Callouts, 'Custom Callouts', true], diff --git a/example/examples/GradientPolylines.js b/example/examples/GradientPolylines.js new file mode 100644 index 000000000..ca89ff2b0 --- /dev/null +++ b/example/examples/GradientPolylines.js @@ -0,0 +1,77 @@ +import React from 'react'; +import { + StyleSheet, + Dimensions, +} from 'react-native'; + +import MapView from 'react-native-maps'; + +const { width, height } = Dimensions.get('window'); + +const ASPECT_RATIO = width / height; +const LATITUDE = 37.78825; +const LONGITUDE = -122.4324; +const LATITUDE_DELTA = 0.0922; +const LONGITUDE_DELTA = LATITUDE_DELTA * ASPECT_RATIO; + +const COORDINATES = [ + { latitude: 37.8025259, longitude: -122.4351431 }, + { latitude: 37.7896386, longitude: -122.421646 }, + { latitude: 37.7665248, longitude: -122.4161628 }, + { latitude: 37.7734153, longitude: -122.4577787 }, + { latitude: 37.7948605, longitude: -122.4596065 }, + { latitude: 37.8025259, longitude: -122.4351431 }, +]; + +const COLORS = [ + '#7F0000', + '#00000000', // no color, creates a "long" gradient between the previous and next coordinate + '#B24112', + '#E5845C', + '#238C23', + '#7F0000', +]; + +class GradientPolylines extends React.Component { + constructor(props) { + super(props); + + this.state = { + region: { + latitude: LATITUDE, + longitude: LONGITUDE, + latitudeDelta: LATITUDE_DELTA, + longitudeDelta: LONGITUDE_DELTA, + }, + }; + } + + render() { + return ( + + + + ); + } +} + +GradientPolylines.propTypes = { + provider: MapView.ProviderPropType, +}; + +const styles = StyleSheet.create({ + container: { + ...StyleSheet.absoluteFillObject, + }, +}); + +module.exports = GradientPolylines; diff --git a/example/ios/AirMapsExplorer.xcodeproj/project.pbxproj b/example/ios/AirMapsExplorer.xcodeproj/project.pbxproj index dc9fb85bd..f91f8c470 100644 --- a/example/ios/AirMapsExplorer.xcodeproj/project.pbxproj +++ b/example/ios/AirMapsExplorer.xcodeproj/project.pbxproj @@ -266,7 +266,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "../../node_modules/react-native/packager/react-native-xcode.sh"; + shellScript = "../../node_modules/react-native/scripts/react-native-xcode.sh"; }; 17E7BB4CEC38ABB7449E144E /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; diff --git a/lib/components/MapPolyline.js b/lib/components/MapPolyline.js index 8ea9b4295..bba6c932b 100644 --- a/lib/components/MapPolyline.js +++ b/lib/components/MapPolyline.js @@ -51,6 +51,11 @@ const propTypes = { */ strokeColor: PropTypes.string, + /** + * The stroke colors to use for the path. + */ + strokeColors: PropTypes.arrayOf(PropTypes.string), + /** * The order in which this tile overlay is drawn with respect to other overlays. An overlay * with a larger z-index is drawn over overlays with smaller z-indices. The order of overlays diff --git a/lib/ios/AirMaps.xcodeproj/project.pbxproj b/lib/ios/AirMaps.xcodeproj/project.pbxproj index 4c959ad9f..09d16bc36 100644 --- a/lib/ios/AirMaps.xcodeproj/project.pbxproj +++ b/lib/ios/AirMaps.xcodeproj/project.pbxproj @@ -22,6 +22,7 @@ 1125B2E61C4AD3DA007D0023 /* AIRMapPolylineManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 1125B2D61C4AD3DA007D0023 /* AIRMapPolylineManager.m */; }; 1125B2F21C4AD445007D0023 /* SMCalloutView.m in Sources */ = {isa = PBXBuildFile; fileRef = 1125B2F11C4AD445007D0023 /* SMCalloutView.m */; }; 19DABC7F1E7C9D3C00F41150 /* RCTConvert+AirMap.m in Sources */ = {isa = PBXBuildFile; fileRef = 19DABC7E1E7C9D3C00F41150 /* RCTConvert+AirMap.m */; }; + 2163AA501FEAEDD100BBEC95 /* AIRMapPolylineRenderer.m in Sources */ = {isa = PBXBuildFile; fileRef = 2163AA4F1FEAEDD100BBEC95 /* AIRMapPolylineRenderer.m */; }; 628F81201FD16DF80058313A /* AIRMapLocalTile.m in Sources */ = {isa = PBXBuildFile; fileRef = 628F811F1FD16DF80058313A /* AIRMapLocalTile.m */; }; 628F81231FD16EFA0058313A /* AIRMapLocalTileManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 628F81221FD16EFA0058313A /* AIRMapLocalTileManager.m */; }; 62AEC4D41FD5A0AA003225E0 /* AIRMapLocalTileOverlay.m in Sources */ = {isa = PBXBuildFile; fileRef = 62AEC4D31FD5A0AA003225E0 /* AIRMapLocalTileOverlay.m */; }; @@ -73,6 +74,8 @@ 11FA5C511C4A1296003AC2EE /* libAirMaps.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libAirMaps.a; sourceTree = BUILT_PRODUCTS_DIR; }; 19DABC7D1E7C9D3C00F41150 /* RCTConvert+AirMap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "RCTConvert+AirMap.h"; sourceTree = ""; }; 19DABC7E1E7C9D3C00F41150 /* RCTConvert+AirMap.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "RCTConvert+AirMap.m"; sourceTree = ""; }; + 2163AA4E1FEAEDD100BBEC95 /* AIRMapPolylineRenderer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRMapPolylineRenderer.h; sourceTree = ""; }; + 2163AA4F1FEAEDD100BBEC95 /* AIRMapPolylineRenderer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRMapPolylineRenderer.m; sourceTree = ""; }; 628F811E1FD16D780058313A /* AIRMapLocalTile.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AIRMapLocalTile.h; sourceTree = ""; }; 628F811F1FD16DF80058313A /* AIRMapLocalTile.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AIRMapLocalTile.m; sourceTree = ""; }; 628F81211FD16EAB0058313A /* AIRMapLocalTileManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AIRMapLocalTileManager.h; sourceTree = ""; }; @@ -141,6 +144,8 @@ 1125B2D31C4AD3DA007D0023 /* AIRMapPolyline.h */, 1125B2D51C4AD3DA007D0023 /* AIRMapPolylineManager.h */, 1125B2D61C4AD3DA007D0023 /* AIRMapPolylineManager.m */, + 2163AA4E1FEAEDD100BBEC95 /* AIRMapPolylineRenderer.h */, + 2163AA4F1FEAEDD100BBEC95 /* AIRMapPolylineRenderer.m */, 1125B2F01C4AD445007D0023 /* SMCalloutView.h */, 1125B2F11C4AD445007D0023 /* SMCalloutView.m */, 19DABC7D1E7C9D3C00F41150 /* RCTConvert+AirMap.h */, @@ -227,6 +232,7 @@ 1125B2DA1C4AD3DA007D0023 /* AIRMap.m in Sources */, 1125B2DF1C4AD3DA007D0023 /* AIRMapCoordinate.m in Sources */, 1125B2F21C4AD445007D0023 /* SMCalloutView.m in Sources */, + 2163AA501FEAEDD100BBEC95 /* AIRMapPolylineRenderer.m in Sources */, 1125B2E11C4AD3DA007D0023 /* AIRMapMarker.m in Sources */, 1125B2E21C4AD3DA007D0023 /* AIRMapMarkerManager.m in Sources */, DA6C26381C9E2AFE0035349F /* AIRMapUrlTile.m in Sources */, diff --git a/lib/ios/AirMaps/AIRMapPolyline.h b/lib/ios/AirMaps/AIRMapPolyline.h index 6311c3248..d34a1dd6c 100644 --- a/lib/ios/AirMaps/AIRMapPolyline.h +++ b/lib/ios/AirMaps/AIRMapPolyline.h @@ -20,11 +20,12 @@ @property (nonatomic, weak) AIRMap *map; @property (nonatomic, strong) MKPolyline *polyline; -@property (nonatomic, strong) MKPolylineRenderer *renderer; +@property (nonatomic, strong) MKOverlayPathRenderer *renderer; @property (nonatomic, strong) NSArray *coordinates; @property (nonatomic, strong) UIColor *fillColor; @property (nonatomic, strong) UIColor *strokeColor; +@property (nonatomic, strong) NSArray *strokeColors; @property (nonatomic, assign) CGFloat strokeWidth; @property (nonatomic, assign) CGFloat miterLimit; @property (nonatomic, assign) CGLineCap lineCap; diff --git a/lib/ios/AirMaps/AIRMapPolyline.m b/lib/ios/AirMaps/AIRMapPolyline.m index 8e07a63b3..b230ec7ef 100644 --- a/lib/ios/AirMaps/AIRMapPolyline.m +++ b/lib/ios/AirMaps/AIRMapPolyline.m @@ -4,11 +4,12 @@ // #import "AIRMapPolyline.h" +#import "AIRMapPolylineRenderer.h" #import @implementation AIRMapPolyline { - + } - (void)setFillColor:(UIColor *)fillColor { @@ -21,6 +22,14 @@ - (void)setStrokeColor:(UIColor *)strokeColor { [self update]; } +- (void)setStrokeColors:(NSArray *)strokeColors { + _strokeColors = strokeColors; + if ((self.renderer != nil) && ![_renderer isKindOfClass:[AIRMapPolylineRenderer class]]) { + self.renderer = [self createRenderer]; + } + [self update]; +} + - (void)setStrokeWidth:(CGFloat)strokeWidth { _strokeWidth = strokeWidth; [self update]; @@ -59,27 +68,48 @@ - (void)setCoordinates:(NSArray *)coordinates { coords[i] = coordinates[i].coordinate; } self.polyline = [MKPolyline polylineWithCoordinates:coords count:coordinates.count]; - self.renderer = [[MKPolylineRenderer alloc] initWithPolyline:self.polyline]; + self.renderer = [self createRenderer]; [self update]; } +- (MKOverlayPathRenderer*)createRenderer { + if (self.polyline == nil) return nil; + if (self.strokeColors == nil) { + // Use the default renderer when no array of stroke-colors is defined. + // This behaviour may be changed in the future if we permanently want to + // use the custom renderer, because it can add funtionality that is not + // supported by the default renderer. + return [[MKPolylineRenderer alloc] initWithPolyline:self.polyline]; + } + else { + return [[AIRMapPolylineRenderer alloc] initWithOverlay:self polyline:self.polyline]; + } +} + - (void) update { if (!_renderer) return; - _renderer.fillColor = _fillColor; - _renderer.strokeColor = _strokeColor; - _renderer.lineWidth = _strokeWidth; - _renderer.lineCap = _lineCap; - _renderer.lineJoin = _lineJoin; - _renderer.miterLimit = _miterLimit; - _renderer.lineDashPhase = _lineDashPhase; - _renderer.lineDashPattern = _lineDashPattern; - + [self updateRenderer:_renderer]; + if (_map == nil) return; [_map removeOverlay:self]; [_map addOverlay:self]; } +- (void) updateRenderer:(MKOverlayPathRenderer*)renderer { + renderer.fillColor = _fillColor; + renderer.strokeColor = _strokeColor; + renderer.lineWidth = _strokeWidth; + renderer.lineCap = _lineCap; + renderer.lineJoin = _lineJoin; + renderer.miterLimit = _miterLimit; + renderer.lineDashPhase = _lineDashPhase; + renderer.lineDashPattern = _lineDashPattern; + + if ([renderer isKindOfClass:[AIRMapPolylineRenderer class]]) { + ((AIRMapPolylineRenderer*)renderer).strokeColors = _strokeColors; + } +} #pragma mark MKOverlay implementation @@ -109,38 +139,9 @@ - (BOOL)canReplaceMapContent - (void) drawToSnapshot:(MKMapSnapshot *) snapshot context:(CGContextRef) context { - // Prepare context - CGContextSetStrokeColorWithColor(context, self.strokeColor.CGColor); - CGContextSetLineWidth(context, self.strokeWidth); - CGContextSetLineCap(context, self.lineCap); - CGContextSetLineJoin(context, self.lineJoin); - CGContextSetMiterLimit(context, self.miterLimit); - CGFloat dashes[self.lineDashPattern.count]; - for (NSUInteger i = 0; i < self.lineDashPattern.count; i++) { - dashes[i] = self.lineDashPattern[i].floatValue; - } - CGContextSetLineDash(context, self.lineDashPhase, dashes, self.lineDashPattern.count); - - // Begin path - CGContextBeginPath(context); - - // Get coordinates - CLLocationCoordinate2D coordinates[[self.polyline pointCount]]; - [self.polyline getCoordinates:coordinates range:NSMakeRange(0, [self.polyline pointCount])]; - - // Draw line segments - for(int i = 0; i < [self.polyline pointCount]; i++) { - CGPoint point = [snapshot pointForCoordinate:coordinates[i]]; - if (i == 0) { - CGContextMoveToPoint(context,point.x, point.y); - } - else{ - CGContextAddLineToPoint(context,point.x, point.y); - } - } - - // Finish path - CGContextStrokePath(context); + AIRMapPolylineRenderer* renderer = [[AIRMapPolylineRenderer alloc] initWithSnapshot:snapshot overlay:self polyline:self.polyline]; + [self updateRenderer:renderer]; + [renderer drawWithZoomScale:2 inContext:context]; } -@end \ No newline at end of file +@end diff --git a/lib/ios/AirMaps/AIRMapPolylineManager.m b/lib/ios/AirMaps/AIRMapPolylineManager.m index e064b7c4b..fb807fd94 100644 --- a/lib/ios/AirMaps/AIRMapPolylineManager.m +++ b/lib/ios/AirMaps/AIRMapPolylineManager.m @@ -35,6 +35,7 @@ - (UIView *)view RCT_EXPORT_VIEW_PROPERTY(coordinates, AIRMapCoordinateArray) RCT_EXPORT_VIEW_PROPERTY(strokeColor, UIColor) +RCT_EXPORT_VIEW_PROPERTY(strokeColors, UIColorArray) RCT_EXPORT_VIEW_PROPERTY(strokeWidth, CGFloat) RCT_EXPORT_VIEW_PROPERTY(lineCap, CGLineCap) RCT_EXPORT_VIEW_PROPERTY(lineJoin, CGLineJoin) diff --git a/lib/ios/AirMaps/AIRMapPolylineRenderer.h b/lib/ios/AirMaps/AIRMapPolylineRenderer.h new file mode 100644 index 000000000..f4684c6f4 --- /dev/null +++ b/lib/ios/AirMaps/AIRMapPolylineRenderer.h @@ -0,0 +1,19 @@ +// +// AIRMapPolylineRenderer.h +// mapDemo +// +// Created by IjzerenHein on 13-11-21. +// Copyright (c) 2017 IjzerenHein. All rights reserved. +// + +#import + +@interface AIRMapPolylineRenderer : MKOverlayPathRenderer + +-(id)initWithOverlay:(id)overlay polyline:(MKPolyline*)polyline; +-(id)initWithSnapshot:(MKMapSnapshot*)snapshot overlay:(id)overlay polyline:(MKPolyline*)polyline; +-(void)drawWithZoomScale:(MKZoomScale)zoomScale inContext:(CGContextRef)context; + +@property (nonatomic, strong) NSArray *strokeColors; + +@end diff --git a/lib/ios/AirMaps/AIRMapPolylineRenderer.m b/lib/ios/AirMaps/AIRMapPolylineRenderer.m new file mode 100644 index 000000000..5ac024f97 --- /dev/null +++ b/lib/ios/AirMaps/AIRMapPolylineRenderer.m @@ -0,0 +1,244 @@ +// +// AIRMapPolylineRenderer.h +// mapDemo +// +// Created by IjzerenHein on 13-11-21. +// Copyright (c) 2017 IjzerenHein. All rights reserved. +// + +#import "AIRMapPolylineRenderer.h" + +@interface AIRMapPolylineRendererSegment : NSObject +- (id)initWithPoint:(CGPoint)point color:(UIColor*)color; +- (void) addPoint:(CGPoint)point color:(UIColor*)color; +@property CGMutablePathRef path; +@property UIColor *startColor; +@property UIColor *endColor; +@property CGPoint startPoint; +@property CGPoint endPoint; +@end +@implementation AIRMapPolylineRendererSegment +- (id)initWithPoint:(CGPoint)point color:(UIColor*)color +{ + self = [super init]; + if (self){ + self.path = CGPathCreateMutable(); + self.startColor = color; + self.startPoint = point; + self.endPoint = point; + CGPathMoveToPoint(self.path, nil, point.x, point.y); + } + return self; +} +- (void) addPoint:(CGPoint)point color:(UIColor*)color +{ + self.endPoint = point; + self.endColor = color; + CGPathAddLineToPoint(self.path, nil, point.x, point.y); +} +@end + +@implementation AIRMapPolylineRenderer { + NSMutableArray* _segments; + MKPolyline* _polyline; + NSArray *_strokeColors; + MKMapSnapshot* _snapshot; + CLLocationCoordinate2D* _coordinates; +} + +@synthesize strokeColors; + +- (id)initWithOverlay:(id)overlay polyline:(MKPolyline*)polyline +{ + self = [super initWithOverlay:overlay]; + if (self){ + _polyline = polyline; + [self createPath]; + } + return self; +} + +- (id)initWithSnapshot:(MKMapSnapshot*)snapshot overlay:(id)overlay polyline:(MKPolyline*)polyline +{ + self = [super initWithOverlay:overlay]; + if (self){ + _snapshot = snapshot; + _polyline = polyline; + _coordinates = malloc(sizeof(CLLocationCoordinate2D) * [_polyline pointCount]); + [_polyline getCoordinates:_coordinates range:NSMakeRange(0, [_polyline pointCount])]; + } + return self; +} + +- (void) dealloc +{ + if (_coordinates) free(_coordinates); +} + +- (CGPoint) pointForIndex:(NSUInteger)index +{ + if (_snapshot != nil) { + return [_snapshot pointForCoordinate:_coordinates[index]]; + } + else { + return [self pointForMapPoint:_polyline.points[index]]; + } +} + +- (UIColor*) colorForIndex:(NSUInteger)index +{ + if ((_strokeColors == nil) || !_strokeColors.count) return self.strokeColor; + index = MIN(index, _strokeColors.count - 1); + UIColor* color = _strokeColors[index]; + CGFloat pc_r,pc_g,pc_b,pc_a; + [color getRed:&pc_r green:&pc_g blue:&pc_b alpha:&pc_a]; + return (pc_a == 0) ? nil : color; +} + +- (void) createPath +{ + CGMutablePathRef path = CGPathCreateMutable(); + BOOL first = YES; + for (NSUInteger i = 0, n = _polyline.pointCount; i < n; i++){ + CGPoint point = [self pointForIndex:i]; + if (first) { + CGPathMoveToPoint(path, nil, point.x, point.y); + first = NO; + } else { + CGPathAddLineToPoint(path, nil, point.x, point.y); + } + } + self.path = path; +} + +- (void) createSegments +{ + _segments = [NSMutableArray new]; + if (_polyline.pointCount <= 1) return; + AIRMapPolylineRendererSegment* segment = nil; + for (NSUInteger i = 0, n = _polyline.pointCount; i < n; i++){ + CGPoint point = [self pointForIndex:i]; + UIColor* color = [self colorForIndex:i]; + if (segment == nil) { + + // Start new segment + segment = [[AIRMapPolylineRendererSegment alloc] initWithPoint:point color:color]; + [_segments addObject:segment]; + } + else if (((color == nil) && (segment.endColor == nil)) || + ((color != nil) && [segment.startColor isEqual:color])) { + + // Append point to segment + [segment addPoint:point color: color]; + } + else { + + // Close the last segment if needed + if (segment.endColor == nil) { + [segment addPoint:point color:color]; + } + else { + + // Add transition gradient + segment = [[AIRMapPolylineRendererSegment alloc] initWithPoint:segment.endPoint color:segment.endColor]; + [segment addPoint:point color:color]; + [_segments addObject:segment]; + } + + // Start new segment + if (i < (n - 1)) { + segment = [[AIRMapPolylineRendererSegment alloc] initWithPoint:point color:color]; + [_segments addObject:segment]; + } + } + } + + // Close last segment in case this was forgotten + if ((segment != nil) && (segment.endColor == nil)) { + segment.endColor = segment.startColor; + } +} + +- (void) setStrokeColors:(NSArray *)strokeColors +{ + if (_strokeColors != strokeColors) { + _strokeColors = strokeColors; + _segments = nil; + } +} + +- (void) setStrokeColor:(UIColor *)strokeColor +{ + if (super.strokeColor != strokeColor) { + super.strokeColor = strokeColor; + _segments = nil; + } +} + +- (void) drawMapRect:(MKMapRect)mapRect zoomScale:(MKZoomScale)zoomScale inContext:(CGContextRef)context +{ + CGRect pointsRect = CGPathGetBoundingBox(self.path); + CGRect mapRectCG = [self rectForMapRect:mapRect]; + if (!CGRectIntersectsRect(pointsRect, mapRectCG)) return; + + [self drawWithZoomScale:zoomScale inContext:context]; +} + +- (void) drawWithZoomScale:(MKZoomScale)zoomScale inContext:(CGContextRef)context +{ + CGFloat lineWidth = (self.lineWidth / zoomScale) * 2.0; + CGContextSetLineWidth(context, lineWidth); + CGContextSetLineCap(context, self.lineCap); + CGContextSetLineJoin(context, self.lineJoin); + CGContextSetFillColorWithColor(context, self.fillColor.CGColor); + CGContextSetMiterLimit(context, self.miterLimit); + CGFloat dashes[self.lineDashPattern.count]; + for (NSUInteger i = 0; i < self.lineDashPattern.count; i++) { + dashes[i] = self.lineDashPattern[i].floatValue; + } + CGContextSetLineDash(context, self.lineDashPhase, dashes, self.lineDashPattern.count); + + if (_segments == nil) { + [self createSegments]; + } + + for (NSUInteger i = 0, n = _segments.count; i < n; i++) { + AIRMapPolylineRendererSegment* segment = _segments[i]; + + CGContextBeginPath(context); + CGContextAddPath(context, segment.path); + + // When segment has two colors, draw it as a gradient + if (![segment.startColor isEqual:segment.endColor]) { + CGFloat pc_r,pc_g,pc_b,pc_a, + cc_r,cc_g,cc_b,cc_a; + [segment.startColor getRed:&pc_r green:&pc_g blue:&pc_b alpha:&pc_a]; + [segment.endColor getRed:&cc_r green:&cc_g blue:&cc_b alpha:&cc_a]; + CGFloat gradientColors[8] = {pc_r,pc_g,pc_b,pc_a, + cc_r,cc_g,cc_b,cc_a}; + CGFloat gradientLocation[2] = {0,1}; + CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); + CGGradientRef gradient = CGGradientCreateWithColorComponents(colorSpace, gradientColors, gradientLocation, 2); + CGColorSpaceRelease(colorSpace); + + CGContextReplacePathWithStrokedPath(context); + CGContextClip(context); + CGContextDrawLinearGradient( + context, + gradient, + segment.startPoint, + segment.endPoint, + kCGGradientDrawsBeforeStartLocation | kCGGradientDrawsAfterEndLocation + ); + CGGradientRelease(gradient); + CGContextResetClip(context); + } + else { + CGContextSetStrokeColorWithColor(context, segment.startColor.CGColor); + CGContextStrokePath(context); + } + } +} + +@end + From 16a7fe69935a0cc4057abc0e728ce8f73284c20f Mon Sep 17 00:00:00 2001 From: Ivan Pusic Date: Sat, 23 Dec 2017 23:34:05 +0100 Subject: [PATCH 0378/1148] default export is MapView (#1904) With old ts file based on namespaces there was no default export, and therefore `import MapView from 'react-native-maps';` was not valid. I removed namespace, introduced module and exported all members. --- index.d.ts | 151 ++++++++++++++++++++++++++--------------------------- 1 file changed, 74 insertions(+), 77 deletions(-) diff --git a/index.d.ts b/index.d.ts index 28574faa6..01627932c 100644 --- a/index.d.ts +++ b/index.d.ts @@ -1,69 +1,68 @@ -import * as React from 'react'; +declare module "react-native-maps" { + import * as React from 'react'; -interface MapViewProps { - provider?: 'google'; - style: any; - customMapStyle?: any[]; - customMapStyleString?: string; - showsUserLocation?: boolean; - userLocationAnnotationTitle?: string; - showsMyLocationButton?: boolean; - followsUserLocation?: boolean; - showsPointsOfInterest?: boolean; - showsCompass?: boolean; - zoomEnabled?: boolean; - zoomControlEnabled?: boolean; - rotateEnabled?: boolean; - cacheEnabled?: boolean; - loadingEnabled?: boolean; - loadingBackgroundColor?: any; - loadingIndicatorColor?: any; - scrollEnabled?: boolean; - pitchEnabled?: boolean; - toolbarEnabled?: boolean; - moveOnMarkerPress?: boolean; - showsScale?: boolean; - showsBuildings?: boolean; - showsTraffic?: boolean; - showsIndoors?: boolean; - showsIndoorLevelPicker?: boolean; - mapType?: 'standard' | 'satellite' | 'hybrid' | 'terrain' | 'none' | 'mutedStandard'; - region?: { latitude: number; longitude: number; latitudeDelta: number; longitudeDelta: number; }; - initialRegion?: { latitude: number; longitude: number; latitudeDelta: number; longitudeDelta: number; }; - liteMode?: boolean; - maxDelta?: number; - minDelta?: number; - legalLabelInsets?: any; - onChange?: Function; - onMapReady?: Function; - onRegionChange?: Function; - onRegionChangeComplete?: Function; - onPress?: Function; - onLayout?: Function; - onLongPress?: Function; - onPanDrag?: Function; - onMarkerPress?: Function; - onMarkerSelect?: Function; - onMarkerDeselect?: Function; - onCalloutPress?: Function; - onMarkerDragStart?: Function; - onMarkerDrag?: Function; - onMarkerDragEnd?: Function; - minZoomLevel?: number; - maxZoomLevel?: number; -} - -declare class MapView extends React.Component { - static Animated: any; - static AnimatedRegion: any; -} + export interface MapViewProps { + provider?: 'google'; + style: any; + customMapStyle?: any[]; + customMapStyleString?: string; + showsUserLocation?: boolean; + userLocationAnnotationTitle?: string; + showsMyLocationButton?: boolean; + followsUserLocation?: boolean; + showsPointsOfInterest?: boolean; + showsCompass?: boolean; + zoomEnabled?: boolean; + zoomControlEnabled?: boolean; + rotateEnabled?: boolean; + cacheEnabled?: boolean; + loadingEnabled?: boolean; + loadingBackgroundColor?: any; + loadingIndicatorColor?: any; + scrollEnabled?: boolean; + pitchEnabled?: boolean; + toolbarEnabled?: boolean; + moveOnMarkerPress?: boolean; + showsScale?: boolean; + showsBuildings?: boolean; + showsTraffic?: boolean; + showsIndoors?: boolean; + showsIndoorLevelPicker?: boolean; + mapType?: 'standard' | 'satellite' | 'hybrid' | 'terrain' | 'none' | 'mutedStandard'; + region?: { latitude: number; longitude: number; latitudeDelta: number; longitudeDelta: number; }; + initialRegion?: { latitude: number; longitude: number; latitudeDelta: number; longitudeDelta: number; }; + liteMode?: boolean; + maxDelta?: number; + minDelta?: number; + legalLabelInsets?: any; + onChange?: Function; + onMapReady?: Function; + onRegionChange?: Function; + onRegionChangeComplete?: Function; + onPress?: Function; + onLayout?: Function; + onLongPress?: Function; + onPanDrag?: Function; + onMarkerPress?: Function; + onMarkerSelect?: Function; + onMarkerDeselect?: Function; + onCalloutPress?: Function; + onMarkerDragStart?: Function; + onMarkerDrag?: Function; + onMarkerDragEnd?: Function; + minZoomLevel?: number; + maxZoomLevel?: number; + } -declare namespace MapView { + export default class MapView extends React.Component { + static Animated: any; + static AnimatedRegion: any; + } - type LineCapType = 'butt' | 'round' | 'square'; - type LineJoinType = 'miter' | 'round' | 'bevel'; + export type LineCapType = 'butt' | 'round' | 'square'; + export type LineJoinType = 'miter' | 'round' | 'bevel'; - interface MarkerProps { + export interface MarkerProps { identifier?: string; reuseIdentifier?: string; title?: string; @@ -89,7 +88,7 @@ declare namespace MapView { style?: any; } - interface MapPolylineProps { + export interface MapPolylineProps { coordinates?: { latitude: number; longitude: number; }[]; onPress?: Function; tappable?: boolean; @@ -105,7 +104,7 @@ declare namespace MapView { lineDashPattern?: number[]; } - interface MapPolygonProps { + export interface MapPolygonProps { coordinates?: { latitude: number; longitude: number; }[]; holes?: { latitude: number; longitude: number; }[][]; onPress?: Function; @@ -122,7 +121,7 @@ declare namespace MapView { lineDashPattern?: number[]; } - interface MapCircleProps { + export interface MapCircleProps { center: { latitude: number; longitude: number }; radius: number; onPress?: Function; @@ -137,30 +136,28 @@ declare namespace MapView { lineDashPattern?: number[]; } - interface MapUrlTileProps { + export interface MapUrlTileProps { urlTemplate: string; zIndex?: number; } - interface MapLocalTileProps { + export interface MapLocalTileProps { pathTemplate: string; tileSize: number; zIndex?: number; } - interface MapCalloutProps { + export interface MapCalloutProps { tooltip?: boolean; onPress?: Function; style?: any; } - export class Marker extends React.Component {} - export class Polyline extends React.Component {} - export class Polygon extends React.Component {} - export class Circle extends React.Component {} - export class UrlTile extends React.Component {} - export class LocalTile extends React.Component {} - export class Callout extends React.Component {} + export class Marker extends React.Component { } + export class Polyline extends React.Component { } + export class Polygon extends React.Component { } + export class Circle extends React.Component { } + export class UrlTile extends React.Component { } + export class LocalTile extends React.Component { } + export class Callout extends React.Component { } } - -export = MapView; From 4ed5453bf097e9dafb8c524f452abd7eef69e6cc Mon Sep 17 00:00:00 2001 From: koka0012 Date: Wed, 27 Dec 2017 15:59:46 -0300 Subject: [PATCH 0379/1148] fixed polyline example --- docs/polyline.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/polyline.md b/docs/polyline.md index b00ecf0d9..97b11f8a8 100644 --- a/docs/polyline.md +++ b/docs/polyline.md @@ -46,7 +46,7 @@ Example: { latitude: 37.7734153, longitude: -122.4577787 }, { latitude: 37.7948605, longitude: -122.4596065 }, { latitude: 37.8025259, longitude: -122.4351431 } - ]) + ]} strokeColor="#000" // fallback for when `strokeColors` is not supported by the map-provider strokeColors={[ '#7F0000', @@ -59,4 +59,4 @@ Example: strokeWidth={6} /> -``` \ No newline at end of file +``` From 4c613242c52b9fb474c00350b2ce26465db91d69 Mon Sep 17 00:00:00 2001 From: Alexander Veligurov Date: Fri, 29 Dec 2017 08:22:47 -0300 Subject: [PATCH 0380/1148] Merge Ground Overlay Support (PR-1586) (#1918) --- README.md | 2 + docs/overlay.md | 17 +++ .../android/react/maps/AirMapOverlay.java | 109 ++++++++++++++++++ .../react/maps/AirMapOverlayManager.java | 72 ++++++++++++ .../airbnb/android/react/maps/AirMapView.java | 4 + .../airbnb/android/react/maps/ImageUtil.java | 27 +++++ .../android/react/maps/MapsPackage.java | 5 +- lib/components/MapOverlay.js | 70 +++++++++++ lib/components/MapView.js | 2 + 9 files changed, 307 insertions(+), 1 deletion(-) create mode 100644 docs/overlay.md create mode 100644 lib/android/src/main/java/com/airbnb/android/react/maps/AirMapOverlay.java create mode 100644 lib/android/src/main/java/com/airbnb/android/react/maps/AirMapOverlayManager.java create mode 100644 lib/android/src/main/java/com/airbnb/android/react/maps/ImageUtil.java create mode 100644 lib/components/MapOverlay.js diff --git a/README.md b/README.md index 76df69603..e146deb55 100644 --- a/README.md +++ b/README.md @@ -36,6 +36,8 @@ versions you should add `react` as a dependency in your `package.json`. [`` Component API](docs/circle.md) +[`` Component API](docs/overlay.md) + ## General Usage ```js diff --git a/docs/overlay.md b/docs/overlay.md new file mode 100644 index 000000000..f9a45d94f --- /dev/null +++ b/docs/overlay.md @@ -0,0 +1,17 @@ +# `` Component API + +## Props + +| Prop | Type | Default | Note | +|---|---|---|---| +| `image` | `ImageSource` | A custom image to be used as the overlay. Only required local image resources and uri (as for images located in the net) are allowed to be used. +| `bounds` | `Array` | | The coordinates for the image (left-top corner, right-bottom corner). + +## Types + +``` +type LatLng { + latitude: Number, + longitude: Number, +} +``` \ No newline at end of file diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapOverlay.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapOverlay.java new file mode 100644 index 000000000..9e257760c --- /dev/null +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapOverlay.java @@ -0,0 +1,109 @@ +package com.airbnb.android.react.maps; + +import android.content.Context; +import android.graphics.Bitmap; + +import com.facebook.react.bridge.ReadableArray; +import com.facebook.react.bridge.ReadableMap; +import com.google.android.gms.maps.GoogleMap; +import com.google.android.gms.maps.model.BitmapDescriptor; +import com.google.android.gms.maps.model.BitmapDescriptorFactory; +import com.google.android.gms.maps.model.GroundOverlay; +import com.google.android.gms.maps.model.GroundOverlayOptions; +import com.google.android.gms.maps.model.LatLng; +import com.google.android.gms.maps.model.LatLngBounds; + +import java.util.ArrayList; + +public class AirMapOverlay extends AirMapFeature { + + private GroundOverlayOptions groundOverlayOptions; + private GroundOverlay groundOverlay; + private LatLngBounds bounds; + private BitmapDescriptor iconBitmapDescriptor; + private float zIndex; + private float transparency; + + + public AirMapOverlay(Context context) { + super(context); + } + + + public void setBounds(ReadableArray bounds) { + ArrayList tmpBounds = new ArrayList<>(bounds.size()); + for (int i = 0; i < bounds.size(); i++) { + tmpBounds.add(bounds.getArray(i)); + } + this.bounds = new LatLngBounds( + new LatLng(Double.parseDouble(bounds.getArray(0).getString(0)), Double.parseDouble(bounds.getArray(0) + .getString(1))), + new LatLng(Double.parseDouble(bounds.getArray(1).getString(0)), Double + .parseDouble(bounds.getArray(1) + .getString(1))) + ); + if (groundOverlay != null) { + groundOverlay.setPositionFromBounds(this.bounds); + } + } + + public void setZIndex(float zIndex) { + this.zIndex = zIndex; + if (groundOverlay != null) { + groundOverlay.setZIndex(zIndex); + } + } + + // public void setTransparency(float transparency) { + // this.transparency = transparency; + // if (groundOverlay != null) { + // groundOverlay.setTransparency(transparency); + // } + // } + + public void setImage(String uri) { + this.iconBitmapDescriptor = getBitmapDescriptorByName(uri); + + if (groundOverlay != null) { + groundOverlay.setImage(this.iconBitmapDescriptor); + } + } + + + public GroundOverlayOptions getGroundOverlayOptions() { + if (groundOverlayOptions == null) { + groundOverlayOptions = createGroundOverlayOptions(); + } + return groundOverlayOptions; + } + + private GroundOverlayOptions createGroundOverlayOptions() { + GroundOverlayOptions options = new GroundOverlayOptions(); + options.image(iconBitmapDescriptor); + options.positionFromBounds(bounds); + // options.transparency(transparency); + options.zIndex(zIndex); + return options; + } + + private BitmapDescriptor getBitmapDescriptorByName(String name) { + Bitmap bitmap = ImageUtil.convert(name); + return BitmapDescriptorFactory.fromBitmap(bitmap); + } + + @Override + public Object getFeature() { + return groundOverlay; + } + + @Override + public void addToMap(GoogleMap map) { + groundOverlay = map.addGroundOverlay(getGroundOverlayOptions()); + groundOverlay.setClickable(true); + } + + @Override + public void removeFromMap(GoogleMap map) { + groundOverlay.remove(); + } +} diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapOverlayManager.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapOverlayManager.java new file mode 100644 index 000000000..ccc5a7eaa --- /dev/null +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapOverlayManager.java @@ -0,0 +1,72 @@ +package com.airbnb.android.react.maps; + +import android.content.Context; +import android.os.Build; +import android.util.DisplayMetrics; +import android.view.WindowManager; + +import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.bridge.ReadableArray; +import com.facebook.react.common.MapBuilder; +import com.facebook.react.uimanager.ThemedReactContext; +import com.facebook.react.uimanager.ViewGroupManager; +import com.facebook.react.uimanager.annotations.ReactProp; + +import java.util.Map; + +import javax.annotation.Nullable; + +public class AirMapOverlayManager extends ViewGroupManager { + private final DisplayMetrics metrics; + + public AirMapOverlayManager(ReactApplicationContext reactContext) { + super(); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { + metrics = new DisplayMetrics(); + ((WindowManager) reactContext.getSystemService(Context.WINDOW_SERVICE)) + .getDefaultDisplay() + .getRealMetrics(metrics); + } else { + metrics = reactContext.getResources().getDisplayMetrics(); + } + } + + @Override + public String getName() { + return "AIRMapOverlay"; + } + + @Override + public AirMapOverlay createViewInstance(ThemedReactContext context) { + return new AirMapOverlay(context); + } + + @ReactProp(name = "bounds") + public void setBounds(AirMapOverlay view, ReadableArray bounds) { + view.setBounds(bounds); + } + + @ReactProp(name = "zIndex", defaultFloat = 1.0f) + public void setZIndex(AirMapOverlay view, float zIndex) { + view.setZIndex(zIndex); + } + + // @ReactProp(name = "transparency", defaultFloat = 1.0f) + // public void setTransparency(AirMapOverlay view, float transparency) { + // view.setTransparency(transparency); + // } + + @ReactProp(name = "image") + public void setImage(AirMapOverlay view, @Nullable String source) { + view.setImage(source); + } + + + @Override + @Nullable + public Map getExportedCustomDirectEventTypeConstants() { + return MapBuilder.of( + "onPress", MapBuilder.of("registrationName", "onPress") + ); + } +} diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java index 9ba2368a2..20dbad12b 100644 --- a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java @@ -506,6 +506,10 @@ public void addFeature(View child, int index) { AirMapLocalTile localTileView = (AirMapLocalTile) child; localTileView.addToMap(map); features.add(index, localTileView); + } else if (child instanceof AirMapOverlay) { + AirMapOverlay overlayView = (AirMapOverlay) child; + overlayView.addToMap(map); + features.add(index, overlayView); } else if (child instanceof ViewGroup) { ViewGroup children = (ViewGroup) child; for (int i = 0; i < children.getChildCount(); i++) { diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/ImageUtil.java b/lib/android/src/main/java/com/airbnb/android/react/maps/ImageUtil.java new file mode 100644 index 000000000..35078a905 --- /dev/null +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/ImageUtil.java @@ -0,0 +1,27 @@ +package com.airbnb.android.react.maps; + + +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.util.Base64; + +import java.io.ByteArrayOutputStream; + +public class ImageUtil { + public static Bitmap convert(String base64Str) throws IllegalArgumentException { + byte[] decodedBytes = Base64.decode( + base64Str.substring(base64Str.indexOf(",") + 1), + Base64.DEFAULT + ); + + return BitmapFactory.decodeByteArray(decodedBytes, 0, decodedBytes.length); + } + + public static String convert(Bitmap bitmap) { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + bitmap.compress(Bitmap.CompressFormat.PNG, 100, outputStream); + + return Base64.encodeToString(outputStream.toByteArray(), Base64.DEFAULT); + } + +} \ No newline at end of file diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/MapsPackage.java b/lib/android/src/main/java/com/airbnb/android/react/maps/MapsPackage.java index 63e55d8ae..45364b3be 100644 --- a/lib/android/src/main/java/com/airbnb/android/react/maps/MapsPackage.java +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/MapsPackage.java @@ -40,6 +40,7 @@ public List createViewManagers(ReactApplicationContext reactContext AirMapLiteManager mapLiteManager = new AirMapLiteManager(reactContext); AirMapUrlTileManager urlTileManager = new AirMapUrlTileManager(reactContext); AirMapLocalTileManager localTileManager = new AirMapLocalTileManager(reactContext); + AirMapOverlayManager overlayManager = new AirMapOverlayManager(reactContext); return Arrays.asList( calloutManager, @@ -50,6 +51,8 @@ public List createViewManagers(ReactApplicationContext reactContext mapManager, mapLiteManager, urlTileManager, - localTileManager); + localTileManager, + overlayManager + ); } } diff --git a/lib/components/MapOverlay.js b/lib/components/MapOverlay.js new file mode 100644 index 000000000..5c1581548 --- /dev/null +++ b/lib/components/MapOverlay.js @@ -0,0 +1,70 @@ +import React, { PropTypes, Component } from 'react'; +import { + View, + StyleSheet, + Animated, +} from 'react-native'; + +import resolveAssetSource from 'react-native/Libraries/Image/resolveAssetSource'; +import decorateMapComponent, { + SUPPORTED, + USES_DEFAULT_IMPLEMENTATION, +} from './decorateMapComponent'; + +const viewConfig = { + uiViewClassName: 'AIRMapOverlay', + validAttributes: { + image: true, + }, +}; + +const propTypes = { + ...View.propTypes, + // A custom image to be used as overlay. + image: PropTypes.any.isRequired, + // Top left and bottom right coordinates for the overlay + bounds: PropTypes.arrayOf(PropTypes.array.isRequired).isRequired, +}; + +class MapOverlay extends Component { + + render() { + let image; + if (this.props.image) { + image = resolveAssetSource(this.props.image) || {}; + image = image.uri; + } + + const AIRMapOverlay = this.getAirComponent(); + + return ( + + ); + } +} + +MapOverlay.propTypes = propTypes; +MapOverlay.viewConfig = viewConfig; + +const styles = StyleSheet.create({ + overlay: { + position: 'absolute', + backgroundColor: 'transparent', + }, +}); + +MapOverlay.Animated = Animated.createAnimatedComponent(MapOverlay); + +module.exports = decorateMapComponent(MapOverlay, { + componentType: 'Overlay', + providers: { + google: { + ios: SUPPORTED, + android: USES_DEFAULT_IMPLEMENTATION, + }, + }, +}); diff --git a/lib/components/MapView.js b/lib/components/MapView.js index 8c3ccadbe..b72ffb118 100644 --- a/lib/components/MapView.js +++ b/lib/components/MapView.js @@ -16,6 +16,7 @@ import MapPolyline from './MapPolyline'; import MapPolygon from './MapPolygon'; import MapCircle from './MapCircle'; import MapCallout from './MapCallout'; +import MapOverlay from './MapOverlay'; import MapUrlTile from './MapUrlTile'; import MapLocalTile from './MapLocalTile'; import AnimatedRegion from './AnimatedRegion'; @@ -749,6 +750,7 @@ MapView.Polygon = MapPolygon; MapView.Circle = MapCircle; MapView.UrlTile = MapUrlTile; MapView.LocalTile = MapLocalTile; +MapView.Overlay = MapOverlay; MapView.Callout = MapCallout; Object.assign(MapView, ProviderConstants); MapView.ProviderPropType = PropTypes.oneOf(Object.values(ProviderConstants)); From d598a99b0a2688c3e93e2ed03d93c5675951468a Mon Sep 17 00:00:00 2001 From: Tomas Maly Date: Sun, 31 Dec 2017 05:32:41 -0800 Subject: [PATCH 0381/1148] Update MapOverlay.js (#1927) * Update MapOverlay.js Fixing PropTypes usage for modern React * Update MapView.js Fixing map movement jerking loop * Update MapView.js Removing code that did not help --- lib/components/MapOverlay.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/components/MapOverlay.js b/lib/components/MapOverlay.js index 5c1581548..93215212a 100644 --- a/lib/components/MapOverlay.js +++ b/lib/components/MapOverlay.js @@ -1,4 +1,5 @@ -import React, { PropTypes, Component } from 'react'; +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; import { View, StyleSheet, From 148c4d3cd82635117375d62f2ce9541afa6dff41 Mon Sep 17 00:00:00 2001 From: Budi Adiono Date: Sun, 7 Jan 2018 09:49:43 +0700 Subject: [PATCH 0382/1148] Added missing methods declaration (index.d.ts) (#1930) --- index.d.ts | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/index.d.ts b/index.d.ts index 01627932c..64b53d17e 100644 --- a/index.d.ts +++ b/index.d.ts @@ -1,5 +1,17 @@ declare module "react-native-maps" { import * as React from 'react'; + + export interface Region { + latitude: number + longitude: number + latitudeDelta: number + longitudeDelta: number + } + + export interface LatLng { + latitude: number + longitude: number + } export interface MapViewProps { provider?: 'google'; @@ -57,6 +69,14 @@ declare module "react-native-maps" { export default class MapView extends React.Component { static Animated: any; static AnimatedRegion: any; + animateToRegion(region: Region, duration?: number): void; + animateToCoordinate(latLng: LatLng, duration?: number): void; + animateToBearing(bearing: number, duration?: number): void; + animateToViewingAngle(angle: number, duration?: number): void; + fitToElements(animated: boolean): void; + fitToSuppliedMarkers(markers: string[], animated: boolean): void; + fitToCoordinates(coordinates?: LatLng[], options?:{}): void; + setMapBoundaries(northEast: LatLng, southWest: LatLng): void; } export type LineCapType = 'butt' | 'round' | 'square'; From 4a7e113420bd32ecfb6801cd5ec14881b039d0a7 Mon Sep 17 00:00:00 2001 From: Mohammad Reza Abedini Date: Mon, 8 Jan 2018 13:53:09 +0330 Subject: [PATCH 0383/1148] Add openning the .xcworkspace file instead of .xcodeproj to documentation. (#1931) --- docs/installation.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/installation.md b/docs/installation.md index 9af69f623..cd4041de1 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -88,7 +88,9 @@ Add to `ios/_YOUR_PROJECT_NAME_/AppDelegate.m: ... ``` +## Notes on running on a real ios device +The steps are as described in https://facebook.github.io/react-native/docs/running-on-device.html , however instead of opening the .xcodeproj file you should open .xcworkspace file. ## Android From 9cb22b9dd8249169cddaf94903a64e6602b460e0 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Wed, 10 Jan 2018 13:04:56 +0200 Subject: [PATCH 0384/1148] New methods to convert between LatLng and Point (#1851) * New methods to convert between LatLng and Point * Clarification for `pointForCoordinate` and `coordinateForPoint` --- docs/mapview.md | 2 + .../android/react/maps/AirMapModule.java | 75 +++++++++++++++++++ lib/components/MapView.js | 58 ++++++++++++++ lib/ios/AirGoogleMaps/AIRGoogleMapManager.m | 53 +++++++++++++ lib/ios/AirMaps/AIRMap.m | 32 ++++++++ 5 files changed, 220 insertions(+) diff --git a/docs/mapview.md b/docs/mapview.md index b2c021414..ddb8dc75c 100644 --- a/docs/mapview.md +++ b/docs/mapview.md @@ -71,6 +71,8 @@ To access event data, you will need to use `e.nativeEvent`. For example, `onPres | `fitToElements` | `animated: Boolean` | | `fitToSuppliedMarkers` | `markerIDs: String[]`, `animated: Boolean` | If you need to use this in `ComponentDidMount`, make sure you put it in a timeout or it will cause performance problems. | `fitToCoordinates` | `coordinates: Array, options: { edgePadding: EdgePadding, animated: Boolean }` | If called in `ComponentDidMount` in android, it will cause an exception. It is recommended to call it from the MapView `onLayout` event. +| `pointForCoordinate` | `coordinate: LatLng` | Converts a map coordinate to a view coordinate (`Point`). Returns a `Promise`. +| `coordinateForPoint` | `point: Point` | Converts a view coordinate (`Point`) to a map coordinate. Returns a `Promise`. diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapModule.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapModule.java index dfc71d6d9..02c43b2fb 100644 --- a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapModule.java +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapModule.java @@ -2,6 +2,7 @@ import android.app.Activity; import android.graphics.Bitmap; +import android.graphics.Point; import android.net.Uri; import android.util.Base64; import android.util.DisplayMetrics; @@ -11,11 +12,13 @@ import com.facebook.react.bridge.ReactContextBaseJavaModule; import com.facebook.react.bridge.ReactMethod; import com.facebook.react.bridge.ReadableMap; +import com.facebook.react.bridge.WritableNativeMap; import com.facebook.react.uimanager.NativeViewHierarchyManager; import com.facebook.react.uimanager.UIBlock; import com.facebook.react.uimanager.UIManagerModule; import com.google.android.gms.maps.GoogleMap; import com.google.android.gms.common.GoogleApiAvailability; +import com.google.android.gms.maps.model.LatLng; import java.io.ByteArrayOutputStream; import java.io.Closeable; @@ -135,4 +138,76 @@ public void onSnapshotReady(@Nullable Bitmap snapshot) { } }); } + + @ReactMethod + public void pointForCoordinate(final int tag, ReadableMap coordinate, final Promise promise) { + final LatLng coord = new LatLng( + coordinate.hasKey("latitude") ? coordinate.getDouble("latitude") : 0.0, + coordinate.hasKey("longitude") ? coordinate.getDouble("longitude") : 0.0 + ); + + final ReactApplicationContext context = getReactApplicationContext(); + UIManagerModule uiManager = context.getNativeModule(UIManagerModule.class); + uiManager.addUIBlock(new UIBlock() + { + @Override + public void execute(NativeViewHierarchyManager nvhm) + { + AirMapView view = (AirMapView) nvhm.resolveView(tag); + if (view == null) { + promise.reject("AirMapView not found"); + return; + } + if (view.map == null) { + promise.reject("AirMapView.map is not valid"); + return; + } + + Point pt = view.map.getProjection().toScreenLocation(coord); + + WritableMap ptJson = new WritableNativeMap(); + ptJson.putDouble("x", pt.x); + ptJson.putDouble("y", pt.y); + + promise.resolve(ptJson); + } + }); + } + + @ReactMethod + public void coordinateForPoint(final int tag, ReadableMap point, final Promise promise) { + final Point pt = new Point( + point.hasKey("x") ? point.getInt("x") : 0, + point.hasKey("y") ? point.getInt("y") : 0 + ); + + final ReactApplicationContext context = getReactApplicationContext(); + UIManagerModule uiManager = context.getNativeModule(UIManagerModule.class); + uiManager.addUIBlock(new UIBlock() + { + @Override + public void execute(NativeViewHierarchyManager nvhm) + { + AirMapView view = (AirMapView) nvhm.resolveView(tag); + if (view == null) + { + promise.reject("AirMapView not found"); + return; + } + if (view.map == null) + { + promise.reject("AirMapView.map is not valid"); + return; + } + + LatLng coord = view.map.getProjection().fromScreenLocation(pt); + + WritableMap coordJson = new WritableNativeMap(); + coordJson.putDouble("latitude", coord.latitude); + coordJson.putDouble("longitude", coord.longitude); + + promise.resolve(coordJson); + } + }); + } } diff --git a/lib/components/MapView.js b/lib/components/MapView.js index b72ffb118..b28054291 100644 --- a/lib/components/MapView.js +++ b/lib/components/MapView.js @@ -630,6 +630,64 @@ class MapView extends React.Component { return Promise.reject('takeSnapshot not supported on this platform'); } + /** + * Convert a map coordinate to user-space point + * + * @param coordinate Coordinate + * @param [coordinate.latitude] Latitude + * @param [coordinate.longitude] Longitude + * + * @return Promise Promise with the point ({ x: Number, y: Number }) + */ + pointForCoordinate(coordinate) { + if (Platform.OS === 'android') { + return NativeModules.AirMapModule.pointForCoordinate(this._getHandle(), coordinate); + } else if (Platform.OS === 'ios') { + return new Promise((resolve, reject) => { + this._runCommand('pointForCoordinate', [ + coordinate, + (err, snapshot) => { + if (err) { + reject(err); + } else { + resolve(snapshot); + } + }, + ]); + }); + } + return Promise.reject('pointForCoordinate not supported on this platform'); + } + + /** + * Convert a user-space point to a map coordinate + * + * @param point Point + * @param [point.x] X + * @param [point.x] Y + * + * @return Promise Promise with the coordinate ({ latitude: Number, longitude: Number }) + */ + coordinateFromPoint(point) { + if (Platform.OS === 'android') { + return NativeModules.AirMapModule.coordinateFromPoint(this._getHandle(), point); + } else if (Platform.OS === 'ios') { + return new Promise((resolve, reject) => { + this._runCommand('coordinateFromPoint', [ + point, + (err, snapshot) => { + if (err) { + reject(err); + } else { + resolve(snapshot); + } + }, + ]); + }); + } + return Promise.reject('coordinateFromPoint not supported on this platform'); + } + _uiManagerCommand(name) { return NativeModules.UIManager[getAirMapName(this.props.provider)].Commands[name]; } diff --git a/lib/ios/AirGoogleMaps/AIRGoogleMapManager.m b/lib/ios/AirGoogleMaps/AIRGoogleMapManager.m index 0d5e1d5c4..ba2077c96 100644 --- a/lib/ios/AirGoogleMaps/AIRGoogleMapManager.m +++ b/lib/ios/AirGoogleMaps/AIRGoogleMapManager.m @@ -294,6 +294,59 @@ - (UIView *)view }]; } +RCT_EXPORT_METHOD(pointForCoordinate:(nonnull NSNumber *)reactTag + coordinate:(NSDictionary *)coordinate + withCallback:(RCTResponseSenderBlock)callback) +{ + CLLocationCoordinate2D coord = + CLLocationCoordinate2DMake( + [coordinate[@"latitude"] doubleValue], + [coordinate[@"longitude"] doubleValue] + ); + + [self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary *viewRegistry) { + id view = viewRegistry[reactTag]; + if (![view isKindOfClass:[AIRGoogleMap class]]) { + RCTLogError(@"Invalid view returned from registry, expecting AIRMap, got: %@", view); + } else { + AIRGoogleMap *mapView = (AIRGoogleMap *)view; + + CGPoint touchPoint = [mapView.projection pointForCoordinate:coord]; + + callback(@[[NSNull null], @{ + @"x": @(touchPoint.x), + @"y": @(touchPoint.y), + }]); + } + }]; +} + +RCT_EXPORT_METHOD(coordinateForPoint:(nonnull NSNumber *)reactTag + point:(NSDictionary *)point + withCallback:(RCTResponseSenderBlock)callback) +{ + CGPoint pt = CGPointMake( + [point[@"x"] doubleValue], + [point[@"y"] doubleValue] + ); + + [self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary *viewRegistry) { + id view = viewRegistry[reactTag]; + if (![view isKindOfClass:[AIRGoogleMap class]]) { + RCTLogError(@"Invalid view returned from registry, expecting AIRMap, got: %@", view); + } else { + AIRGoogleMap *mapView = (AIRGoogleMap *)view; + + CLLocationCoordinate2D coordinate = [mapView.projection coordinateForPoint:pt]; + + callback(@[[NSNull null], @{ + @"latitude": @(coordinate.latitude), + @"longitude": @(coordinate.longitude), + }]); + } + }]; +} + RCT_EXPORT_METHOD(setMapBoundaries:(nonnull NSNumber *)reactTag northEast:(CLLocationCoordinate2D)northEast southWest:(CLLocationCoordinate2D)southWest) diff --git a/lib/ios/AirMaps/AIRMap.m b/lib/ios/AirMaps/AIRMap.m index cf194363a..335059877 100644 --- a/lib/ios/AirMaps/AIRMap.m +++ b/lib/ios/AirMaps/AIRMap.m @@ -302,6 +302,38 @@ - (void)setLoadingIndicatorColor:(UIColor *)loadingIndicatorColor { self.activityIndicatorView.color = loadingIndicatorColor; } +RCT_EXPORT_METHOD(pointForCoordinate:(NSDictionary *)coordinate resolver: (RCTPromiseResolveBlock)resolve + rejecter:(RCTPromiseRejectBlock)reject) +{ + CGPoint touchPoint = [self convertCoordinate: + CLLocationCoordinate2DMake( + [coordinate[@"lat"] doubleValue], + [coordinate[@"lng"] doubleValue] + ) + toPointToView:self]; + + resolve(@{ + @"x": @(touchPoint.x), + @"y": @(touchPoint.y), + }); +} + +RCT_EXPORT_METHOD(coordinateForPoint:(NSDictionary *)point resolver: (RCTPromiseResolveBlock)resolve + rejecter:(RCTPromiseRejectBlock)reject) +{ + CLLocationCoordinate2D coordinate = [self convertPoint: + CGPointMake( + [point[@"x"] doubleValue], + [point[@"y"] doubleValue] + ) + toCoordinateFromView:self]; + + resolve(@{ + @"lat": @(coordinate.latitude), + @"lng": @(coordinate.longitude), + }); +} + // Include properties of MKMapView which are only available on iOS 9+ // and check if their selector is available before calling super method. From 0fcfa3a7088c3148b2ecd7bd365ab0ba7df6e3b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Vendramini?= Date: Thu, 11 Jan 2018 08:41:15 -0200 Subject: [PATCH 0385/1148] Add missing import on AirMapModule.java (#1958) --- .../main/java/com/airbnb/android/react/maps/AirMapModule.java | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapModule.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapModule.java index 02c43b2fb..2cec24eba 100644 --- a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapModule.java +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapModule.java @@ -12,6 +12,7 @@ import com.facebook.react.bridge.ReactContextBaseJavaModule; import com.facebook.react.bridge.ReactMethod; import com.facebook.react.bridge.ReadableMap; +import com.facebook.react.bridge.WritableMap; import com.facebook.react.bridge.WritableNativeMap; import com.facebook.react.uimanager.NativeViewHierarchyManager; import com.facebook.react.uimanager.UIBlock; From 9f592ba8fd41eba4cd60e4daaddf0857cf8688bb Mon Sep 17 00:00:00 2001 From: Olof Dahlbom Date: Thu, 11 Jan 2018 15:48:55 +0100 Subject: [PATCH 0386/1148] Fix callouts appearing behind markers (#1846) A bit ugly, but works well. --- lib/ios/AirMaps/AIRMapMarker.m | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/lib/ios/AirMaps/AIRMapMarker.m b/lib/ios/AirMaps/AIRMapMarker.m index 8be20784e..9fc6c96f9 100644 --- a/lib/ios/AirMaps/AIRMapMarker.m +++ b/lib/ios/AirMaps/AIRMapMarker.m @@ -14,8 +14,11 @@ #import #import #import +NSInteger const CALLOUT_OPEN_ZINDEX_BASELINE = 999; @implementation AIREmptyCalloutBackgroundView +bool _calloutIsOpen = NO; +NSInteger _zIndexBeforeOpen = 0; @end @implementation AIRMapMarker { @@ -137,6 +140,9 @@ - (void)fillCalloutView:(SMCalloutView *)calloutView - (void)showCalloutView { + _calloutIsOpen = YES; + [self setZIndex:_zIndexBeforeOpen]; + MKAnnotationView *annotationView = [self getAnnotationView]; [self setSelected:YES animated:NO]; @@ -222,6 +228,8 @@ - (void)_handleTap:(UITapGestureRecognizer *)recognizer { - (void)hideCalloutView { + _calloutIsOpen = NO; + [self setZIndex:_zIndexBeforeOpen]; // hide the callout view [self.map.calloutView dismissCalloutAnimated:YES]; @@ -298,8 +306,9 @@ - (void)setPinColor:(UIColor *)pinColor - (void)setZIndex:(NSInteger)zIndex { - _zIndex = zIndex; - self.layer.zPosition = _zIndex; + _zIndexBeforeOpen = zIndex; + _zIndex = _calloutIsOpen ? zIndex + CALLOUT_OPEN_ZINDEX_BASELINE : zIndex; + self.layer.zPosition = zIndex; } @end From 3ee850b5e31bc588e4618a2cee99e64d33cfef58 Mon Sep 17 00:00:00 2001 From: Ben Roth Date: Fri, 12 Jan 2018 11:28:24 -0800 Subject: [PATCH 0387/1148] [docs] Clarify that mutedStandard is only supported starting in iOS 11 (#1962) --- docs/mapview.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/mapview.md b/docs/mapview.md index ddb8dc75c..707226b9a 100644 --- a/docs/mapview.md +++ b/docs/mapview.md @@ -8,7 +8,7 @@ | `region` | `Region` | | The region to be displayed by the map.

The region is defined by the center coordinates and the span of coordinates to display. | `initialRegion` | `Region` | | The initial region to be displayed by the map. Use this prop instead of `region` only if you don't want to control the viewport of the map besides the initial region.

Changing this prop after the component has mounted will not result in a region change.

This is similar to the `initialValue` prop of a text input. | `liteMode` | `Boolean` | `false` | Enable lite mode. **Note**: Android only. -| `mapType` | `String` | `"standard"` | The map type to be displayed.

- standard: standard road map (default)
- satellite: satellite view
- hybrid: satellite view with roads and points of interest overlayed
- terrain: (Android only) topographic view
- mutedStandard: more subtle, makes markers/lines pop more (iOS only) +| `mapType` | `String` | `"standard"` | The map type to be displayed.

- standard: standard road map (default)
- satellite: satellite view
- hybrid: satellite view with roads and points of interest overlayed
- terrain: (Android only) topographic view
- mutedStandard: more subtle, makes markers/lines pop more (iOS 11.0+ only) | `customMapStyle` | `Array` | | Adds custom styling to the map component. See [README](https://github.com/airbnb/react-native-maps#customizing-the-map-style) for more information. | `showsUserLocation` | `Boolean` | `false` | If `true` the app will ask for the user's location. **NOTE**: You need to add `NSLocationWhenInUseUsageDescription` key in Info.plist to enable geolocation, otherwise it is going to *fail silently*! | `userLocationAnnotationTitle` | `String` | | The title of the annotation for current user location. This only works if `showsUserLocation` is true. There is a default value `My Location` set by MapView. **Note**: iOS only. From 153257316a092db3cdacdf311e021ba458d9ea4f Mon Sep 17 00:00:00 2001 From: Alexander Veligurov Date: Fri, 12 Jan 2018 21:25:01 -0300 Subject: [PATCH 0388/1148] Fix build example for android --- example/android/app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/example/android/app/build.gradle b/example/android/app/build.gradle index 3dd571052..d2b475051 100644 --- a/example/android/app/build.gradle +++ b/example/android/app/build.gradle @@ -130,5 +130,5 @@ dependencies { compile 'com.facebook.react:react-native:0.51.+' compile 'com.android.support:appcompat-v7:25.3.0' compile 'com.android.support:support-annotations:25.3.0' - compile project(':react-native-maps') + compile project(':react-native-maps-lib') } From 8cb7a35fc8c14ec01766204709424fc8bd9580dd Mon Sep 17 00:00:00 2001 From: Alexander Veligurov Date: Fri, 12 Jan 2018 21:47:13 -0300 Subject: [PATCH 0389/1148] Fix docs for run examples --- README.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/README.md b/README.md index e146deb55..af28f5454 100644 --- a/README.md +++ b/README.md @@ -247,6 +247,21 @@ An unofficial step-by-step guide is also available at https://gist.github.com/he ## Examples +To run examples: + +Android: +```bash +npm i +npm start + +#Android +npm run run:android + +#iOS +npm run build:ios +npm run run:ios +``` + ### MapView Events The `` component and its child components have several events that you can subscribe to. From 0d540b9b7d3fc2c97262b4a9655ad97202a3992d Mon Sep 17 00:00:00 2001 From: Alexander Veligurov Date: Fri, 12 Jan 2018 21:51:27 -0300 Subject: [PATCH 0390/1148] Update README.md --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index af28f5454..1fbb6c430 100644 --- a/README.md +++ b/README.md @@ -249,7 +249,6 @@ An unofficial step-by-step guide is also available at https://gist.github.com/he To run examples: -Android: ```bash npm i npm start From 13abfa4a149a78902bb931e475e6beff35fc7be1 Mon Sep 17 00:00:00 2001 From: satori-ytolstoguzov <31261230+satori-ytolstoguzov@users.noreply.github.com> Date: Wed, 17 Jan 2018 09:45:07 -0800 Subject: [PATCH 0391/1148] Added tracksInfoWindowChanges property to iOS Google Maps (#1969) --- docs/marker.md | 1 + lib/components/MapMarker.js | 8 ++++++++ lib/ios/AirGoogleMaps/AIRGoogleMapMarker.h | 1 + lib/ios/AirGoogleMaps/AIRGoogleMapMarker.m | 9 +++++++++ lib/ios/AirGoogleMaps/AIRGoogleMapMarkerManager.m | 1 + 5 files changed, 20 insertions(+) diff --git a/docs/marker.md b/docs/marker.md index 4214e4d6e..a3e409cec 100644 --- a/docs/marker.md +++ b/docs/marker.md @@ -17,6 +17,7 @@ | `identifier` | `String` | | An identifier used to reference this marker at a later date. | `rotation` | `Float` | | A float number indicating marker's rotation angle, in degrees. | `draggable` | `` | | This is a non-value based prop. Adding this allows the marker to be draggable (re-positioned). +| `tracksInfoWindowChanges` | false | Sets whether this marker should track view changes in info window. Enabling it will let marker change content of info window after first render pass, but will lead to decreased performance, so it's recommended to disable it whenever you don't need it. **Note**: iOS Google Maps only. ## Events diff --git a/lib/components/MapMarker.js b/lib/components/MapMarker.js index a2f809f58..7d906f6b6 100644 --- a/lib/components/MapMarker.js +++ b/lib/components/MapMarker.js @@ -177,6 +177,14 @@ const propTypes = { tracksViewChanges: PropTypes.bool, + /** + * Sets whether this marker should track view changes in info window true. + * + * @platform ios + */ + + tracksInfoWindowChanges: PropTypes.bool, + /** * Callback that is called when the user presses on the marker */ diff --git a/lib/ios/AirGoogleMaps/AIRGoogleMapMarker.h b/lib/ios/AirGoogleMaps/AIRGoogleMapMarker.h index 1cb4d2659..cc536d52b 100644 --- a/lib/ios/AirGoogleMaps/AIRGoogleMapMarker.h +++ b/lib/ios/AirGoogleMaps/AIRGoogleMapMarker.h @@ -32,6 +32,7 @@ @property (nonatomic, assign) double opacity; @property (nonatomic, assign) BOOL draggable; @property (nonatomic, assign) BOOL tracksViewChanges; +@property (nonatomic, assign) BOOL tracksInfoWindowChanges; - (void)showCalloutView; - (void)hideCalloutView; diff --git a/lib/ios/AirGoogleMaps/AIRGoogleMapMarker.m b/lib/ios/AirGoogleMaps/AIRGoogleMapMarker.m index 42cf016a9..5c513854c 100644 --- a/lib/ios/AirGoogleMaps/AIRGoogleMapMarker.m +++ b/lib/ios/AirGoogleMaps/AIRGoogleMapMarker.m @@ -37,6 +37,7 @@ - (instancetype)init _realMarker = [[AIRGMSMarker alloc] init]; _realMarker.fakeMarker = self; _realMarker.tracksViewChanges = true; + _realMarker.tracksInfoWindowChanges = false; } return self; } @@ -304,4 +305,12 @@ - (BOOL)tracksViewChanges { return _realMarker.tracksViewChanges; } +- (void)setTracksInfoWindowChanges:(BOOL)tracksInfoWindowChanges { + _realMarker.tracksInfoWindowChanges = tracksInfoWindowChanges; +} + +- (BOOL)tracksInfoWindowChanges { + return _realMarker.tracksInfoWindowChanges; +} + @end diff --git a/lib/ios/AirGoogleMaps/AIRGoogleMapMarkerManager.m b/lib/ios/AirGoogleMaps/AIRGoogleMapMarkerManager.m index 6b9c8f64b..ff9b1afa7 100644 --- a/lib/ios/AirGoogleMaps/AIRGoogleMapMarkerManager.m +++ b/lib/ios/AirGoogleMaps/AIRGoogleMapMarkerManager.m @@ -38,6 +38,7 @@ - (UIView *)view RCT_EXPORT_VIEW_PROPERTY(zIndex, NSInteger) RCT_EXPORT_VIEW_PROPERTY(draggable, BOOL) RCT_EXPORT_VIEW_PROPERTY(tracksViewChanges, BOOL) +RCT_EXPORT_VIEW_PROPERTY(tracksInfoWindowChanges, BOOL) RCT_EXPORT_VIEW_PROPERTY(opacity, double) RCT_EXPORT_VIEW_PROPERTY(onDragStart, RCTDirectEventBlock) RCT_EXPORT_VIEW_PROPERTY(onDrag, RCTDirectEventBlock) From 937b082dce09d893f2732a4bd4255e98c84d29e7 Mon Sep 17 00:00:00 2001 From: satori-ytolstoguzov <31261230+satori-ytolstoguzov@users.noreply.github.com> Date: Wed, 17 Jan 2018 13:08:11 -0800 Subject: [PATCH 0392/1148] Added tracksViewChanges description to marker docs (#1968) --- docs/marker.md | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/docs/marker.md b/docs/marker.md index a3e409cec..97f79ab79 100644 --- a/docs/marker.md +++ b/docs/marker.md @@ -9,15 +9,16 @@ | `image` | `ImageSource` | | A custom image to be used as the marker's icon. Only local image resources are allowed to be used. | `pinColor` | `Color` | | If no custom marker view or custom image is provided, the platform default pin will be used, which can be customized by this color. Ignored if a custom marker is being used. | `coordinate` | `LatLng` | | The coordinate for the marker. -| `centerOffset` | `Point` | | The offset (in points) at which to display the view.

By default, the center point of an annotation view is placed at the coordinate point of the associated annotation. You can use this property to reposition the annotation view as needed. This x and y offset values are measured in points. Positive offset values move the annotation view down and to the right, while negative values move it up and to the left.

For Google Maps, see the `anchor` prop. -| `calloutOffset` | `Point` | | The offset (in points) at which to place the callout bubble.

This property determines the additional distance by which to move the callout bubble. When this property is set to (0, 0), the anchor point of the callout bubble is placed on the top-center point of the marker view’s frame. Specifying positive offset values moves the callout bubble down and to the right, while specifying negative values moves it up and to the left.

For android, see the `calloutAnchor` prop. -| `anchor` | `Point` | | Sets the anchor point for the marker.

The anchor specifies the point in the icon image that is anchored to the marker's position on the Earth's surface.

The anchor point is specified in the continuous space [0.0, 1.0] x [0.0, 1.0], where (0, 0) is the top-left corner of the image, and (1, 1) is the bottom-right corner. The anchoring point in a W x H image is the nearest discrete grid point in a (W + 1) x (H + 1) grid, obtained by scaling the then rounding. For example, in a 4 x 2 image, the anchor point (0.7, 0.6) resolves to the grid point at (3, 1).

For MapKit on iOS, see the `centerOffset` prop. -| `calloutAnchor` | `Point` | | Specifies the point in the marker image at which to anchor the callout when it is displayed. This is specified in the same coordinate system as the anchor. See the `anchor` prop for more details.

The default is the top middle of the image.

For ios, see the `calloutOffset` prop. -| `flat` | `Boolean` | | Sets whether this marker should be flat against the map true or a billboard facing the camera false. +| `centerOffset` | `Point` | (0, 0) | The offset (in points) at which to display the view.

By default, the center point of an annotation view is placed at the coordinate point of the associated annotation. You can use this property to reposition the annotation view as needed. This x and y offset values are measured in points. Positive offset values move the annotation view down and to the right, while negative values move it up and to the left.

For Google Maps, see the `anchor` prop. +| `calloutOffset` | `Point` | (0, 0) | The offset (in points) at which to place the callout bubble.

This property determines the additional distance by which to move the callout bubble. When this property is set to (0, 0), the anchor point of the callout bubble is placed on the top-center point of the marker view’s frame. Specifying positive offset values moves the callout bubble down and to the right, while specifying negative values moves it up and to the left.

For android, see the `calloutAnchor` prop. +| `anchor` | `Point` | (0.5, 1) | Sets the anchor point for the marker.

The anchor specifies the point in the icon image that is anchored to the marker's position on the Earth's surface.

The anchor point is specified in the continuous space [0.0, 1.0] x [0.0, 1.0], where (0, 0) is the top-left corner of the image, and (1, 1) is the bottom-right corner. The anchoring point in a W x H image is the nearest discrete grid point in a (W + 1) x (H + 1) grid, obtained by scaling the then rounding. For example, in a 4 x 2 image, the anchor point (0.7, 0.6) resolves to the grid point at (3, 1).

For MapKit on iOS, see the `centerOffset` prop. +| `calloutAnchor` | `Point` | (0.5, 0) | Specifies the point in the marker image at which to anchor the callout when it is displayed. This is specified in the same coordinate system as the anchor. See the `anchor` prop for more details.

The default is the top middle of the image.

For ios, see the `calloutOffset` prop. +| `flat` | `Boolean` | false | Sets whether this marker should be flat against the map true or a billboard facing the camera. | `identifier` | `String` | | An identifier used to reference this marker at a later date. -| `rotation` | `Float` | | A float number indicating marker's rotation angle, in degrees. +| `rotation` | `Float` | 0 | A float number indicating marker's rotation angle, in degrees. | `draggable` | `` | | This is a non-value based prop. Adding this allows the marker to be draggable (re-positioned). -| `tracksInfoWindowChanges` | false | Sets whether this marker should track view changes in info window. Enabling it will let marker change content of info window after first render pass, but will lead to decreased performance, so it's recommended to disable it whenever you don't need it. **Note**: iOS Google Maps only. +| `tracksViewChanges` | `Boolean` | true | Sets whether this marker should track view changes. It's recommended to turn it off whenever it's possible to improve custom marker performance. **Note**: iOS Google Maps only. +| `tracksInfoWindowChanges` | `Boolean` | false | Sets whether this marker should track view changes in info window. Enabling it will let marker change content of info window after first render pass, but will lead to decreased performance, so it's recommended to disable it whenever you don't need it. **Note**: iOS Google Maps only. ## Events From 5ec275cb8535f47af21c6ae11290bd0329d3c3c7 Mon Sep 17 00:00:00 2001 From: Hein Rutjes Date: Wed, 17 Jan 2018 22:10:18 +0100 Subject: [PATCH 0393/1148] Fixed gradient polyline not always fully drawn + crashes (#1960) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The gradient polyline was not always completely visible, because the Matrix transform in the paths was not applied correctly. This happened, because the segments were cached and could have the wrong matrix transform applied to them. This could cause the line to not visible, because it will below the map-tile. Also, I’ve witnessed some rare crashes due to the caching of the segments. Apparently, the class was accessed from multiple threads which led to threading issues. Removing the segments cache fixed this problem as well. --- lib/ios/AirMaps/AIRMapPolylineRenderer.m | 30 ++++++++++-------------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/lib/ios/AirMaps/AIRMapPolylineRenderer.m b/lib/ios/AirMaps/AIRMapPolylineRenderer.m index 5ac024f97..b9e8c060c 100644 --- a/lib/ios/AirMaps/AIRMapPolylineRenderer.m +++ b/lib/ios/AirMaps/AIRMapPolylineRenderer.m @@ -39,7 +39,6 @@ - (void) addPoint:(CGPoint)point color:(UIColor*)color @end @implementation AIRMapPolylineRenderer { - NSMutableArray* _segments; MKPolyline* _polyline; NSArray *_strokeColors; MKMapSnapshot* _snapshot; @@ -111,10 +110,10 @@ - (void) createPath self.path = path; } -- (void) createSegments +- (NSArray*) createSegments { - _segments = [NSMutableArray new]; - if (_polyline.pointCount <= 1) return; + NSMutableArray* segments = [NSMutableArray new]; + if (_polyline.pointCount <= 1) return segments; AIRMapPolylineRendererSegment* segment = nil; for (NSUInteger i = 0, n = _polyline.pointCount; i < n; i++){ CGPoint point = [self pointForIndex:i]; @@ -123,7 +122,7 @@ - (void) createSegments // Start new segment segment = [[AIRMapPolylineRendererSegment alloc] initWithPoint:point color:color]; - [_segments addObject:segment]; + [segments addObject:segment]; } else if (((color == nil) && (segment.endColor == nil)) || ((color != nil) && [segment.startColor isEqual:color])) { @@ -142,28 +141,29 @@ - (void) createSegments // Add transition gradient segment = [[AIRMapPolylineRendererSegment alloc] initWithPoint:segment.endPoint color:segment.endColor]; [segment addPoint:point color:color]; - [_segments addObject:segment]; + [segments addObject:segment]; } // Start new segment if (i < (n - 1)) { segment = [[AIRMapPolylineRendererSegment alloc] initWithPoint:point color:color]; - [_segments addObject:segment]; + [segments addObject:segment]; } } } - // Close last segment in case this was forgotten + // Remove last segment in case it only contains a single path point if ((segment != nil) && (segment.endColor == nil)) { - segment.endColor = segment.startColor; + [segments removeLastObject]; } + + return segments; } - (void) setStrokeColors:(NSArray *)strokeColors { if (_strokeColors != strokeColors) { _strokeColors = strokeColors; - _segments = nil; } } @@ -171,7 +171,6 @@ - (void) setStrokeColor:(UIColor *)strokeColor { if (super.strokeColor != strokeColor) { super.strokeColor = strokeColor; - _segments = nil; } } @@ -198,12 +197,9 @@ - (void) drawWithZoomScale:(MKZoomScale)zoomScale inContext:(CGContextRef)contex } CGContextSetLineDash(context, self.lineDashPhase, dashes, self.lineDashPattern.count); - if (_segments == nil) { - [self createSegments]; - } - - for (NSUInteger i = 0, n = _segments.count; i < n; i++) { - AIRMapPolylineRendererSegment* segment = _segments[i]; + NSArray* segments = [self createSegments]; + for (NSUInteger i = 0, n = segments.count; i < n; i++) { + AIRMapPolylineRendererSegment* segment = segments[i]; CGContextBeginPath(context); CGContextAddPath(context, segment.path); From 6c23a8aed08bbb7acb8e628d53e7e828f3b7d976 Mon Sep 17 00:00:00 2001 From: Iftekhar Rifat Date: Thu, 18 Jan 2018 18:30:17 +0600 Subject: [PATCH 0394/1148] iOS google map fixes (#1953) * iOS: Google map fixes - - Fix onMapReady not getting called after first time - Fix initialRegion lat/lng delta not setting properly * iOSGoogleMap: do not allow setRegion method to be called if map is not ready * iOSGoogleMap: Prevent didChangeCameraPosition & idleAtCameraPosition event until initialRegion or region is set. * iOSGoogleMap: fix flickeing issue on setting initialRegion Also preserve ios behavior for map ready state credits @danielgindi * Emit region change events even if user does not provide initialRegion or region --- lib/ios/AirGoogleMaps/AIRGoogleMap.m | 37 ++++++++++++++++++--- lib/ios/AirGoogleMaps/AIRGoogleMapManager.m | 22 +++++------- 2 files changed, 40 insertions(+), 19 deletions(-) diff --git a/lib/ios/AirGoogleMaps/AIRGoogleMap.m b/lib/ios/AirGoogleMaps/AIRGoogleMap.m index c7c57663e..81ab5c4d0 100644 --- a/lib/ios/AirGoogleMaps/AIRGoogleMap.m +++ b/lib/ios/AirGoogleMaps/AIRGoogleMap.m @@ -34,7 +34,11 @@ - (id)eventFromCoordinate:(CLLocationCoordinate2D)coordinate; @implementation AIRGoogleMap { NSMutableArray *_reactSubviews; - BOOL _initialRegionSet; + MKCoordinateRegion _initialRegion; + MKCoordinateRegion _region; + BOOL _initialRegionSetOnLoad; + BOOL _didCallOnMapReady; + BOOL _didMoveToWindow; } - (instancetype)init @@ -46,7 +50,11 @@ - (instancetype)init _polylines = [NSMutableArray array]; _circles = [NSMutableArray array]; _tiles = [NSMutableArray array]; - _initialRegionSet = false; + _initialRegion = MKCoordinateRegionMake(CLLocationCoordinate2DMake(0.0, 0.0), MKCoordinateSpanMake(0.0, 0.0)); + _region = MKCoordinateRegionMake(CLLocationCoordinate2DMake(0.0, 0.0), MKCoordinateSpanMake(0.0, 0.0)); + _initialRegionSetOnLoad = false; + _didCallOnMapReady = false; + _didMoveToWindow = false; } return self; } @@ -144,19 +152,38 @@ - (void)removeReactSubview:(id)subview { } #pragma clang diagnostic pop +- (void)didMoveToWindow { + if (_didMoveToWindow) return; + _didMoveToWindow = true; + + if (_initialRegion.span.latitudeDelta != 0.0 && + _initialRegion.span.longitudeDelta != 0.0) { + self.camera = [AIRGoogleMap makeGMSCameraPositionFromMap:self andMKCoordinateRegion:_initialRegion]; + } else if (_region.span.latitudeDelta != 0.0 && + _region.span.longitudeDelta != 0.0) { + self.camera = [AIRGoogleMap makeGMSCameraPositionFromMap:self andMKCoordinateRegion:_region]; + } + + [super didMoveToWindow]; +} + - (void)setInitialRegion:(MKCoordinateRegion)initialRegion { - if (_initialRegionSet) return; - _initialRegionSet = true; + if (_initialRegionSetOnLoad) return; + _initialRegion = initialRegion; + _initialRegionSetOnLoad = true; self.camera = [AIRGoogleMap makeGMSCameraPositionFromMap:self andMKCoordinateRegion:initialRegion]; } - (void)setRegion:(MKCoordinateRegion)region { // TODO: The JS component is repeatedly setting region unnecessarily. We might want to deal with that in here. + _region = region; self.camera = [AIRGoogleMap makeGMSCameraPositionFromMap:self andMKCoordinateRegion:region]; } - (void)didPrepareMap { - if (self.onMapReady) self.onMapReady(@{}); + if (_didCallOnMapReady) return; + _didCallOnMapReady = true; + if (self.onMapReady) self.onMapReady(@{}); } - (BOOL)didTapMarker:(GMSMarker *)marker { diff --git a/lib/ios/AirGoogleMaps/AIRGoogleMapManager.m b/lib/ios/AirGoogleMaps/AIRGoogleMapManager.m index ba2077c96..f0f78a870 100644 --- a/lib/ios/AirGoogleMaps/AIRGoogleMapManager.m +++ b/lib/ios/AirGoogleMaps/AIRGoogleMapManager.m @@ -32,10 +32,7 @@ @interface AIRGoogleMapManager() -{ - BOOL didCallOnMapReady; -} - + @end @implementation AIRGoogleMapManager @@ -247,22 +244,22 @@ - (UIView *)view RCTLogError(@"Invalid view returned from registry, expecting AIRMap, got: %@", view); } else { AIRGoogleMap *mapView = (AIRGoogleMap *)view; - + // TODO: currently we are ignoring width, height, region - + UIGraphicsBeginImageContextWithOptions(mapView.frame.size, YES, 0.0f); [mapView.layer renderInContext:UIGraphicsGetCurrentContext()]; UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); - + NSData *data; if ([format isEqualToString:@"png"]) { data = UIImagePNGRepresentation(image); - + } else if([format isEqualToString:@"jpg"]) { data = UIImageJPEGRepresentation(image, quality.floatValue); } - + if ([result isEqualToString:@"file"]) { [data writeToFile:filePath atomically:YES]; callback(@[[NSNull null], filePath]); @@ -271,7 +268,7 @@ - (UIView *)view callback(@[[NSNull null], [data base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithCarriageReturn]]); } else if ([result isEqualToString:@"legacy"]) { - + // In the initial (iOS only) implementation of takeSnapshot, // both the uri and the base64 encoded string were returned. // Returning both is rarely useful and in fact causes a @@ -288,7 +285,7 @@ - (UIView *)view }; callback(@[[NSNull null], snapshotData]); } - + } UIGraphicsEndImageContext(); }]; @@ -374,9 +371,6 @@ - (NSDictionary *)constantsToExport { } - (void)mapViewDidStartTileRendering:(GMSMapView *)mapView { - if (didCallOnMapReady) return; - didCallOnMapReady = YES; - AIRGoogleMap *googleMapView = (AIRGoogleMap *)mapView; [googleMapView didPrepareMap]; } From eab6ff559992950718a008bb6b0a4d3212b741d1 Mon Sep 17 00:00:00 2001 From: Lee Jeo Date: Fri, 19 Jan 2018 21:43:13 +0900 Subject: [PATCH 0395/1148] Android polygon holes support (#1781) --- docs/polygon.md | 1 + .../android/react/maps/AirMapPolygon.java | 40 +++++++++++++++++++ .../react/maps/AirMapPolygonManager.java | 5 +++ 3 files changed, 46 insertions(+) diff --git a/docs/polygon.md b/docs/polygon.md index f13f50755..fb5b25beb 100644 --- a/docs/polygon.md +++ b/docs/polygon.md @@ -5,6 +5,7 @@ | Prop | Type | Default | Note | |---|---|---|---| | `coordinates` | `Array` | (Required) | An array of coordinates to describe the polygon +| `holes` | `Array>` | | A 2d array of coordinates to describe holes of the polygon where each hole has at least 3 points. | `strokeWidth` | `Number` | `1` | The stroke width to use for the path. | `strokeColor` | `String` | `#000`, `rgba(r,g,b,0.5)` | The stroke color to use for the path. | `fillColor` | `String` | `#000`, `rgba(r,g,b,0.5)` | The fill color to use for the path. diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapPolygon.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapPolygon.java index 41257b32e..5f2729378 100644 --- a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapPolygon.java +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapPolygon.java @@ -18,6 +18,7 @@ public class AirMapPolygon extends AirMapFeature { private Polygon polygon; private List coordinates; + private List> holes; private int strokeColor; private int fillColor; private float strokeWidth; @@ -41,6 +42,38 @@ public void setCoordinates(ReadableArray coordinates) { } } + public void setHoles(ReadableArray holes) { + if (holes == null) { return; } + + this.holes = new ArrayList<>(holes.size()); + + for (int i = 0; i < holes.size(); i++) { + ReadableArray hole = holes.getArray(i); + + if (hole.size() < 3) { continue; } + + List coordinates = new ArrayList<>(); + for (int j = 0; j < hole.size(); j++) { + ReadableMap coordinate = hole.getMap(j); + coordinates.add(new LatLng( + coordinate.getDouble("latitude"), + coordinate.getDouble("longitude"))); + } + + // If hole is triangle + if (coordinates.size() == 3) { + coordinates.add(coordinates.get(0)); + } + + this.holes.add(coordinates); + } + + if (polygon != null) { + polygon.setHoles(this.holes); + } + } + + public void setFillColor(int color) { this.fillColor = color; if (polygon != null) { @@ -91,6 +124,13 @@ private PolygonOptions createPolygonOptions() { options.strokeWidth(strokeWidth); options.geodesic(geodesic); options.zIndex(zIndex); + + if (this.holes != null) { + for (int i = 0; i < holes.size(); i++) { + options.addHole(holes.get(i)); + } + } + return options; } diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapPolygonManager.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapPolygonManager.java index 6f1605758..0f0378026 100644 --- a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapPolygonManager.java +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapPolygonManager.java @@ -47,6 +47,11 @@ public void setCoordinate(AirMapPolygon view, ReadableArray coordinates) { view.setCoordinates(coordinates); } + @ReactProp(name = "holes") + public void setHoles(AirMapPolygon view, ReadableArray holes) { + view.setHoles(holes); + } + @ReactProp(name = "strokeWidth", defaultFloat = 1f) public void setStrokeWidth(AirMapPolygon view, float widthInPoints) { float widthInScreenPx = metrics.density * widthInPoints; // done for parity with iOS From 9f3c5f6e8be3f95335de20fda073d3edceb2c850 Mon Sep 17 00:00:00 2001 From: Daniel Playfair Cal Date: Sun, 21 Jan 2018 18:57:00 +1100 Subject: [PATCH 0396/1148] Switch to using es6 exports --- docs/installation.md | 2 +- example/App.js | 2 +- example/examples/AnimatedMarkers.js | 2 +- example/examples/AnimatedPriceMarker.js | 2 +- example/examples/AnimatedViews.js | 2 +- example/examples/BugMarkerWontUpdate.js | 2 +- example/examples/CachedMap.js | 2 +- example/examples/Callouts.js | 2 +- example/examples/CustomCallout.js | 2 +- example/examples/CustomMarkers.js | 2 +- example/examples/CustomOverlay.js | 2 +- example/examples/CustomTiles.js | 2 +- example/examples/CustomTilesLocal.js | 2 +- example/examples/DefaultMarkers.js | 2 +- example/examples/DisplayLatLng.js | 2 +- example/examples/DraggableMarkers.js | 2 +- example/examples/EventListener.js | 2 +- example/examples/FitToCoordinates.js | 2 +- example/examples/FitToSuppliedMarkers.js | 2 +- example/examples/GradientPolylines.js | 2 +- example/examples/LegalLabel.js | 2 +- example/examples/LiteMapView.js | 2 +- example/examples/LoadingMap.js | 2 +- example/examples/MapStyle.js | 2 +- example/examples/MarkerTypes.js | 2 +- example/examples/Overlays.js | 2 +- example/examples/PanController.js | 2 +- example/examples/PolygonCreator.js | 2 +- example/examples/PolylineCreator.js | 2 +- example/examples/PriceMarker.js | 2 +- example/examples/SetNativePropsOverlays.js | 2 +- example/examples/StaticMap.js | 2 +- example/examples/TakeSnapshot.js | 2 +- example/examples/ViewsAsMarkers.js | 2 +- example/examples/ZIndexMarkers.js | 2 +- index.js | 13 ++++++++++++- lib/components/MapCallout.js | 2 +- lib/components/MapCircle.js | 2 +- lib/components/MapLocalTile.js | 2 +- lib/components/MapMarker.js | 2 +- lib/components/MapOverlay.js | 2 +- lib/components/MapPolygon.js | 2 +- lib/components/MapPolyline.js | 2 +- lib/components/MapUrlTile.js | 2 +- lib/components/MapView.js | 14 +++++++++----- 45 files changed, 64 insertions(+), 49 deletions(-) diff --git a/docs/installation.md b/docs/installation.md index cd4041de1..4971925a8 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -214,7 +214,7 @@ If you use Xcode with version less than 9 you may get `use of undeclared identif }, }); - module.exports = class MyApp extends React.Component { + export default class MyApp extends React.Component { render() { const { region } = this.props; console.log(region); diff --git a/example/App.js b/example/App.js index cddb5b7dc..71c77d9fd 100644 --- a/example/App.js +++ b/example/App.js @@ -191,4 +191,4 @@ const styles = StyleSheet.create({ }, }); -module.exports = App; +export default App; diff --git a/example/examples/AnimatedMarkers.js b/example/examples/AnimatedMarkers.js index 31cfafac4..6684ff4d7 100644 --- a/example/examples/AnimatedMarkers.js +++ b/example/examples/AnimatedMarkers.js @@ -104,4 +104,4 @@ const styles = StyleSheet.create({ }, }); -module.exports = AnimatedMarkers; +export default AnimatedMarkers; diff --git a/example/examples/AnimatedPriceMarker.js b/example/examples/AnimatedPriceMarker.js index 2d876c0ae..edcda94ef 100644 --- a/example/examples/AnimatedPriceMarker.js +++ b/example/examples/AnimatedPriceMarker.js @@ -105,4 +105,4 @@ const styles = StyleSheet.create({ }, }); -module.exports = AnimatedPriceMarker; +export default AnimatedPriceMarker; diff --git a/example/examples/AnimatedViews.js b/example/examples/AnimatedViews.js index 884f11a37..9ec19b775 100644 --- a/example/examples/AnimatedViews.js +++ b/example/examples/AnimatedViews.js @@ -418,4 +418,4 @@ const styles = StyleSheet.create({ }, }); -module.exports = AnimatedViews; +export default AnimatedViews; diff --git a/example/examples/BugMarkerWontUpdate.js b/example/examples/BugMarkerWontUpdate.js index 8bf62ffca..c75d2dfcf 100644 --- a/example/examples/BugMarkerWontUpdate.js +++ b/example/examples/BugMarkerWontUpdate.js @@ -131,4 +131,4 @@ const styles = StyleSheet.create({ }, }); -module.exports = BugMarkerWontUpdate; +export default BugMarkerWontUpdate; diff --git a/example/examples/CachedMap.js b/example/examples/CachedMap.js index 296e042d6..0afc634e7 100644 --- a/example/examples/CachedMap.js +++ b/example/examples/CachedMap.js @@ -1832,4 +1832,4 @@ const COUNTRIES = [ }, ]; -module.exports = CachedMap; +export default CachedMap; diff --git a/example/examples/Callouts.js b/example/examples/Callouts.js index 5d14619dc..590029fd5 100644 --- a/example/examples/Callouts.js +++ b/example/examples/Callouts.js @@ -159,4 +159,4 @@ const styles = StyleSheet.create({ }, }); -module.exports = Callouts; +export default Callouts; diff --git a/example/examples/CustomCallout.js b/example/examples/CustomCallout.js index 55cb9eb0f..844252cc2 100644 --- a/example/examples/CustomCallout.js +++ b/example/examples/CustomCallout.js @@ -66,4 +66,4 @@ const styles = StyleSheet.create({ }, }); -module.exports = CustomCallout; +export default CustomCallout; diff --git a/example/examples/CustomMarkers.js b/example/examples/CustomMarkers.js index 5c5330263..7aafcdf5d 100644 --- a/example/examples/CustomMarkers.js +++ b/example/examples/CustomMarkers.js @@ -115,4 +115,4 @@ const styles = StyleSheet.create({ }, }); -module.exports = CustomMarkers; +export default CustomMarkers; diff --git a/example/examples/CustomOverlay.js b/example/examples/CustomOverlay.js index c57f83ff7..894448de5 100644 --- a/example/examples/CustomOverlay.js +++ b/example/examples/CustomOverlay.js @@ -82,4 +82,4 @@ const styles = StyleSheet.create({ }, }); -module.exports = CustomOverlay; +export default CustomOverlay; diff --git a/example/examples/CustomTiles.js b/example/examples/CustomTiles.js index 3d6e11d7f..70982f906 100644 --- a/example/examples/CustomTiles.js +++ b/example/examples/CustomTiles.js @@ -106,4 +106,4 @@ const styles = StyleSheet.create({ }, }); -module.exports = CustomTiles; +export default CustomTiles; diff --git a/example/examples/CustomTilesLocal.js b/example/examples/CustomTilesLocal.js index fa5173ac1..addcd0e53 100644 --- a/example/examples/CustomTilesLocal.js +++ b/example/examples/CustomTilesLocal.js @@ -107,4 +107,4 @@ const styles = StyleSheet.create({ }, }); -module.exports = CustomTiles; +export default CustomTiles; diff --git a/example/examples/DefaultMarkers.js b/example/examples/DefaultMarkers.js index 67768d07b..d868c3e37 100644 --- a/example/examples/DefaultMarkers.js +++ b/example/examples/DefaultMarkers.js @@ -116,4 +116,4 @@ const styles = StyleSheet.create({ }, }); -module.exports = DefaultMarkers; +export default DefaultMarkers; diff --git a/example/examples/DisplayLatLng.js b/example/examples/DisplayLatLng.js index 688427b35..b17a78b28 100644 --- a/example/examples/DisplayLatLng.js +++ b/example/examples/DisplayLatLng.js @@ -168,4 +168,4 @@ const styles = StyleSheet.create({ }, }); -module.exports = DisplayLatLng; +export default DisplayLatLng; diff --git a/example/examples/DraggableMarkers.js b/example/examples/DraggableMarkers.js index 17ec862e2..383e4fd55 100644 --- a/example/examples/DraggableMarkers.js +++ b/example/examples/DraggableMarkers.js @@ -91,4 +91,4 @@ const styles = StyleSheet.create({ }, }); -module.exports = MarkerTypes; +export default MarkerTypes; diff --git a/example/examples/EventListener.js b/example/examples/EventListener.js index 459f087b5..96ff1081f 100644 --- a/example/examples/EventListener.js +++ b/example/examples/EventListener.js @@ -231,4 +231,4 @@ const styles = StyleSheet.create({ }, }); -module.exports = EventListener; +export default EventListener; diff --git a/example/examples/FitToCoordinates.js b/example/examples/FitToCoordinates.js index c6c42ad4e..f347cdfbd 100644 --- a/example/examples/FitToCoordinates.js +++ b/example/examples/FitToCoordinates.js @@ -129,4 +129,4 @@ const styles = StyleSheet.create({ }, }); -module.exports = FitToCoordinates; +export default FitToCoordinates; diff --git a/example/examples/FitToSuppliedMarkers.js b/example/examples/FitToSuppliedMarkers.js index 786763990..5d54e0506 100644 --- a/example/examples/FitToSuppliedMarkers.js +++ b/example/examples/FitToSuppliedMarkers.js @@ -164,4 +164,4 @@ const styles = StyleSheet.create({ }, }); -module.exports = FocusOnMarkers; +export default FocusOnMarkers; diff --git a/example/examples/GradientPolylines.js b/example/examples/GradientPolylines.js index ca89ff2b0..0fe668a66 100644 --- a/example/examples/GradientPolylines.js +++ b/example/examples/GradientPolylines.js @@ -74,4 +74,4 @@ const styles = StyleSheet.create({ }, }); -module.exports = GradientPolylines; +export default GradientPolylines; diff --git a/example/examples/LegalLabel.js b/example/examples/LegalLabel.js index 6d5894c85..17cbcc7eb 100644 --- a/example/examples/LegalLabel.js +++ b/example/examples/LegalLabel.js @@ -144,4 +144,4 @@ const styles = StyleSheet.create({ }, }); -module.exports = LegalLabel; +export default LegalLabel; diff --git a/example/examples/LiteMapView.js b/example/examples/LiteMapView.js index 7f65fb6c9..56f3079e6 100644 --- a/example/examples/LiteMapView.js +++ b/example/examples/LiteMapView.js @@ -50,4 +50,4 @@ const styles = StyleSheet.create({ }, }); -module.exports = LiteMapView; +export default LiteMapView; diff --git a/example/examples/LoadingMap.js b/example/examples/LoadingMap.js index 2b2ea8970..7edfa100c 100644 --- a/example/examples/LoadingMap.js +++ b/example/examples/LoadingMap.js @@ -104,4 +104,4 @@ const styles = StyleSheet.create({ }, }); -module.exports = LoadingMap; +export default LoadingMap; diff --git a/example/examples/MapStyle.js b/example/examples/MapStyle.js index 5d3416c93..e7704f78a 100644 --- a/example/examples/MapStyle.js +++ b/example/examples/MapStyle.js @@ -219,4 +219,4 @@ const styles = StyleSheet.create({ }, }); -module.exports = MapStyle; +export default MapStyle; diff --git a/example/examples/MarkerTypes.js b/example/examples/MarkerTypes.js index 76685d782..d533c5ad2 100644 --- a/example/examples/MarkerTypes.js +++ b/example/examples/MarkerTypes.js @@ -99,4 +99,4 @@ const styles = StyleSheet.create({ }, }); -module.exports = MarkerTypes; +export default MarkerTypes; diff --git a/example/examples/Overlays.js b/example/examples/Overlays.js index 17a976014..940570b3b 100644 --- a/example/examples/Overlays.js +++ b/example/examples/Overlays.js @@ -147,4 +147,4 @@ const styles = StyleSheet.create({ }, }); -module.exports = Overlays; +export default Overlays; diff --git a/example/examples/PanController.js b/example/examples/PanController.js index ac8e4a119..97c41f642 100644 --- a/example/examples/PanController.js +++ b/example/examples/PanController.js @@ -413,4 +413,4 @@ class PanController extends React.Component{ } }; -module.exports = PanController; +export default PanController; diff --git a/example/examples/PolygonCreator.js b/example/examples/PolygonCreator.js index c0d1e44f5..5921c0def 100644 --- a/example/examples/PolygonCreator.js +++ b/example/examples/PolygonCreator.js @@ -211,4 +211,4 @@ const styles = StyleSheet.create({ }, }); -module.exports = PolygonCreator; +export default PolygonCreator; diff --git a/example/examples/PolylineCreator.js b/example/examples/PolylineCreator.js index f3fbcd4a6..026a5dcec 100644 --- a/example/examples/PolylineCreator.js +++ b/example/examples/PolylineCreator.js @@ -144,4 +144,4 @@ const styles = StyleSheet.create({ }, }); -module.exports = PolylineCreator; +export default PolylineCreator; diff --git a/example/examples/PriceMarker.js b/example/examples/PriceMarker.js index a1b1591d7..e78cb84a0 100644 --- a/example/examples/PriceMarker.js +++ b/example/examples/PriceMarker.js @@ -76,4 +76,4 @@ const styles = StyleSheet.create({ }, }); -module.exports = PriceMarker; +export default PriceMarker; diff --git a/example/examples/SetNativePropsOverlays.js b/example/examples/SetNativePropsOverlays.js index b0dac9a80..a5ba8f928 100644 --- a/example/examples/SetNativePropsOverlays.js +++ b/example/examples/SetNativePropsOverlays.js @@ -159,4 +159,4 @@ const styles = StyleSheet.create({ }, }); -module.exports = SetNativePropsOverlays; +export default SetNativePropsOverlays; diff --git a/example/examples/StaticMap.js b/example/examples/StaticMap.js index 02a74f348..762b84e88 100644 --- a/example/examples/StaticMap.js +++ b/example/examples/StaticMap.js @@ -115,4 +115,4 @@ const styles = StyleSheet.create({ }, }); -module.exports = StaticMap; +export default StaticMap; diff --git a/example/examples/TakeSnapshot.js b/example/examples/TakeSnapshot.js index 26022a4d5..029511393 100644 --- a/example/examples/TakeSnapshot.js +++ b/example/examples/TakeSnapshot.js @@ -135,4 +135,4 @@ const styles = StyleSheet.create({ }, }); -module.exports = MarkerTypes; +export default MarkerTypes; diff --git a/example/examples/ViewsAsMarkers.js b/example/examples/ViewsAsMarkers.js index 610699883..bbea11515 100644 --- a/example/examples/ViewsAsMarkers.js +++ b/example/examples/ViewsAsMarkers.js @@ -111,4 +111,4 @@ const styles = StyleSheet.create({ }, }); -module.exports = ViewsAsMarkers; +export default ViewsAsMarkers; diff --git a/example/examples/ZIndexMarkers.js b/example/examples/ZIndexMarkers.js index 78e3063d2..59e862a28 100644 --- a/example/examples/ZIndexMarkers.js +++ b/example/examples/ZIndexMarkers.js @@ -97,4 +97,4 @@ const styles = StyleSheet.create({ }, }); -module.exports = ZIndexMarkers; +export default ZIndexMarkers; diff --git a/index.js b/index.js index 207d0119d..edc3b3c50 100644 --- a/index.js +++ b/index.js @@ -1,3 +1,14 @@ import MapView from './lib/components/MapView'; -module.exports = MapView; +export { default as Marker } from './lib/components/MapMarker.js'; +export { default as Polyline } from './lib/components/MapPolyline.js'; +export { default as Polygon } from './lib/components/MapPolygon.js'; +export { default as Circle } from './lib/components/MapCircle.js'; +export { default as UrlTile } from './lib/components/MapUrlTile.js'; +export { default as LocalTile } from './lib/components/MapLocalTile.js'; +export { default as Overlay } from './lib/components/MapOverlay.js'; +export { default as Callout } from './lib/components/MapCallout.js'; +export { default as AnimatedRegion } from './lib/components/AnimatedRegion.js'; +export { Animated, ProviderPropType, MAP_TYPES } from './lib/components/MapView.js'; + +export default MapView; diff --git a/lib/components/MapCallout.js b/lib/components/MapCallout.js index 2ef73a096..5d677e27c 100644 --- a/lib/components/MapCallout.js +++ b/lib/components/MapCallout.js @@ -39,7 +39,7 @@ const styles = StyleSheet.create({ }, }); -module.exports = decorateMapComponent(MapCallout, { +export default decorateMapComponent(MapCallout, { componentType: 'Callout', providers: { google: { diff --git a/lib/components/MapCircle.js b/lib/components/MapCircle.js index c0c23a5ad..7163128ea 100644 --- a/lib/components/MapCircle.js +++ b/lib/components/MapCircle.js @@ -145,7 +145,7 @@ class MapCircle extends React.Component { MapCircle.propTypes = propTypes; MapCircle.defaultProps = defaultProps; -module.exports = decorateMapComponent(MapCircle, { +export default decorateMapComponent(MapCircle, { componentType: 'Circle', providers: { google: { diff --git a/lib/components/MapLocalTile.js b/lib/components/MapLocalTile.js index 508da5676..8548c6592 100644 --- a/lib/components/MapLocalTile.js +++ b/lib/components/MapLocalTile.js @@ -52,7 +52,7 @@ class MapLocalTile extends React.Component { MapLocalTile.propTypes = propTypes; -module.exports = decorateMapComponent(MapLocalTile, { +export default decorateMapComponent(MapLocalTile, { componentType: 'LocalTile', providers: { google: { diff --git a/lib/components/MapMarker.js b/lib/components/MapMarker.js index 7d906f6b6..1a8b294a8 100644 --- a/lib/components/MapMarker.js +++ b/lib/components/MapMarker.js @@ -308,7 +308,7 @@ const styles = StyleSheet.create({ MapMarker.Animated = Animated.createAnimatedComponent(MapMarker); -module.exports = decorateMapComponent(MapMarker, { +export default decorateMapComponent(MapMarker, { componentType: 'Marker', providers: { google: { diff --git a/lib/components/MapOverlay.js b/lib/components/MapOverlay.js index 93215212a..0d756d085 100644 --- a/lib/components/MapOverlay.js +++ b/lib/components/MapOverlay.js @@ -60,7 +60,7 @@ const styles = StyleSheet.create({ MapOverlay.Animated = Animated.createAnimatedComponent(MapOverlay); -module.exports = decorateMapComponent(MapOverlay, { +export default decorateMapComponent(MapOverlay, { componentType: 'Overlay', providers: { google: { diff --git a/lib/components/MapPolygon.js b/lib/components/MapPolygon.js index c6daeae86..a57e62b2b 100644 --- a/lib/components/MapPolygon.js +++ b/lib/components/MapPolygon.js @@ -166,7 +166,7 @@ class MapPolygon extends React.Component { MapPolygon.propTypes = propTypes; MapPolygon.defaultProps = defaultProps; -module.exports = decorateMapComponent(MapPolygon, { +export default decorateMapComponent(MapPolygon, { componentType: 'Polygon', providers: { google: { diff --git a/lib/components/MapPolyline.js b/lib/components/MapPolyline.js index bba6c932b..4351aa8c5 100644 --- a/lib/components/MapPolyline.js +++ b/lib/components/MapPolyline.js @@ -162,7 +162,7 @@ class MapPolyline extends React.Component { MapPolyline.propTypes = propTypes; MapPolyline.defaultProps = defaultProps; -module.exports = decorateMapComponent(MapPolyline, { +export default decorateMapComponent(MapPolyline, { componentType: 'Polyline', providers: { google: { diff --git a/lib/components/MapUrlTile.js b/lib/components/MapUrlTile.js index a2b49e960..38672d3b4 100644 --- a/lib/components/MapUrlTile.js +++ b/lib/components/MapUrlTile.js @@ -46,7 +46,7 @@ class MapUrlTile extends React.Component { MapUrlTile.propTypes = propTypes; -module.exports = decorateMapComponent(MapUrlTile, { +export default decorateMapComponent(MapUrlTile, { componentType: 'UrlTile', providers: { google: { diff --git a/lib/components/MapView.js b/lib/components/MapView.js index b28054291..73ef7e38f 100644 --- a/lib/components/MapView.js +++ b/lib/components/MapView.js @@ -3,7 +3,7 @@ import React from 'react'; import { EdgeInsetsPropType, Platform, - Animated, + Animated as RNAnimated, requireNativeComponent, NativeModules, ColorPropType, @@ -28,7 +28,7 @@ import { } from './decorateMapComponent'; import * as ProviderConstants from './ProviderConstants'; -const MAP_TYPES = { +export const MAP_TYPES = { STANDARD: 'standard', SATELLITE: 'satellite', HYBRID: 'hybrid', @@ -802,6 +802,10 @@ const AIRMapLite = NativeModules.UIManager.AIRMapLite && }, }); +export const Animated = RNAnimated.createAnimatedComponent(MapView); + +export const ProviderPropType = PropTypes.oneOf(Object.values(ProviderConstants)); + MapView.Marker = MapMarker; MapView.Polyline = MapPolyline; MapView.Polygon = MapPolygon; @@ -811,9 +815,9 @@ MapView.LocalTile = MapLocalTile; MapView.Overlay = MapOverlay; MapView.Callout = MapCallout; Object.assign(MapView, ProviderConstants); -MapView.ProviderPropType = PropTypes.oneOf(Object.values(ProviderConstants)); +MapView.ProviderPropType = ProviderPropType; -MapView.Animated = Animated.createAnimatedComponent(MapView); +MapView.Animated = Animated; MapView.AnimatedRegion = AnimatedRegion; -module.exports = MapView; +export default MapView; From 89832a46dae1270a4b28aaea520b99422fe8c483 Mon Sep 17 00:00:00 2001 From: Daniel Playfair Cal Date: Sun, 21 Jan 2018 19:25:57 +1100 Subject: [PATCH 0397/1148] Make babel-plugin-module-resolver and babel-preset-react-native runtime dependencies --- package.json | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 87b595397..1cd80bc4f 100644 --- a/package.json +++ b/package.json @@ -13,8 +13,7 @@ "lint": "eslint ./", "build": "npm run build:js && npm run build:android && npm run build:ios", "build:js": "exit 0", - "build:ios": - "bundle install --binstubs ./examples/ios && bundle exec pod install --project-directory=./example/ios/", + "build:ios": "bundle install --binstubs ./examples/ios && bundle exec pod install --project-directory=./example/ios/", "build:android": "./gradlew :react-native-maps:assembleDebug", "ci": "npm run lint", "preversion": "./scripts/update-version.js" @@ -39,9 +38,7 @@ }, "devDependencies": { "babel-eslint": "^6.1.2", - "babel-plugin-module-resolver": "^2.3.0", "babel-preset-airbnb": "^1.1.1", - "babel-preset-react-native": "1.9.0", "eslint": "^3.3.1", "eslint-config-airbnb": "^10.0.1", "eslint-plugin-import": "^1.14.0", @@ -58,5 +55,9 @@ "android": { "sourceDir": "./lib/android" } + }, + "dependencies": { + "babel-plugin-module-resolver": "^2.7.1", + "babel-preset-react-native": "^1.9.0" } } From dc6bbb7acc1a176aa3ab68b59383dfb50128589d Mon Sep 17 00:00:00 2001 From: Daniel Playfair Cal Date: Sun, 21 Jan 2018 19:29:28 +1100 Subject: [PATCH 0398/1148] Don't change npm dependency versions --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 1cd80bc4f..bcfc2b0d9 100644 --- a/package.json +++ b/package.json @@ -57,7 +57,7 @@ } }, "dependencies": { - "babel-plugin-module-resolver": "^2.7.1", - "babel-preset-react-native": "^1.9.0" + "babel-plugin-module-resolver": "^2.3.0", + "babel-preset-react-native": "1.9.0" } } From 100c50aa054c3a6b67a3104fab037feba4a987fb Mon Sep 17 00:00:00 2001 From: Daniel Playfair Cal Date: Mon, 22 Jan 2018 09:41:27 +1100 Subject: [PATCH 0399/1148] Update examples and documentation to use new es6 exports --- README.md | 60 +++++++++++-------- docs/callout.md | 2 +- docs/circle.md | 2 +- docs/marker.md | 6 +- docs/overlay.md | 2 +- docs/polygon.md | 2 +- docs/polyline.md | 6 +- example/examples/AnimatedMarkers.js | 8 +-- example/examples/AnimatedViews.js | 19 +++--- example/examples/BugMarkerWontUpdate.js | 4 +- example/examples/CachedMap.js | 6 +- example/examples/Callouts.js | 22 +++---- example/examples/CustomMarkers.js | 6 +- example/examples/CustomOverlay.js | 4 +- .../examples/CustomOverlayXMarksTheSpot.js | 10 ++-- example/examples/CustomTiles.js | 6 +- example/examples/CustomTilesLocal.js | 11 +++- example/examples/DefaultMarkers.js | 6 +- example/examples/DisplayLatLng.js | 4 +- example/examples/DraggableMarkers.js | 10 ++-- example/examples/EventListener.js | 20 +++---- example/examples/FitToCoordinates.js | 4 +- example/examples/FitToSuppliedMarkers.js | 14 ++--- example/examples/GradientPolylines.js | 6 +- example/examples/LegalLabel.js | 6 +- example/examples/LoadingMap.js | 14 ++--- example/examples/MapStyle.js | 4 +- example/examples/MarkerTypes.js | 12 ++-- example/examples/MyLocationMapMarker.js | 8 +-- example/examples/Overlays.js | 10 ++-- example/examples/PolygonCreator.js | 10 ++-- example/examples/PolylineCreator.js | 8 +-- example/examples/SetNativePropsOverlays.js | 10 ++-- example/examples/StaticMap.js | 6 +- example/examples/TakeSnapshot.js | 8 +-- example/examples/ViewsAsMarkers.js | 8 +-- example/examples/ZIndexMarkers.js | 6 +- lib/components/MapMarker.js | 4 +- 38 files changed, 189 insertions(+), 165 deletions(-) diff --git a/README.md b/README.md index 1fbb6c430..fbcbffa82 100644 --- a/README.md +++ b/README.md @@ -26,17 +26,17 @@ versions you should add `react` as a dependency in your `package.json`. [`` Component API](docs/mapview.md) -[`` Component API](docs/marker.md) +[`` Component API](docs/marker.md) -[`` Component API](docs/callout.md) +[`` Component API](docs/callout.md) -[`` Component API](docs/polygon.md) +[`` Component API](docs/polygon.md) -[`` Component API](docs/polyline.md) +[`` Component API](docs/polyline.md) -[`` Component API](docs/circle.md) +[`` Component API](docs/circle.md) -[`` Component API](docs/overlay.md) +[`` Component API](docs/overlay.md) ## General Usage @@ -98,12 +98,14 @@ render() { ### Rendering a list of markers on a map ```jsx +import { Marker } from 'react-native-maps'; + {this.state.markers.map(marker => ( - + - + ``` ### Rendering a Marker with a custom image ```jsx - @@ -132,19 +134,21 @@ render() { ### Rendering a custom Marker with a custom Callout ```jsx - +import { Callout } from 'react-native-maps'; + + - + - - +
+ ``` ### Draggable Markers ```jsx - this.setState({ x: e.nativeEvent.coordinate })} /> @@ -156,11 +160,13 @@ render() { #### Tile Overlay using tile server ```jsx +import { UrlTile } from 'react-native-maps'; + - - @@ -421,9 +429,11 @@ render() { Markers can also accept an `AnimatedRegion` value as a coordinate. ```jsx +import Mapview, { AnimatedRegion, Marker } from 'react-native-maps'; + getInitialState() { return { - coordinate: new MapView.AnimatedRegion({ + coordinate: new AnimatedRegion({ latitude: LATITUDE, longitude: LONGITUDE, }), @@ -442,7 +452,7 @@ componentWillReceiveProps(nextProps) { render() { return ( - + ); } @@ -451,6 +461,8 @@ render() { ### Take Snapshot of map ```jsx +import MapView, { Marker } from 'react-native-maps'; + getInitialState() { return { coordinate: { @@ -480,7 +492,7 @@ render() { return ( { this.map = map }}> - + diff --git a/docs/callout.md b/docs/callout.md index 58b59a6bd..9a3eb5543 100644 --- a/docs/callout.md +++ b/docs/callout.md @@ -1,4 +1,4 @@ -# `` Component API +# `` Component API ## Props diff --git a/docs/circle.md b/docs/circle.md index 992ac4567..d00d6f4d9 100644 --- a/docs/circle.md +++ b/docs/circle.md @@ -1,4 +1,4 @@ -# `` Component API +# `` Component API ## Props diff --git a/docs/marker.md b/docs/marker.md index 97f79ab79..2671add03 100644 --- a/docs/marker.md +++ b/docs/marker.md @@ -1,11 +1,11 @@ -# `` Component API +# `` Component API ## Props | Prop | Type | Default | Note | |---|---|---|---| -| `title` | `String` | | The title of the marker. This is only used if the component has no children that are an ``, in which case the default callout behavior will be used, which will show both the `title` and the `description`, if provided. -| `description` | `String` | | The description of the marker. This is only used if the component has no children that are an ``, in which case the default callout behavior will be used, which will show both the `title` and the `description`, if provided. +| `title` | `String` | | The title of the marker. This is only used if the component has no children that are a ``, in which case the default callout behavior will be used, which will show both the `title` and the `description`, if provided. +| `description` | `String` | | The description of the marker. This is only used if the component has no children that are a ``, in which case the default callout behavior will be used, which will show both the `title` and the `description`, if provided. | `image` | `ImageSource` | | A custom image to be used as the marker's icon. Only local image resources are allowed to be used. | `pinColor` | `Color` | | If no custom marker view or custom image is provided, the platform default pin will be used, which can be customized by this color. Ignored if a custom marker is being used. | `coordinate` | `LatLng` | | The coordinate for the marker. diff --git a/docs/overlay.md b/docs/overlay.md index f9a45d94f..24430b8e1 100644 --- a/docs/overlay.md +++ b/docs/overlay.md @@ -1,4 +1,4 @@ -# `` Component API +# `` Component API ## Props diff --git a/docs/polygon.md b/docs/polygon.md index f13f50755..a77cf820a 100644 --- a/docs/polygon.md +++ b/docs/polygon.md @@ -1,4 +1,4 @@ -# `` Component API +# `` Component API ## Props diff --git a/docs/polyline.md b/docs/polyline.md index 97b11f8a8..6e8aaa26e 100644 --- a/docs/polyline.md +++ b/docs/polyline.md @@ -1,4 +1,4 @@ -# `` Component API +# `` Component API ## Props @@ -37,8 +37,10 @@ Gradient polylines can be created by using the `strokeColors` prop. `strokeColor Example: ```js +import MapView, { Polyline } from 'react-native-maps'; + - - @@ -68,7 +68,7 @@ class AnimatedMarkers extends React.Component { } AnimatedMarkers.propTypes = { - provider: MapView.ProviderPropType, + provider: ProviderPropType, }; const styles = StyleSheet.create({ diff --git a/example/examples/AnimatedViews.js b/example/examples/AnimatedViews.js index 9ec19b775..a16b2f192 100644 --- a/example/examples/AnimatedViews.js +++ b/example/examples/AnimatedViews.js @@ -6,7 +6,12 @@ import { Animated, } from 'react-native'; -import MapView from 'react-native-maps'; +import { + ProviderPropType, + Animated as AnimatedMap, + AnimatedRegion, + Marker, +} from 'react-native-maps'; import PanController from './PanController'; import PriceMarker from './AnimatedPriceMarker'; @@ -191,7 +196,7 @@ class AnimatedViews extends React.Component { scale, translateY, markers, - region: new MapView.AnimatedRegion({ + region: new AnimatedRegion({ latitude: LATITUDE, longitude: LONGITUDE, latitudeDelta: LATITUDE_DELTA, @@ -324,7 +329,7 @@ class AnimatedViews extends React.Component { onStartShouldSetPanResponder={this.onStartShouldSetPanResponder} onMoveShouldSetPanResponder={this.onMoveShouldSetPanResponder} > - @@ -352,10 +357,10 @@ class AnimatedViews extends React.Component { amount={marker.amount} selected={selected} /> - + ); })} - + {markers.map((marker, i) => { const { @@ -387,7 +392,7 @@ class AnimatedViews extends React.Component { } AnimatedViews.propTypes = { - provider: MapView.ProviderPropType, + provider: ProviderPropType, }; const styles = StyleSheet.create({ diff --git a/example/examples/BugMarkerWontUpdate.js b/example/examples/BugMarkerWontUpdate.js index c75d2dfcf..8b2f697e2 100644 --- a/example/examples/BugMarkerWontUpdate.js +++ b/example/examples/BugMarkerWontUpdate.js @@ -6,7 +6,7 @@ import { Dimensions, TouchableOpacity, } from 'react-native'; -import MapView from 'react-native-maps'; +import MapView, { ProviderPropType } from 'react-native-maps'; import MyLocationMapMarker from './MyLocationMapMarker'; const { width, height } = Dimensions.get('window'); @@ -93,7 +93,7 @@ class BugMarkerWontUpdate extends React.Component { } BugMarkerWontUpdate.propTypes = { - provider: MapView.ProviderPropType, + provider: ProviderPropType, }; const styles = StyleSheet.create({ diff --git a/example/examples/CachedMap.js b/example/examples/CachedMap.js index 0afc634e7..2be98d2e4 100644 --- a/example/examples/CachedMap.js +++ b/example/examples/CachedMap.js @@ -8,7 +8,7 @@ import { TouchableOpacity, } from 'react-native'; -import MapView from 'react-native-maps'; +import MapView, { ProviderPropType, Marker } from 'react-native-maps'; import flagImg from './assets/flag-blue.png'; const HORIZONTAL_PADDING = 12; @@ -69,7 +69,7 @@ class CachedMap extends React.Component { loadingIndicatorColor="#666666" loadingBackgroundColor="#eeeeee" > - - { this.marker1 = ref; }} coordinate={markers[0].coordinate} title="This is a native view" description="Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation" // eslint-disable-line max-len /> - - + This is a plain view - - - + + - + This is a custom callout bubble view - - + + @@ -116,7 +116,7 @@ class Callouts extends React.Component { } Callouts.propTypes = { - provider: MapView.ProviderPropType, + provider: ProviderPropType, }; const styles = StyleSheet.create({ diff --git a/example/examples/CustomMarkers.js b/example/examples/CustomMarkers.js index 7aafcdf5d..4b7a8630f 100644 --- a/example/examples/CustomMarkers.js +++ b/example/examples/CustomMarkers.js @@ -7,7 +7,7 @@ import { TouchableOpacity, } from 'react-native'; -import MapView from 'react-native-maps'; +import MapView, { Marker, ProviderPropType } from 'react-native-maps'; import flagPinkImg from './assets/flag-pink.png'; const { width, height } = Dimensions.get('window'); @@ -58,7 +58,7 @@ class CustomMarkers extends React.Component { onPress={this.onMapPress} > {this.state.markers.map(marker => ( - - - - - diff --git a/example/examples/CustomTiles.js b/example/examples/CustomTiles.js index 70982f906..039b62f51 100644 --- a/example/examples/CustomTiles.js +++ b/example/examples/CustomTiles.js @@ -6,7 +6,7 @@ import { Dimensions, } from 'react-native'; -import MapView, { MAP_TYPES, PROVIDER_DEFAULT } from 'react-native-maps'; +import MapView, { MAP_TYPES, PROVIDER_DEFAULT, ProviderPropType, UrlTile } from 'react-native-maps'; const { width, height } = Dimensions.get('window'); @@ -46,7 +46,7 @@ class CustomTiles extends React.Component { style={styles.map} initialRegion={region} > - @@ -62,7 +62,7 @@ class CustomTiles extends React.Component { } CustomTiles.propTypes = { - provider: MapView.ProviderPropType, + provider: ProviderPropType, }; const styles = StyleSheet.create({ diff --git a/example/examples/CustomTilesLocal.js b/example/examples/CustomTilesLocal.js index addcd0e53..0962d1096 100644 --- a/example/examples/CustomTilesLocal.js +++ b/example/examples/CustomTilesLocal.js @@ -6,7 +6,12 @@ import { Dimensions, } from 'react-native'; -import MapView, { MAP_TYPES, PROVIDER_DEFAULT } from 'react-native-maps'; +import MapView, { + MAP_TYPES, + PROVIDER_DEFAULT, + LocalTile, + ProviderPropType, +} from 'react-native-maps'; const { width, height } = Dimensions.get('window'); @@ -46,7 +51,7 @@ class CustomTiles extends React.Component { style={styles.map} initialRegion={region} > - this.onMapPress(e)} > {this.state.markers.map(marker => ( - - log('onSelect', e)} onDrag={(e) => log('onDrag', e)} @@ -60,8 +60,8 @@ class MarkerTypes extends React.Component { draggable > - - + log('onSelect', e)} onDrag={(e) => log('onDrag', e)} @@ -77,7 +77,7 @@ class MarkerTypes extends React.Component { } MarkerTypes.propTypes = { - provider: MapView.ProviderPropType, + provider: ProviderPropType, }; const styles = StyleSheet.create({ diff --git a/example/examples/EventListener.js b/example/examples/EventListener.js index 96ff1081f..0dc2461d3 100644 --- a/example/examples/EventListener.js +++ b/example/examples/EventListener.js @@ -9,7 +9,7 @@ import { ScrollView, } from 'react-native'; // eslint-disable-next-line max-len -import MapView from 'react-native-maps'; +import MapView, { Marker, ProviderPropType, Polygon, Polyline, Callout } from 'react-native-maps'; import PriceMarker from './PriceMarker'; const { width, height } = Dimensions.get('window'); @@ -94,19 +94,19 @@ class EventListener extends React.Component { onMarkerDeselect={this.recordEvent('Map::onMarkerDeselect')} onCalloutPress={this.recordEvent('Map::onCalloutPress')} > - - - - Well hello there... - - - + + - {MARKERS.map((marker, i) => ( - diff --git a/example/examples/FitToSuppliedMarkers.js b/example/examples/FitToSuppliedMarkers.js index 5d54e0506..5ae3313a4 100644 --- a/example/examples/FitToSuppliedMarkers.js +++ b/example/examples/FitToSuppliedMarkers.js @@ -5,7 +5,7 @@ import { Dimensions, } from 'react-native'; -import MapView from 'react-native-maps'; +import MapView, { Marker, ProviderPropType } from 'react-native-maps'; const { width, height } = Dimensions.get('window'); @@ -123,23 +123,23 @@ class FocusOnMarkers extends React.Component { longitudeDelta: LONGITUDE_DELTA, }} > - - - - - @@ -150,7 +150,7 @@ class FocusOnMarkers extends React.Component { } FocusOnMarkers.propTypes = { - provider: MapView.ProviderPropType, + provider: ProviderPropType, }; const styles = StyleSheet.create({ diff --git a/example/examples/GradientPolylines.js b/example/examples/GradientPolylines.js index 0fe668a66..4ab44d26d 100644 --- a/example/examples/GradientPolylines.js +++ b/example/examples/GradientPolylines.js @@ -4,7 +4,7 @@ import { Dimensions, } from 'react-native'; -import MapView from 'react-native-maps'; +import MapView, { Polyline, ProviderPropType } from 'react-native-maps'; const { width, height } = Dimensions.get('window'); @@ -53,7 +53,7 @@ class GradientPolylines extends React.Component { style={styles.container} initialRegion={this.state.region} > - - + diff --git a/example/examples/LoadingMap.js b/example/examples/LoadingMap.js index 7edfa100c..ec0175ed4 100644 --- a/example/examples/LoadingMap.js +++ b/example/examples/LoadingMap.js @@ -6,7 +6,7 @@ import { StyleSheet, } from 'react-native'; -import MapView from 'react-native-maps'; +import MapView, { Marker, Callout, ProviderPropType } from 'react-native-maps'; import flagImg from './assets/flag-blue.png'; const { width, height } = Dimensions.get('window'); @@ -44,7 +44,7 @@ class LoadingMap extends React.Component { loadingIndicatorColor="#666666" loadingBackgroundColor="#eeeeee" > - - - + This is a plain view - - +
+ @@ -79,7 +79,7 @@ class LoadingMap extends React.Component { } LoadingMap.propTypes = { - provider: MapView.ProviderPropType, + provider: ProviderPropType, }; const styles = StyleSheet.create({ diff --git a/example/examples/MapStyle.js b/example/examples/MapStyle.js index e7704f78a..612e76640 100644 --- a/example/examples/MapStyle.js +++ b/example/examples/MapStyle.js @@ -5,7 +5,7 @@ import { Dimensions, } from 'react-native'; -import MapView from 'react-native-maps'; +import MapView, { ProviderPropType } from 'react-native-maps'; const { width, height } = Dimensions.get('window'); @@ -205,7 +205,7 @@ class MapStyle extends React.Component { } MapStyle.propTypes = { - provider: MapView.ProviderPropType, + provider: ProviderPropType, }; const styles = StyleSheet.create({ diff --git a/example/examples/MarkerTypes.js b/example/examples/MarkerTypes.js index d533c5ad2..bd9880642 100644 --- a/example/examples/MarkerTypes.js +++ b/example/examples/MarkerTypes.js @@ -5,7 +5,7 @@ import { Text, Dimensions, } from 'react-native'; -import MapView from 'react-native-maps'; +import MapView, { Marker, ProviderPropType } from 'react-native-maps'; import flagBlueImg from './assets/flag-blue.png'; import flagPinkImg from './assets/flag-pink.png'; @@ -40,7 +40,7 @@ class MarkerTypes extends React.Component { longitudeDelta: LONGITUDE_DELTA, }} > - this.setState({ marker1: !this.state.marker1 })} coordinate={{ latitude: LATITUDE + SPACE, @@ -51,8 +51,8 @@ class MarkerTypes extends React.Component { image={this.state.marker1 ? flagBlueImg : flagPinkImg} > X - - + this.setState({ marker2: !this.state.marker2 })} coordinate={{ latitude: LATITUDE - SPACE, @@ -62,7 +62,7 @@ class MarkerTypes extends React.Component { anchor={{ x: 0.84, y: 1 }} image={this.state.marker2 ? flagBlueImg : flagPinkImg} /> - this.setState({ marker2: !this.state.marker2 })} coordinate={{ latitude: LATITUDE + SPACE, @@ -80,7 +80,7 @@ class MarkerTypes extends React.Component { } MarkerTypes.propTypes = { - provider: MapView.ProviderPropType, + provider: ProviderPropType, }; const styles = StyleSheet.create({ diff --git a/example/examples/MyLocationMapMarker.js b/example/examples/MyLocationMapMarker.js index 56fc10f80..052910e10 100644 --- a/example/examples/MyLocationMapMarker.js +++ b/example/examples/MyLocationMapMarker.js @@ -8,7 +8,7 @@ import { PermissionsAndroid, Platform, } from 'react-native'; -import MapView from 'react-native-maps'; +import { Marker } from 'react-native-maps'; import isEqual from 'lodash/isEqual'; const GEOLOCATION_OPTIONS = { enableHighAccuracy: true, timeout: 20000, maximumAge: 1000 }; @@ -17,7 +17,7 @@ const ANCHOR = { x: 0.5, y: 0.5 }; const colorOfmyLocationMapMarker = 'blue'; const propTypes = { - ...MapView.Marker.propTypes, + ...Marker.propTypes, // override this prop to make it optional coordinate: PropTypes.shape({ latitude: PropTypes.number.isRequired, @@ -87,7 +87,7 @@ export default class MyLocationMapMarker extends React.PureComponent { const rotate = (typeof heading === 'number' && heading >= 0) ? `${heading}deg` : null; return ( - {this.props.children} -
+ ); } } diff --git a/example/examples/Overlays.js b/example/examples/Overlays.js index 940570b3b..95db0bb69 100644 --- a/example/examples/Overlays.js +++ b/example/examples/Overlays.js @@ -6,7 +6,7 @@ import { Dimensions, } from 'react-native'; -import MapView from 'react-native-maps'; +import MapView, { Circle, Polygon, Polyline, ProviderPropType } from 'react-native-maps'; const { width, height } = Dimensions.get('window'); @@ -79,7 +79,7 @@ class Overlays extends React.Component { style={styles.map} initialRegion={region} > - - - this.onPress(e)} {...mapOptions} > {this.state.polygons.map(polygon => ( - ))} {this.state.editing && ( - this.onPanDrag(e)} > {this.state.polylines.map(polyline => ( - ))} {this.state.editing && - - { this.circle = ref; }} center={circle.center} radius={circle.radius} @@ -96,14 +96,14 @@ class SetNativePropsOverlays extends React.Component { zIndex={3} strokeWidth={3} /> - { this.polygon = ref; }} coordinates={polygon} fillColor="rgba(255, 255, 255, 0.6)" strokeColor="green" strokeWidth={2} /> - { this.polyline = ref; }} coordinates={polyline} strokeColor="green" @@ -133,7 +133,7 @@ class SetNativePropsOverlays extends React.Component { } SetNativePropsOverlays.propTypes = { - provider: MapView.ProviderPropType, + provider: ProviderPropType, }; const styles = StyleSheet.create({ diff --git a/example/examples/StaticMap.js b/example/examples/StaticMap.js index 762b84e88..d9d66e2f8 100644 --- a/example/examples/StaticMap.js +++ b/example/examples/StaticMap.js @@ -6,7 +6,7 @@ import { Dimensions, ScrollView, } from 'react-native'; -import MapView from 'react-native-maps'; +import MapView, { Marker, ProviderPropType } from 'react-native-maps'; const { width, height } = Dimensions.get('window'); @@ -54,7 +54,7 @@ class StaticMap extends React.Component { rotateEnabled={false} initialRegion={this.state.region} > - - - - + - + - component has no children that - * are an ``, in which case the default callout behavior will be used, which + * are a ``, in which case the default callout behavior will be used, which * will show both the `title` and the `description`, if provided. */ title: PropTypes.string, /** * The description of the marker. This is only used if the component has no children - * that are an ``, in which case the default callout behavior will be used, + * that are a ``, in which case the default callout behavior will be used, * which will show both the `title` and the `description`, if provided. */ description: PropTypes.string, From c44b80de2bc1cf752da8248f6114f6d00079d5c7 Mon Sep 17 00:00:00 2001 From: Daniel Playfair Cal Date: Mon, 22 Jan 2018 09:56:28 +1100 Subject: [PATCH 0400/1148] Events example: Call event.persist() where appropriate to avoid synthetic events being recycled before setState occurs --- example/examples/EventListener.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/example/examples/EventListener.js b/example/examples/EventListener.js index 0dc2461d3..ff498c89a 100644 --- a/example/examples/EventListener.js +++ b/example/examples/EventListener.js @@ -68,6 +68,9 @@ class EventListener extends React.Component { recordEvent(name) { return e => { + if (e.persist) { + e.persist(); // Avoids warnings relating to https://fb.me/react-event-pooling + } this.setState(prevState => ({ events: [ this.makeEvent(e, name), From adbb4e4d50145b23f647bc10c4e3149a8054a5ee Mon Sep 17 00:00:00 2001 From: Daniel Playfair Cal Date: Mon, 22 Jan 2018 09:59:08 +1100 Subject: [PATCH 0401/1148] Add comment suggesting to deprecate other components being set as properties on MapView --- lib/components/MapView.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lib/components/MapView.js b/lib/components/MapView.js index 73ef7e38f..a8005756e 100644 --- a/lib/components/MapView.js +++ b/lib/components/MapView.js @@ -806,6 +806,14 @@ export const Animated = RNAnimated.createAnimatedComponent(MapView); export const ProviderPropType = PropTypes.oneOf(Object.values(ProviderConstants)); +/** + * TODO: + * All of these properties on MapView are unecessary since they can be imported + * individually with the es6 exports in index.js. Removing them is a breaking change, + * but potentially allows for better dead code elimination since references are not + * kept to components which are never used. + */ + MapView.Marker = MapMarker; MapView.Polyline = MapPolyline; MapView.Polygon = MapPolygon; From 8363c7c011bce72c00dbf401f4648e9c467bc32e Mon Sep 17 00:00:00 2001 From: BEGEMOT9I Date: Mon, 22 Jan 2018 18:55:14 +0300 Subject: [PATCH 0402/1148] Add native animation for Markers on Android (with documentation) (#1976) * added functionality for smooth marker movement on android * added docs for new functionality * edited example of marker animation * fixed formatting * removed package-lock --- README.md | 61 +++++++++++++++++-- docs/marker.md | 1 + example/examples/AnimatedMarkers.js | 14 ++++- .../android/react/maps/AirMapMarker.java | 26 ++++++++ .../react/maps/AirMapMarkerManager.java | 19 +++++- lib/components/MapMarker.js | 5 ++ package.json | 3 +- 7 files changed, 119 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 1fbb6c430..9eb71f4d6 100644 --- a/README.md +++ b/README.md @@ -431,18 +431,69 @@ getInitialState() { } componentWillReceiveProps(nextProps) { + const duration = 500 + + if (this.props.coordinate !== nextProps.coordinate) { + if (Platform.OS === 'android') { + if (this.marker) { + this.marker._component.animateMarkerToCoordinate( + nextProps.coordinate, + duration + ); + } + } else { + this.state.coordinate.timing({ + ...nextProps.coordinate, + duration + }).start(); + } + } +} + +render() { + return ( + + { this.marker = marker }} + coordinate={this.state.coordinate} + /> + + ); +} +``` + +If you need a smoother animation to move the marker on Android, you can modify the previous example: + +```jsx +// ... + +componentWillReceiveProps(nextProps) { + const duration = 500 + if (this.props.coordinate !== nextProps.coordinate) { - this.state.coordinate.timing({ - ...nextProps.coordinate, - duration: 500 - }).start(); + if (Platform.OS === 'android') { + if (this.marker) { + this.marker._component.animateMarkerToCoordinate( + nextProps.coordinate, + duration + ); + } + } else { + this.state.coordinate.timing({ + ...nextProps.coordinate, + duration + }).start(); + } } } render() { return ( - + { this.marker = marker }} + coordinate={this.state.coordinate} + /> ); } diff --git a/docs/marker.md b/docs/marker.md index 97f79ab79..f165ab6f5 100644 --- a/docs/marker.md +++ b/docs/marker.md @@ -41,6 +41,7 @@ To access event data, you will need to use `e.nativeEvent`. For example, `onPres |---|---|---| | `showCallout` | | Shows the callout for this marker | `hideCallout` | | Hides the callout for this marker +| `animateMarkerToCoordinate` | `coordinate: LatLng, duration: number` | Animates marker movement. **Note**: Android only diff --git a/example/examples/AnimatedMarkers.js b/example/examples/AnimatedMarkers.js index 31cfafac4..9e8d8b0be 100644 --- a/example/examples/AnimatedMarkers.js +++ b/example/examples/AnimatedMarkers.js @@ -5,6 +5,7 @@ import { Text, Dimensions, TouchableOpacity, + Platform, } from 'react-native'; import MapView from 'react-native-maps'; @@ -31,10 +32,18 @@ class AnimatedMarkers extends React.Component { animate() { const { coordinate } = this.state; - coordinate.timing({ + const newCoordinate = { latitude: LATITUDE + ((Math.random() - 0.5) * (LATITUDE_DELTA / 2)), longitude: LONGITUDE + ((Math.random() - 0.5) * (LONGITUDE_DELTA / 2)), - }).start(); + }; + + if (Platform.OS === 'android') { + if (this.marker) { + this.marker._component.animateMarkerToCoordinate(newCoordinate, 500); + } + } else { + coordinate.timing(newCoordinate).start(); + } } render() { @@ -51,6 +60,7 @@ class AnimatedMarkers extends React.Component { }} > { this.marker = marker; }} coordinate={this.state.coordinate} /> diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapMarker.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapMarker.java index cb0274bfa..f560bd40b 100644 --- a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapMarker.java +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapMarker.java @@ -8,6 +8,9 @@ import android.net.Uri; import android.view.View; import android.widget.LinearLayout; +import android.animation.ObjectAnimator; +import android.util.Property; +import android.animation.TypeEvaluator; import com.facebook.common.references.CloseableReference; import com.facebook.datasource.DataSource; @@ -217,6 +220,29 @@ public void setCalloutAnchor(double x, double y) { update(); } + public LatLng interpolate(float fraction, LatLng a, LatLng b) { + double lat = (b.latitude - a.latitude) * fraction + a.latitude; + double lng = (b.longitude - a.longitude) * fraction + a.longitude; + return new LatLng(lat, lng); + } + + public void animateToCoodinate(LatLng finalPosition, Integer duration) { + TypeEvaluator typeEvaluator = new TypeEvaluator() { + @Override + public LatLng evaluate(float fraction, LatLng startValue, LatLng endValue) { + return interpolate(fraction, startValue, endValue); + } + }; + Property property = Property.of(Marker.class, LatLng.class, "position"); + ObjectAnimator animator = ObjectAnimator.ofObject( + marker, + property, + typeEvaluator, + finalPosition); + animator.setDuration(duration); + animator.start(); + } + public void setImage(String uri) { if (uri == null) { iconBitmapDescriptor = null; diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapMarkerManager.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapMarkerManager.java index 3aef3148c..080abad71 100644 --- a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapMarkerManager.java +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapMarkerManager.java @@ -11,6 +11,7 @@ import com.facebook.react.uimanager.ViewGroupManager; import com.facebook.react.uimanager.annotations.ReactProp; import com.google.android.gms.maps.model.Marker; +import com.google.android.gms.maps.model.LatLng; import java.util.HashMap; import java.util.Map; @@ -21,6 +22,7 @@ public class AirMapMarkerManager extends ViewGroupManager { private static final int SHOW_INFO_WINDOW = 1; private static final int HIDE_INFO_WINDOW = 2; + private static final int ANIMATE_MARKER_TO_COORDINATE = 3; public AirMapMarkerManager() { } @@ -154,12 +156,18 @@ public void removeViewAt(AirMapMarker parent, int index) { public Map getCommandsMap() { return MapBuilder.of( "showCallout", SHOW_INFO_WINDOW, - "hideCallout", HIDE_INFO_WINDOW + "hideCallout", HIDE_INFO_WINDOW, + "animateMarkerToCoordinate", ANIMATE_MARKER_TO_COORDINATE ); } @Override public void receiveCommand(AirMapMarker view, int commandId, @Nullable ReadableArray args) { + Integer duration; + Double lat; + Double lng; + ReadableMap region; + switch (commandId) { case SHOW_INFO_WINDOW: ((Marker) view.getFeature()).showInfoWindow(); @@ -168,6 +176,15 @@ public void receiveCommand(AirMapMarker view, int commandId, @Nullable ReadableA case HIDE_INFO_WINDOW: ((Marker) view.getFeature()).hideInfoWindow(); break; + + case ANIMATE_MARKER_TO_COORDINATE: + region = args.getMap(0); + duration = args.getInt(1); + + lng = region.getDouble("longitude"); + lat = region.getDouble("latitude"); + view.animateToCoodinate(new LatLng(lat, lng), duration); + break; } } diff --git a/lib/components/MapMarker.js b/lib/components/MapMarker.js index 7d906f6b6..fb89b71d0 100644 --- a/lib/components/MapMarker.js +++ b/lib/components/MapMarker.js @@ -236,6 +236,7 @@ class MapMarker extends React.Component { this.showCallout = this.showCallout.bind(this); this.hideCallout = this.hideCallout.bind(this); + this.animateMarkerToCoordinate = this.animateMarkerToCoordinate.bind(this); } setNativeProps(props) { @@ -250,6 +251,10 @@ class MapMarker extends React.Component { this._runCommand('hideCallout', []); } + animateMarkerToCoordinate(coordinate, duration) { + this._runCommand('animateMarkerToCoordinate', [coordinate, duration || 500]); + } + _getHandle() { return findNodeHandle(this.marker); } diff --git a/package.json b/package.json index 87b595397..3abb8730d 100644 --- a/package.json +++ b/package.json @@ -13,8 +13,7 @@ "lint": "eslint ./", "build": "npm run build:js && npm run build:android && npm run build:ios", "build:js": "exit 0", - "build:ios": - "bundle install --binstubs ./examples/ios && bundle exec pod install --project-directory=./example/ios/", + "build:ios": "bundle install --binstubs ./examples/ios && bundle exec pod install --project-directory=./example/ios/", "build:android": "./gradlew :react-native-maps:assembleDebug", "ci": "npm run lint", "preversion": "./scripts/update-version.js" From 31ff2711c487161afa32b917d487c21eb7f1133e Mon Sep 17 00:00:00 2001 From: Taro Matsuzawa Date: Sat, 27 Jan 2018 17:12:40 +0900 Subject: [PATCH 0403/1148] Refactoring Map.Overlay for android - fix LatLngBounds order - LatLngBounds use Double instead of String - enable to image readable and support URI - added two examples --- example/App.js | 4 + example/examples/ImageOverlayWithAssets.js | 94 +++++++++++++ example/examples/ImageOverlayWithURL.js | 106 ++++++++++++++ .../android/react/maps/AirMapOverlay.java | 112 +++++++++------ .../android/react/maps/ImageReadable.java | 15 ++ .../android/react/maps/ImageReader.java | 129 ++++++++++++++++++ lib/components/MapOverlay.js | 9 +- 7 files changed, 428 insertions(+), 41 deletions(-) create mode 100644 example/examples/ImageOverlayWithAssets.js create mode 100644 example/examples/ImageOverlayWithURL.js create mode 100644 lib/android/src/main/java/com/airbnb/android/react/maps/ImageReadable.java create mode 100644 lib/android/src/main/java/com/airbnb/android/react/maps/ImageReader.java diff --git a/example/App.js b/example/App.js index cddb5b7dc..122c51628 100644 --- a/example/App.js +++ b/example/App.js @@ -37,6 +37,8 @@ import LegalLabel from './examples/LegalLabel'; import SetNativePropsOverlays from './examples/SetNativePropsOverlays'; import CustomOverlay from './examples/CustomOverlay'; import BugMarkerWontUpdate from './examples/BugMarkerWontUpdate'; +import ImageOverlayWithAssets from './examples/ImageOverlayWithAssets'; +import ImageOverlayWithURL from './examples/ImageOverlayWithURL'; const IOS = Platform.OS === 'ios'; const ANDROID = Platform.OS === 'android'; @@ -152,6 +154,8 @@ class App extends React.Component { [SetNativePropsOverlays, 'Update native props', true], [CustomOverlay, 'Custom Overlay Component', true], [BugMarkerWontUpdate, 'BUG: Marker Won\'t Update (Android)', true], + [ImageOverlayWithAssets, 'Image Overlay Component with Assets', true], + [ImageOverlayWithURL, 'Image Overlay Component with URL', true], ] // Filter out examples that are not yet supported for Google Maps on iOS. .filter(example => ANDROID || (IOS && (example[2] || !this.state.useGoogleMaps))) diff --git a/example/examples/ImageOverlayWithAssets.js b/example/examples/ImageOverlayWithAssets.js new file mode 100644 index 000000000..d9fcfe77e --- /dev/null +++ b/example/examples/ImageOverlayWithAssets.js @@ -0,0 +1,94 @@ +import React, { Component } from 'react'; +import { + StyleSheet, + View, + Dimensions, +} from 'react-native'; + +import MapView from 'react-native-maps'; +import flagPinkImg from './assets/flag-pink.png'; + +const { width, height } = Dimensions.get('window'); + +const ASPECT_RATIO = width / height; +const LATITUDE = 35.679976; +const LONGITUDE = 139.768458; +const LATITUDE_DELTA = 0.01; +const LONGITUDE_DELTA = LATITUDE_DELTA * ASPECT_RATIO; +// 116423, 51613, 17 +const OVERLAY_TOP_LEFT_COORDINATE = [35.68184060244454, 139.76531982421875]; +const OVERLAY_BOTTOM_RIGHT_COORDINATE = [35.679609609368576, 139.76806640625]; +const IMAGE = flagPinkImg; + +export default class ImageOverlayWithURL extends Component { + + static propTypes = { + provider: MapView.ProviderPropType, + }; + + constructor(props) { + super(props); + + this.state = { + region: { + latitude: LATITUDE, + longitude: LONGITUDE, + latitudeDelta: LATITUDE_DELTA, + longitudeDelta: LONGITUDE_DELTA, + }, + overlay: { + bounds: [OVERLAY_TOP_LEFT_COORDINATE, OVERLAY_BOTTOM_RIGHT_COORDINATE], + image: IMAGE, + }, + }; + } + + render() { + return ( + + + + + + ); + } +} + +const styles = StyleSheet.create({ + container: { + ...StyleSheet.absoluteFillObject, + justifyContent: 'flex-end', + alignItems: 'center', + }, + map: { + ...StyleSheet.absoluteFillObject, + }, + bubble: { + backgroundColor: 'rgba(255,255,255,0.7)', + paddingHorizontal: 18, + paddingVertical: 12, + borderRadius: 20, + }, + latlng: { + width: 200, + alignItems: 'stretch', + }, + button: { + width: 80, + paddingHorizontal: 12, + alignItems: 'center', + marginHorizontal: 10, + }, + buttonContainer: { + flexDirection: 'row', + marginVertical: 20, + backgroundColor: 'transparent', + }, +}); diff --git a/example/examples/ImageOverlayWithURL.js b/example/examples/ImageOverlayWithURL.js new file mode 100644 index 000000000..f3618fa54 --- /dev/null +++ b/example/examples/ImageOverlayWithURL.js @@ -0,0 +1,106 @@ +import React, { Component } from 'react'; +import { + StyleSheet, + View, + Dimensions, +} from 'react-native'; + +import MapView from 'react-native-maps'; + +const { width, height } = Dimensions.get('window'); + +const ASPECT_RATIO = width / height; +const LATITUDE = 35.679976; +const LONGITUDE = 139.768458; +const LATITUDE_DELTA = 0.01; +const LONGITUDE_DELTA = LATITUDE_DELTA * ASPECT_RATIO; +// 116423, 51613, 17 +const OVERLAY_TOP_LEFT_COORDINATE1 = [35.68184060244454, 139.76531982421875]; +const OVERLAY_BOTTOM_RIGHT_COORDINATE1 = [35.679609609368576, 139.76806640625]; +const IMAGE_URL1 = 'https://maps.gsi.go.jp/xyz/std/17/116423/51613.png'; +// 116423, 51614, 17 +const OVERLAY_TOP_LEFT_COORDINATE2 = [35.679609609368576, 139.76531982421875]; +const OVERLAY_BOTTOM_RIGHT_COORDINATE2 = [35.67737855391474, 139.76806640625]; +const IMAGE_URL2 = 'https://maps.gsi.go.jp/xyz/std/17/116423/51614.png'; + +export default class ImageOverlayWithURL extends Component { + + static propTypes = { + provider: MapView.ProviderPropType, + }; + + constructor(props) { + super(props); + + this.state = { + region: { + latitude: LATITUDE, + longitude: LONGITUDE, + latitudeDelta: LATITUDE_DELTA, + longitudeDelta: LONGITUDE_DELTA, + }, + overlay1: { + bounds: [OVERLAY_TOP_LEFT_COORDINATE1, OVERLAY_BOTTOM_RIGHT_COORDINATE1], + image: IMAGE_URL1, + }, + overlay2: { + bounds: [OVERLAY_TOP_LEFT_COORDINATE2, OVERLAY_BOTTOM_RIGHT_COORDINATE2], + image: IMAGE_URL2, + }, + }; + } + + render() { + return ( + + + + + + + ); + } +} + +const styles = StyleSheet.create({ + container: { + ...StyleSheet.absoluteFillObject, + justifyContent: 'flex-end', + alignItems: 'center', + }, + map: { + ...StyleSheet.absoluteFillObject, + }, + bubble: { + backgroundColor: 'rgba(255,255,255,0.7)', + paddingHorizontal: 18, + paddingVertical: 12, + borderRadius: 20, + }, + latlng: { + width: 200, + alignItems: 'stretch', + }, + button: { + width: 80, + paddingHorizontal: 12, + alignItems: 'center', + marginHorizontal: 10, + }, + buttonContainer: { + flexDirection: 'row', + marginVertical: 20, + backgroundColor: 'transparent', + }, +}); diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapOverlay.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapOverlay.java index 9e257760c..0c110d4b5 100644 --- a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapOverlay.java +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapOverlay.java @@ -15,42 +15,37 @@ import java.util.ArrayList; -public class AirMapOverlay extends AirMapFeature { +public class AirMapOverlay extends AirMapFeature implements ImageReadable { private GroundOverlayOptions groundOverlayOptions; private GroundOverlay groundOverlay; private LatLngBounds bounds; private BitmapDescriptor iconBitmapDescriptor; + private Bitmap iconBitmap; private float zIndex; private float transparency; + private final ImageReader mImageReader; + private GoogleMap map; public AirMapOverlay(Context context) { super(context); + this.mImageReader = new ImageReader(context, getResources(), this); } - public void setBounds(ReadableArray bounds) { - ArrayList tmpBounds = new ArrayList<>(bounds.size()); - for (int i = 0; i < bounds.size(); i++) { - tmpBounds.add(bounds.getArray(i)); - } - this.bounds = new LatLngBounds( - new LatLng(Double.parseDouble(bounds.getArray(0).getString(0)), Double.parseDouble(bounds.getArray(0) - .getString(1))), - new LatLng(Double.parseDouble(bounds.getArray(1).getString(0)), Double - .parseDouble(bounds.getArray(1) - .getString(1))) - ); - if (groundOverlay != null) { - groundOverlay.setPositionFromBounds(this.bounds); + LatLng sw = new LatLng(bounds.getArray(1).getDouble(0), bounds.getArray(0).getDouble(1)); + LatLng ne = new LatLng(bounds.getArray(0).getDouble(0), bounds.getArray(1).getDouble(1)); + this.bounds = new LatLngBounds(sw, ne); + if (this.groundOverlay != null) { + this.groundOverlay.setPositionFromBounds(this.bounds); } } public void setZIndex(float zIndex) { this.zIndex = zIndex; - if (groundOverlay != null) { - groundOverlay.setZIndex(zIndex); + if (this.groundOverlay != null) { + this.groundOverlay.setZIndex(zIndex); } } @@ -62,33 +57,29 @@ public void setZIndex(float zIndex) { // } public void setImage(String uri) { - this.iconBitmapDescriptor = getBitmapDescriptorByName(uri); - - if (groundOverlay != null) { - groundOverlay.setImage(this.iconBitmapDescriptor); - } + this.mImageReader.setImage(uri); } public GroundOverlayOptions getGroundOverlayOptions() { - if (groundOverlayOptions == null) { - groundOverlayOptions = createGroundOverlayOptions(); + if (this.groundOverlayOptions == null) { + this.groundOverlayOptions = createGroundOverlayOptions(); } - return groundOverlayOptions; + return this.groundOverlayOptions; } private GroundOverlayOptions createGroundOverlayOptions() { - GroundOverlayOptions options = new GroundOverlayOptions(); - options.image(iconBitmapDescriptor); - options.positionFromBounds(bounds); - // options.transparency(transparency); - options.zIndex(zIndex); - return options; - } - - private BitmapDescriptor getBitmapDescriptorByName(String name) { - Bitmap bitmap = ImageUtil.convert(name); - return BitmapDescriptorFactory.fromBitmap(bitmap); + if (this.groundOverlayOptions != null) { + return this.groundOverlayOptions; + } + if (this.iconBitmapDescriptor != null) { + GroundOverlayOptions options = new GroundOverlayOptions(); + options.image(iconBitmapDescriptor); + options.positionFromBounds(bounds); + options.zIndex(zIndex); + return options; + } + return null; } @Override @@ -98,12 +89,55 @@ public Object getFeature() { @Override public void addToMap(GoogleMap map) { - groundOverlay = map.addGroundOverlay(getGroundOverlayOptions()); - groundOverlay.setClickable(true); + GroundOverlayOptions groundOverlayOptions = getGroundOverlayOptions(); + if (groundOverlayOptions != null) { + this.groundOverlay = map.addGroundOverlay(groundOverlayOptions); + this.groundOverlay.setClickable(true); + } else { + this.map = map; + } } @Override public void removeFromMap(GoogleMap map) { - groundOverlay.remove(); + if (this.groundOverlay != null) { + this.groundOverlay.remove(); + this.groundOverlay = null; + this.groundOverlayOptions = null; + } + } + + @Override + public void setIconBitmap(Bitmap bitmap) { + this.iconBitmap = bitmap; + } + + @Override + public void setIconBitmapDescriptor( + BitmapDescriptor iconBitmapDescriptor) { + this.iconBitmapDescriptor = iconBitmapDescriptor; + } + + @Override + public void update() { + this.groundOverlay = getGroundOverlay(); + if (this.groundOverlay != null) { + this.groundOverlay.setImage(this.iconBitmapDescriptor); + this.groundOverlay.setClickable(true); + } + } + + private GroundOverlay getGroundOverlay() { + if (this.groundOverlay != null) { + return this.groundOverlay; + } + if (this.map == null) { + return null; + } + GroundOverlayOptions groundOverlayOptions = getGroundOverlayOptions(); + if (groundOverlayOptions != null) { + return this.map.addGroundOverlay(groundOverlayOptions); + } + return null; } } diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/ImageReadable.java b/lib/android/src/main/java/com/airbnb/android/react/maps/ImageReadable.java new file mode 100644 index 000000000..640053262 --- /dev/null +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/ImageReadable.java @@ -0,0 +1,15 @@ +package com.airbnb.android.react.maps; + + +import android.graphics.Bitmap; + +import com.google.android.gms.maps.model.BitmapDescriptor; + +public interface ImageReadable { + + public void setIconBitmap(Bitmap bitmap); + + public void setIconBitmapDescriptor(BitmapDescriptor bitmapDescriptor); + + public void update(); +} diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/ImageReader.java b/lib/android/src/main/java/com/airbnb/android/react/maps/ImageReader.java new file mode 100644 index 000000000..09be61976 --- /dev/null +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/ImageReader.java @@ -0,0 +1,129 @@ +package com.airbnb.android.react.maps; + +import android.content.Context; +import android.content.res.Resources; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.drawable.Animatable; +import android.net.Uri; + +import com.facebook.common.references.CloseableReference; +import com.facebook.datasource.DataSource; +import com.facebook.drawee.backends.pipeline.Fresco; +import com.facebook.drawee.controller.BaseControllerListener; +import com.facebook.drawee.controller.ControllerListener; +import com.facebook.drawee.drawable.ScalingUtils; +import com.facebook.drawee.generic.GenericDraweeHierarchy; +import com.facebook.drawee.generic.GenericDraweeHierarchyBuilder; +import com.facebook.drawee.interfaces.DraweeController; +import com.facebook.drawee.view.DraweeHolder; +import com.facebook.imagepipeline.core.ImagePipeline; +import com.facebook.imagepipeline.image.CloseableImage; +import com.facebook.imagepipeline.image.CloseableStaticBitmap; +import com.facebook.imagepipeline.image.ImageInfo; +import com.facebook.imagepipeline.request.ImageRequest; +import com.facebook.imagepipeline.request.ImageRequestBuilder; +import com.google.android.gms.maps.model.BitmapDescriptor; +import com.google.android.gms.maps.model.BitmapDescriptorFactory; + +import javax.annotation.Nullable; + +public class ImageReader { + + private final ImageReadable imp; + private final Context context; + private final Resources resources; + + private final DraweeHolder logoHolder; + private DataSource> dataSource; + + private final ControllerListener mLogoControllerListener = + new BaseControllerListener() { + @Override + public void onFinalImageSet( + String id, + @Nullable final ImageInfo imageInfo, + @Nullable Animatable animatable) { + CloseableReference imageReference = null; + try { + imageReference = dataSource.getResult(); + if (imageReference != null) { + CloseableImage image = imageReference.get(); + if (image != null && image instanceof CloseableStaticBitmap) { + CloseableStaticBitmap closeableStaticBitmap = (CloseableStaticBitmap) image; + Bitmap bitmap = closeableStaticBitmap.getUnderlyingBitmap(); + if (bitmap != null) { + bitmap = bitmap.copy(Bitmap.Config.ARGB_8888, true); + imp.setIconBitmap(bitmap); + imp.setIconBitmapDescriptor(BitmapDescriptorFactory.fromBitmap(bitmap)); + } + } + } + } finally { + dataSource.close(); + if (imageReference != null) { + CloseableReference.closeSafely(imageReference); + } + } + imp.update(); + } + }; + + public ImageReader(Context context, Resources resources, ImageReadable imp) { + this.context = context; + this.resources = resources; + this.imp = imp; + logoHolder = DraweeHolder.create(createDraweeHeirarchy(resources), context); + logoHolder.onAttach(); + } + + private GenericDraweeHierarchy createDraweeHeirarchy(Resources resources){ + return new GenericDraweeHierarchyBuilder(resources) + .setActualImageScaleType(ScalingUtils.ScaleType.FIT_CENTER) + .setFadeDuration(0) + .build(); + } + + public void setImage(String uri) { + if (uri == null) { + imp.setIconBitmapDescriptor(null); + imp.update(); + } else if (uri.startsWith("http://") || uri.startsWith("https://") || + uri.startsWith("file://")) { + ImageRequest imageRequest = ImageRequestBuilder + .newBuilderWithSource(Uri.parse(uri)) + .build(); + ImagePipeline imagePipeline = Fresco.getImagePipeline(); + dataSource = imagePipeline.fetchDecodedImage(imageRequest, this); + + DraweeController controller = Fresco.newDraweeControllerBuilder() + .setImageRequest(imageRequest) + .setControllerListener(mLogoControllerListener) + .setOldController(logoHolder.getController()) + .build(); + logoHolder.setController(controller); + } else { + BitmapDescriptor iconBitmapDescriptor = getBitmapDescriptorByName(uri); + if (iconBitmapDescriptor != null) { + imp.setIconBitmapDescriptor(iconBitmapDescriptor); + imp.setIconBitmap(BitmapFactory.decodeResource(this.resources, getDrawableResourceByName + (uri))); + } + imp.update(); + } + + + } + + private int getDrawableResourceByName(String name) { + return this.resources.getIdentifier( + name, + "drawable", + this.context.getPackageName()); + } + + private BitmapDescriptor getBitmapDescriptorByName(String name) { + return BitmapDescriptorFactory.fromResource(getDrawableResourceByName(name)); + } + +} diff --git a/lib/components/MapOverlay.js b/lib/components/MapOverlay.js index 93215212a..445a15cee 100644 --- a/lib/components/MapOverlay.js +++ b/lib/components/MapOverlay.js @@ -32,8 +32,13 @@ class MapOverlay extends Component { render() { let image; if (this.props.image) { - image = resolveAssetSource(this.props.image) || {}; - image = image.uri; + if (typeof this.props.image.startsWith === 'function' + && this.props.image.startsWith('http')) { + image = this.props.image; + } else { + image = resolveAssetSource(this.props.image) || {}; + image = image.uri; + } } const AIRMapOverlay = this.getAirComponent(); From 921fffb8c4ea0cb1760b7389af254715aaeb3076 Mon Sep 17 00:00:00 2001 From: Alexander Veligurov Date: Sat, 27 Jan 2018 22:16:17 -0300 Subject: [PATCH 0404/1148] add markers not to AirMapView but to MKAnnotationView (fixes some zIndex issues) --- lib/ios/AirMaps/AIRMap.m | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lib/ios/AirMaps/AIRMap.m b/lib/ios/AirMaps/AIRMap.m index 335059877..647754043 100644 --- a/lib/ios/AirMaps/AIRMap.m +++ b/lib/ios/AirMaps/AIRMap.m @@ -93,6 +93,14 @@ - (void)dealloc [_regionChangeObserveTimer invalidate]; } +-(void)addSubview:(UIView *)view { + if([view isKindOfClass:[AIRMapMarker class]]) { + [self addAnnotation:(id )view]; + } else { + [super addSubview:view]; + } +} + #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wobjc-missing-super-calls" - (void)insertReactSubview:(id)subview atIndex:(NSInteger)atIndex { From cfd36ecfe9b2dd625ba14dceb913bf62808b7085 Mon Sep 17 00:00:00 2001 From: Dan Tamas Date: Mon, 29 Jan 2018 15:08:39 +0100 Subject: [PATCH 0405/1148] Update installation.md Move "do not use react-native link" --- docs/installation.md | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/docs/installation.md b/docs/installation.md index 4971925a8..6392391af 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -15,12 +15,6 @@ Without this key the Google Maps map won't render anything. -## IMPORTANT!! - -**!! DO NOT USE !!** `react-native link` - -Have ran it already? Read [this](#on-ios). - ## iOS - CocoaPods Setup your `Podfile` (found at `/ios/Podfile` as below, replace all references to `_YOUR_PROJECT_TARGET_` with your project target (it's the same as project name by default), and then run `pod install` while in the `ios` folder. @@ -72,8 +66,16 @@ end ~~~ + +## IMPORTANT!! + +**!! DO NOT USE !!** `react-native link` + +Have ran it already? Read [this](#on-ios). + ## If you want to use Google maps + Add to `ios/_YOUR_PROJECT_NAME_/AppDelegate.m: ``` From ff606b889fdf831a7f97c357af50023509ad06d3 Mon Sep 17 00:00:00 2001 From: Mellet Solbakk Date: Mon, 5 Feb 2018 09:57:20 +0100 Subject: [PATCH 0406/1148] Improve typescript definitions (#2012) * Improve typescript definitions * MapPolygonProps coordinates should be required as per documentation * MapPolylineProps coordinates should be required as per documentation **Specify that these functions have a argument and what type they are:** * onRegionChange * onRegionChangeComplete * onPress * onLongPress * onPanDrag * onMarkerDragStart * onMarkerDrag * onMarkerDragEnd * Add missing prop and function types for Marker --- index.d.ts | 46 +++++++++++++++++++++++++++++----------------- 1 file changed, 29 insertions(+), 17 deletions(-) diff --git a/index.d.ts b/index.d.ts index 64b53d17e..cac8420f6 100644 --- a/index.d.ts +++ b/index.d.ts @@ -13,6 +13,11 @@ declare module "react-native-maps" { longitude: number } + export interface Point { + x: number + y: number + } + export interface MapViewProps { provider?: 'google'; style: any; @@ -49,19 +54,19 @@ declare module "react-native-maps" { legalLabelInsets?: any; onChange?: Function; onMapReady?: Function; - onRegionChange?: Function; - onRegionChangeComplete?: Function; - onPress?: Function; + onRegionChange?: (region: Region) => void; + onRegionChangeComplete?: (region: Region) => void; + onPress?: (value: { coordinate: LatLng, position: Point }) => void; onLayout?: Function; - onLongPress?: Function; - onPanDrag?: Function; + onLongPress?: (value: { coordinate: LatLng, position: Point }) => void; + onPanDrag?: (value: {coordinate: LatLng, position: Point }) => void; onMarkerPress?: Function; onMarkerSelect?: Function; onMarkerDeselect?: Function; onCalloutPress?: Function; - onMarkerDragStart?: Function; - onMarkerDrag?: Function; - onMarkerDragEnd?: Function; + onMarkerDragStart?: (value: { coordinate: LatLng, position: Point }) => void; + onMarkerDrag?: (value: { coordinate: LatLng, position: Point }) => void; + onMarkerDragEnd?: (value: { coordinate: LatLng, position: Point }) => void; minZoomLevel?: number; maxZoomLevel?: number; } @@ -97,19 +102,22 @@ declare module "react-native-maps" { calloutAnchor?: { x: number; y: number }; flat?: boolean; draggable?: boolean; - onPress?: Function; - onSelect?: Function; - onDeselect?: Function; + onPress?: (value: { coordinate: LatLng, position: Point }) => void; + onSelect?: (value: { coordinate: LatLng, position: Point }) => void; + onDeselect?: (value: { coordinate: LatLng, position: Point }) => void; onCalloutPress?: Function; - onDragStart?: Function; - onDrag?: Function; - onDragEnd?: Function; + onDragStart?: (value: { coordinate: LatLng, position: Point }) => void; + onDrag?: (value: { coordinate: LatLng, position: Point }) => void; + onDragEnd?: (value: { coordinate: LatLng, position: Point }) => void; zIndex?: number; style?: any; + rotation?: number; + tracksViewChanges?: boolean + tracksInfoWindowChanges?: boolean } export interface MapPolylineProps { - coordinates?: { latitude: number; longitude: number; }[]; + coordinates: { latitude: number; longitude: number; }[]; onPress?: Function; tappable?: boolean; fillColor?: string; @@ -125,7 +133,7 @@ declare module "react-native-maps" { } export interface MapPolygonProps { - coordinates?: { latitude: number; longitude: number; }[]; + coordinates: { latitude: number; longitude: number; }[]; holes?: { latitude: number; longitude: number; }[][]; onPress?: Function; tappable?: boolean; @@ -173,7 +181,11 @@ declare module "react-native-maps" { style?: any; } - export class Marker extends React.Component { } + export class Marker extends React.Component { + showCallout(): void; + hideCallout(): void; + animateMarkerToCoordinate(coordinate: LatLng, duration: number): void; + } export class Polyline extends React.Component { } export class Polygon extends React.Component { } export class Circle extends React.Component { } From 0d376464a3b75edb8004cce0cfc9285fcd4a0816 Mon Sep 17 00:00:00 2001 From: Christopher Dro Date: Fri, 9 Feb 2018 11:15:15 +0100 Subject: [PATCH 0407/1148] v0.20.0 --- CHANGELOG.md | 14 ++++++++++++++ example/ios/Podfile.lock | 4 ++-- lib/android/gradle.properties | 2 +- package.json | 2 +- 4 files changed, 18 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 67449849b..bebf3b574 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,19 @@ # Change Log +## 0.20.0 (February 2, 2018) +* Common: [#1889](https://github.com/airbnb/react-native-maps/pull/1889) Fix for 'Animated.Region undefined constructor' in recent react-native version. +* iOS: [#1853](https://github.com/airbnb/react-native-maps/pull/1853) Fixed onMapReady no longer getting called on iOS +* Android: [#1906](https://github.com/airbnb/react-native-maps/pull/1906) Manage Zoom Controls visibility on the map +* iOS: [#1911](https://github.com/airbnb/react-native-maps/pull/1911) Add gradient/multi-color polyline support for iOS (MapKit) +* Android: [#1918](https://github.com/airbnb/react-native-maps/pull/1918) Ground Overlay Support +* Common: [#1851](https://github.com/airbnb/react-native-maps/pull/1851) New methods to convert between LatLng and Point +* iOS: [#1846](https://github.com/airbnb/react-native-maps/pull/1846) Fix callouts appearing behind markers +* iOS: [#1969](https://github.com/airbnb/react-native-maps/pull/1969) Added tracksInfoWindowChanges property to iOS Google Maps +* iOS: [#1960](https://github.com/airbnb/react-native-maps/pull/1960) Fixed gradient polyline not always fully drawn + stability issues +* iOS: [#1953](https://github.com/airbnb/react-native-maps/pull/1953) Fix onMapReady not getting called after first time, initialRegion lat/lng delta not setting properly, setRegion method getting called even when map is not ready and prevent onRegionChange/ onRegionChangeComplete event until initialRegion or region is set. +* Android: [#1781](https://github.com/airbnb/react-native-maps/pull/1781) Polygon holes support +* Android: [#1976](https://github.com/airbnb/react-native-maps/pull/1976) Add native animation for Markers on Android + ## 0.19.0 (December 14, 2017) * Common: [#1715](https://github.com/airbnb/react-native-maps/pull/1715) Fixed region/initialRegion null overrides of this.props * Common: [#1876](https://github.com/airbnb/react-native-maps/pull/1876) Added support for locally stored tile overlay diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index 5f60a8294..70adcdaac 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -6,10 +6,10 @@ PODS: - GoogleMaps/Base - React (0.51.0): - React/Core (= 0.51.0) - - react-native-google-maps (0.19.0): + - react-native-google-maps (0.20.0): - GoogleMaps (= 2.5.0) - React - - react-native-maps (0.19.0): + - react-native-maps (0.20.0): - React - React/BatchedBridge (0.51.0): - React/Core diff --git a/lib/android/gradle.properties b/lib/android/gradle.properties index 97093a06a..2af5ef19b 100644 --- a/lib/android/gradle.properties +++ b/lib/android/gradle.properties @@ -1,5 +1,5 @@ VERSION_CODE=4 -VERSION_NAME=0.19.0 +VERSION_NAME=0.20.0 GROUP=com.airbnb.android POM_DESCRIPTION=React Native Map view component for Android diff --git a/package.json b/package.json index bcfc2b0d9..12c5f7254 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "description": "React Native Mapview component for iOS + Android", "main": "index.js", "author": "Leland Richardson ", - "version": "0.19.0", + "version": "0.20.0", "scripts": { "start": "node node_modules/react-native/local-cli/cli.js start", "run:packager": "./node_modules/react-native/packager/packager.sh", From 49b1c69217cd46673a78a9bd0b2fcdea051c6c08 Mon Sep 17 00:00:00 2001 From: Poh Nean Date: Mon, 12 Feb 2018 18:27:56 +0800 Subject: [PATCH 0408/1148] Exposing the maximumZ property to AIRMapUrlTile (#2019) * Adding maximumZ property to AIRMapUrlTile * Updating docs and fixing MapUrlTile.js according to eslint. --- README.md | 5 +++++ lib/components/MapUrlTile.js | 7 +++++++ lib/ios/AirMaps/AIRMapUrlTile.h | 1 + lib/ios/AirMaps/AIRMapUrlTile.m | 3 +++ lib/ios/AirMaps/AIRMapUrlTileManager.m | 1 + 5 files changed, 17 insertions(+) diff --git a/README.md b/README.md index e359e04b4..300879830 100644 --- a/README.md +++ b/README.md @@ -172,6 +172,11 @@ import { UrlTile } from 'react-native-maps'; * For example, http://c.tile.openstreetmap.org/{z}/{x}/{y}.png */ urlTemplate={this.state.urlTemplate} + /** + * The maximum zoom level for this tile overlay. Corresponds to the maximumZ setting in + * MKTileOverlay. iOS only. + */ + maximumZ={19} /> ``` diff --git a/lib/components/MapUrlTile.js b/lib/components/MapUrlTile.js index 38672d3b4..0566ec2ea 100644 --- a/lib/components/MapUrlTile.js +++ b/lib/components/MapUrlTile.js @@ -31,6 +31,13 @@ const propTypes = { * @platform android */ zIndex: PropTypes.number, + /** + * The maximum zoom level for this tile overlay. Corresponds to the maximumZ setting in + * MKTileOverlay. iOS only. + * + * @platform ios + */ + maximumZ: PropTypes.number, }; class MapUrlTile extends React.Component { diff --git a/lib/ios/AirMaps/AIRMapUrlTile.h b/lib/ios/AirMaps/AIRMapUrlTile.h index 49963d3ee..697e8deae 100644 --- a/lib/ios/AirMaps/AIRMapUrlTile.h +++ b/lib/ios/AirMaps/AIRMapUrlTile.h @@ -24,6 +24,7 @@ @property (nonatomic, strong) MKTileOverlayRenderer *renderer; @property (nonatomic, copy) NSString *urlTemplate; +@property NSInteger maximumZ; #pragma mark MKOverlay protocol diff --git a/lib/ios/AirMaps/AIRMapUrlTile.m b/lib/ios/AirMaps/AIRMapUrlTile.m index fdefbf3bc..4d8abcea6 100644 --- a/lib/ios/AirMaps/AIRMapUrlTile.m +++ b/lib/ios/AirMaps/AIRMapUrlTile.m @@ -26,6 +26,9 @@ - (void) createTileOverlayAndRendererIfPossible if (!_urlTemplateSet) return; self.tileOverlay = [[MKTileOverlay alloc] initWithURLTemplate:self.urlTemplate]; self.tileOverlay.canReplaceMapContent = YES; + if (self.maximumZ) { + self.tileOverlay.maximumZ = self.maximumZ; + } self.renderer = [[MKTileOverlayRenderer alloc] initWithTileOverlay:self.tileOverlay]; } diff --git a/lib/ios/AirMaps/AIRMapUrlTileManager.m b/lib/ios/AirMaps/AIRMapUrlTileManager.m index 4ae4abffc..816b9f6ab 100644 --- a/lib/ios/AirMaps/AIRMapUrlTileManager.m +++ b/lib/ios/AirMaps/AIRMapUrlTileManager.m @@ -33,5 +33,6 @@ - (UIView *)view } RCT_EXPORT_VIEW_PROPERTY(urlTemplate, NSString) +RCT_EXPORT_VIEW_PROPERTY(maximumZ, NSInteger) @end From cd868ea7b33a04c8bdd5e909cf134a133b2cb316 Mon Sep 17 00:00:00 2001 From: Alexander Veligurov Date: Mon, 12 Feb 2018 18:12:22 -0300 Subject: [PATCH 0409/1148] hotfix PROVIDER_GOOGLE --- index.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/index.js b/index.js index edc3b3c50..557462129 100644 --- a/index.js +++ b/index.js @@ -10,5 +10,7 @@ export { default as Overlay } from './lib/components/MapOverlay.js'; export { default as Callout } from './lib/components/MapCallout.js'; export { default as AnimatedRegion } from './lib/components/AnimatedRegion.js'; export { Animated, ProviderPropType, MAP_TYPES } from './lib/components/MapView.js'; +export const PROVIDER_GOOGLE = MapView.PROVIDER_GOOGLE; +export const PROVIDER_DEFAULT = MapView.PROVIDER_DEFAULT; export default MapView; From 106f0ca5774ec3dc1107c70458343a1dcd9c5989 Mon Sep 17 00:00:00 2001 From: Christopher Dro Date: Tue, 13 Feb 2018 07:48:43 -0800 Subject: [PATCH 0410/1148] v0.20.1 --- CHANGELOG.md | 7 ++++++- example/ios/Podfile.lock | 4 ++-- lib/android/gradle.properties | 2 +- package.json | 2 +- 4 files changed, 10 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bebf3b574..0398d7c6a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ # Change Log -## 0.20.0 (February 2, 2018) +## 0.20.1 (February 13, 2018) +* Common: [hotfix PROVIDER_GOOGLE](https://github.com/react-community/react-native-maps/commit/cd868ea7b33a04c8bdd5e909cf134a133b2cb316) +* iOS: [#2019](https://github.com/airbnb/react-native-maps/pull/2019) Exposing the maximumZ property to AIRMapUrlTile + + +## 0.20.0 (February 9, 2018) * Common: [#1889](https://github.com/airbnb/react-native-maps/pull/1889) Fix for 'Animated.Region undefined constructor' in recent react-native version. * iOS: [#1853](https://github.com/airbnb/react-native-maps/pull/1853) Fixed onMapReady no longer getting called on iOS * Android: [#1906](https://github.com/airbnb/react-native-maps/pull/1906) Manage Zoom Controls visibility on the map diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index 70adcdaac..a5fb5b01e 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -6,10 +6,10 @@ PODS: - GoogleMaps/Base - React (0.51.0): - React/Core (= 0.51.0) - - react-native-google-maps (0.20.0): + - react-native-google-maps (0.20.1): - GoogleMaps (= 2.5.0) - React - - react-native-maps (0.20.0): + - react-native-maps (0.20.1): - React - React/BatchedBridge (0.51.0): - React/Core diff --git a/lib/android/gradle.properties b/lib/android/gradle.properties index 2af5ef19b..ee59d1038 100644 --- a/lib/android/gradle.properties +++ b/lib/android/gradle.properties @@ -1,5 +1,5 @@ VERSION_CODE=4 -VERSION_NAME=0.20.0 +VERSION_NAME=0.20.1 GROUP=com.airbnb.android POM_DESCRIPTION=React Native Map view component for Android diff --git a/package.json b/package.json index 12c5f7254..46be522e5 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "description": "React Native Mapview component for iOS + Android", "main": "index.js", "author": "Leland Richardson ", - "version": "0.20.0", + "version": "0.20.1", "scripts": { "start": "node node_modules/react-native/local-cli/cli.js start", "run:packager": "./node_modules/react-native/packager/packager.sh", From 53b374b189599590fc5a5c20c0468f22c1e80598 Mon Sep 17 00:00:00 2001 From: Gabriel Bull Date: Thu, 15 Feb 2018 10:39:41 -0500 Subject: [PATCH 0411/1148] Broader peer dependency support (#2030) This will remove warnings like this when installing: ``` warning " > react-native-maps@0.20.1" has incorrect peer dependency "react@16.0.0". warning " > react-native-maps@0.20.1" has incorrect peer dependency "react-native@0.51.0". warning " > react-native-maps@0.20.1" has unmet peer dependency "prop-types@^15.5.10". ``` --- package.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 46be522e5..79e33c46e 100644 --- a/package.json +++ b/package.json @@ -32,9 +32,9 @@ "mapkit" ], "peerDependencies": { - "react": "16.0.0", - "react-native": "0.51.0", - "prop-types": "^15.5.10" + "react": "^16.0", + "react-native": "^0.51", + "prop-types": "^15.0 || ^16.0" }, "devDependencies": { "babel-eslint": "^6.1.2", From 5820f06714a8fcbffa76f202ac787cda6cfef345 Mon Sep 17 00:00:00 2001 From: David Date: Sun, 18 Feb 2018 13:19:33 +0100 Subject: [PATCH 0412/1148] adding onMyLocationChange event --- docs/mapview.md | 1 + .../android/app/src/main/AndroidManifest.xml | 2 ++ example/examples/EventListener.js | 13 ++++++- .../android/react/maps/AirMapManager.java | 1 + .../airbnb/android/react/maps/AirMapView.java | 15 ++++++++ lib/components/MapView.js | 5 +++ lib/ios/AirGoogleMaps/AIRGoogleMap.h | 1 + lib/ios/AirGoogleMaps/AIRGoogleMap.m | 35 +++++++++++++++++++ lib/ios/AirGoogleMaps/AIRGoogleMapManager.m | 1 + 9 files changed, 73 insertions(+), 1 deletion(-) diff --git a/docs/mapview.md b/docs/mapview.md index 707226b9a..06c924915 100644 --- a/docs/mapview.md +++ b/docs/mapview.md @@ -46,6 +46,7 @@ To access event data, you will need to use `e.nativeEvent`. For example, `onPres | `onMapReady` | | Callback that is called once the map is fully loaded. | `onRegionChange` | `Region` | Callback that is called continuously when the region changes, such as when a user is dragging the map. | `onRegionChangeComplete` | `Region` | Callback that is called once when the region changes, such as when the user is done moving the map. +| `onMyLocationChange` | `{ coordinate: LatLng }` | Callback that is called when the underlying map figures our users current location. Make sure **showsUserLocation** is set to *true* and that the provider is `"google"`. | `onPress` | `{ coordinate: LatLng, position: Point }` | Callback that is called when user taps on the map. | `onPanDrag` | `{ coordinate: LatLng, position: Point }` | Callback that is called when user presses and drags the map. **NOTE**: for iOS `scrollEnabled` should be set to false to trigger the event | `onLongPress` | `{ coordinate: LatLng, position: Point }` | Callback that is called when user makes a "long press" somewhere on the map. diff --git a/example/android/app/src/main/AndroidManifest.xml b/example/android/app/src/main/AndroidManifest.xml index b111eef4a..2f04e8891 100644 --- a/example/android/app/src/main/AndroidManifest.xml +++ b/example/android/app/src/main/AndroidManifest.xml @@ -3,6 +3,8 @@ + + Date: Sun, 18 Feb 2018 13:21:10 +0100 Subject: [PATCH 0413/1148] adding onMyLocationChange event --- docs/mapview.md | 1 + .../android/app/src/main/AndroidManifest.xml | 2 ++ example/examples/EventListener.js | 13 ++++++- .../android/react/maps/AirMapManager.java | 1 + .../airbnb/android/react/maps/AirMapView.java | 15 ++++++++ lib/components/MapView.js | 5 +++ lib/ios/AirGoogleMaps/AIRGoogleMap.h | 1 + lib/ios/AirGoogleMaps/AIRGoogleMap.m | 35 +++++++++++++++++++ lib/ios/AirGoogleMaps/AIRGoogleMapManager.m | 1 + 9 files changed, 73 insertions(+), 1 deletion(-) diff --git a/docs/mapview.md b/docs/mapview.md index 707226b9a..06c924915 100644 --- a/docs/mapview.md +++ b/docs/mapview.md @@ -46,6 +46,7 @@ To access event data, you will need to use `e.nativeEvent`. For example, `onPres | `onMapReady` | | Callback that is called once the map is fully loaded. | `onRegionChange` | `Region` | Callback that is called continuously when the region changes, such as when a user is dragging the map. | `onRegionChangeComplete` | `Region` | Callback that is called once when the region changes, such as when the user is done moving the map. +| `onMyLocationChange` | `{ coordinate: LatLng }` | Callback that is called when the underlying map figures our users current location. Make sure **showsUserLocation** is set to *true* and that the provider is `"google"`. | `onPress` | `{ coordinate: LatLng, position: Point }` | Callback that is called when user taps on the map. | `onPanDrag` | `{ coordinate: LatLng, position: Point }` | Callback that is called when user presses and drags the map. **NOTE**: for iOS `scrollEnabled` should be set to false to trigger the event | `onLongPress` | `{ coordinate: LatLng, position: Point }` | Callback that is called when user makes a "long press" somewhere on the map. diff --git a/example/android/app/src/main/AndroidManifest.xml b/example/android/app/src/main/AndroidManifest.xml index b111eef4a..2f04e8891 100644 --- a/example/android/app/src/main/AndroidManifest.xml +++ b/example/android/app/src/main/AndroidManifest.xml @@ -3,6 +3,8 @@ + + Date: Sun, 18 Feb 2018 13:53:16 +0100 Subject: [PATCH 0414/1148] adding more data to event --- .../main/java/com/airbnb/android/react/maps/AirMapView.java | 4 ++++ lib/ios/AirGoogleMaps/AIRGoogleMap.m | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java index c6d73b03c..d20042c3e 100644 --- a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java @@ -179,6 +179,10 @@ public void onMyLocationChange(Location location){ WritableMap coordinate = new WritableNativeMap(); coordinate.putDouble("latitude", location.getLatitude()); coordinate.putDouble("longitude", location.getLongitude()); + coordinate.putDouble("altitude", location.getAltitude()); + coordinate.putFloat("accuracy", location.getAccuracy()); + coordinate.putFloat("altitude_accuracy", location.getVerticalAccuracyMeters()); + coordinate.putFloat("speed", location.getSpeed()); event.putMap("coordinate", coordinate); manager.pushEvent(context, view, "onMyLocationChange", event); diff --git a/lib/ios/AirGoogleMaps/AIRGoogleMap.m b/lib/ios/AirGoogleMaps/AIRGoogleMap.m index 1e0959c33..c3b455f21 100644 --- a/lib/ios/AirGoogleMaps/AIRGoogleMap.m +++ b/lib/ios/AirGoogleMaps/AIRGoogleMap.m @@ -414,6 +414,10 @@ - (void)observeValueForKeyPath:(NSString *)keyPath id event = @{@"coordinate": @{ @"latitude": @(location.coordinate.latitude), @"longitude": @(location.coordinate.longitude), + @"altitude": @(location.altitude), + @"accuracy": @(location.horizontalAccuracy), + @"altitude_accuracy": @(location.verticalAccuracy), + @"speed": @(location.speed), } }; From 42ff69aa2618604f47920364cf4cb84de916b263 Mon Sep 17 00:00:00 2001 From: "Taro Matsuzawa aka. btm" Date: Wed, 21 Feb 2018 01:10:35 +0900 Subject: [PATCH 0415/1148] Support Map.Overlay for iOS (#2022) * Support Map.Overlay for iOS * change using image in example * add overlay support to Google Maps API for iOS * documented limitation in Overlay for iOS * fix MKMapRectMake params from 'bottom to top' to 'top to bottom' * remove limitation --- docs/overlay.md | 2 +- example/examples/ImageOverlayWithURL.js | 8 +- lib/ios/AirGoogleMaps/AIRGoogleMap.h | 1 + lib/ios/AirGoogleMaps/AIRGoogleMap.m | 10 ++ lib/ios/AirGoogleMaps/AIRGoogleMapOverlay.h | 23 ++++ lib/ios/AirGoogleMaps/AIRGoogleMapOverlay.m | 76 +++++++++++++ .../AIRGoogleMapOverlayManager.h | 10 ++ .../AIRGoogleMapOverlayManager.m | 22 ++++ lib/ios/AirMaps.xcodeproj/project.pbxproj | 18 +++ lib/ios/AirMaps/AIRMap.m | 6 + lib/ios/AirMaps/AIRMapManager.m | 21 ++++ lib/ios/AirMaps/AIRMapOverlay.h | 36 ++++++ lib/ios/AirMaps/AIRMapOverlay.m | 103 ++++++++++++++++++ lib/ios/AirMaps/AIRMapOverlayManager.h | 5 + lib/ios/AirMaps/AIRMapOverlayManager.m | 27 +++++ lib/ios/AirMaps/AIRMapOverlayRenderer.h | 8 ++ lib/ios/AirMaps/AIRMapOverlayRenderer.m | 29 +++++ 17 files changed, 400 insertions(+), 5 deletions(-) create mode 100644 lib/ios/AirGoogleMaps/AIRGoogleMapOverlay.h create mode 100644 lib/ios/AirGoogleMaps/AIRGoogleMapOverlay.m create mode 100644 lib/ios/AirGoogleMaps/AIRGoogleMapOverlayManager.h create mode 100644 lib/ios/AirGoogleMaps/AIRGoogleMapOverlayManager.m create mode 100644 lib/ios/AirMaps/AIRMapOverlay.h create mode 100644 lib/ios/AirMaps/AIRMapOverlay.m create mode 100644 lib/ios/AirMaps/AIRMapOverlayManager.h create mode 100644 lib/ios/AirMaps/AIRMapOverlayManager.m create mode 100644 lib/ios/AirMaps/AIRMapOverlayRenderer.h create mode 100644 lib/ios/AirMaps/AIRMapOverlayRenderer.m diff --git a/docs/overlay.md b/docs/overlay.md index 24430b8e1..29a12aee3 100644 --- a/docs/overlay.md +++ b/docs/overlay.md @@ -14,4 +14,4 @@ type LatLng { latitude: Number, longitude: Number, } -``` \ No newline at end of file +``` diff --git a/example/examples/ImageOverlayWithURL.js b/example/examples/ImageOverlayWithURL.js index f3618fa54..e4d7ad8de 100644 --- a/example/examples/ImageOverlayWithURL.js +++ b/example/examples/ImageOverlayWithURL.js @@ -18,10 +18,10 @@ const LONGITUDE_DELTA = LATITUDE_DELTA * ASPECT_RATIO; const OVERLAY_TOP_LEFT_COORDINATE1 = [35.68184060244454, 139.76531982421875]; const OVERLAY_BOTTOM_RIGHT_COORDINATE1 = [35.679609609368576, 139.76806640625]; const IMAGE_URL1 = 'https://maps.gsi.go.jp/xyz/std/17/116423/51613.png'; -// 116423, 51614, 17 -const OVERLAY_TOP_LEFT_COORDINATE2 = [35.679609609368576, 139.76531982421875]; -const OVERLAY_BOTTOM_RIGHT_COORDINATE2 = [35.67737855391474, 139.76806640625]; -const IMAGE_URL2 = 'https://maps.gsi.go.jp/xyz/std/17/116423/51614.png'; +// 116423, 51615, 17 +const OVERLAY_TOP_LEFT_COORDINATE2 = [35.67737855391474, 139.76531982421875]; +const OVERLAY_BOTTOM_RIGHT_COORDINATE2 = [35.67514743608467, 139.76806640625]; +const IMAGE_URL2 = 'https://maps.gsi.go.jp/xyz/std/17/116423/51615.png'; export default class ImageOverlayWithURL extends Component { diff --git a/lib/ios/AirGoogleMaps/AIRGoogleMap.h b/lib/ios/AirGoogleMaps/AIRGoogleMap.h index 29f71a3a4..4aee9555a 100644 --- a/lib/ios/AirGoogleMaps/AIRGoogleMap.h +++ b/lib/ios/AirGoogleMaps/AIRGoogleMap.h @@ -31,6 +31,7 @@ @property (nonatomic, strong) NSMutableArray *polylines; @property (nonatomic, strong) NSMutableArray *circles; @property (nonatomic, strong) NSMutableArray *tiles; +@property (nonatomic, strong) NSMutableArray *overlays; @property (nonatomic, assign) BOOL showsBuildings; @property (nonatomic, assign) BOOL showsTraffic; diff --git a/lib/ios/AirGoogleMaps/AIRGoogleMap.m b/lib/ios/AirGoogleMaps/AIRGoogleMap.m index 81ab5c4d0..c71c355d6 100644 --- a/lib/ios/AirGoogleMaps/AIRGoogleMap.m +++ b/lib/ios/AirGoogleMaps/AIRGoogleMap.m @@ -11,6 +11,7 @@ #import "AIRGoogleMapPolyline.h" #import "AIRGoogleMapCircle.h" #import "AIRGoogleMapUrlTile.h" +#import "AIRGoogleMapOverlay.h" #import #import #import @@ -50,6 +51,7 @@ - (instancetype)init _polylines = [NSMutableArray array]; _circles = [NSMutableArray array]; _tiles = [NSMutableArray array]; + _overlays = [NSMutableArray array]; _initialRegion = MKCoordinateRegionMake(CLLocationCoordinate2DMake(0.0, 0.0), MKCoordinateSpanMake(0.0, 0.0)); _region = MKCoordinateRegionMake(CLLocationCoordinate2DMake(0.0, 0.0), MKCoordinateSpanMake(0.0, 0.0)); _initialRegionSetOnLoad = false; @@ -99,6 +101,10 @@ - (void)insertReactSubview:(id)subview atIndex:(NSInteger)atIndex AIRGoogleMapUrlTile *tile = (AIRGoogleMapUrlTile*)subview; tile.tileLayer.map = self; [self.tiles addObject:tile]; + } else if ([subview isKindOfClass:[AIRGoogleMapOverlay class]]) { + AIRGoogleMapOverlay *overlay = (AIRGoogleMapOverlay*)subview; + overlay.overlay.map = self; + [self.overlays addObject:overlay]; } else { NSArray> *childSubviews = [subview reactSubviews]; for (int i = 0; i < childSubviews.count; i++) { @@ -135,6 +141,10 @@ - (void)removeReactSubview:(id)subview { AIRGoogleMapUrlTile *tile = (AIRGoogleMapUrlTile*)subview; tile.tileLayer.map = nil; [self.tiles removeObject:tile]; + } else if ([subview isKindOfClass:[AIRGoogleMapOverlay class]]) { + AIRGoogleMapOverlay *overlay = (AIRGoogleMapOverlay*)subview; + overlay.overlay.map = nil; + [self.overlays removeObject:overlay]; } else { NSArray> *childSubviews = [subview reactSubviews]; for (int i = 0; i < childSubviews.count; i++) { diff --git a/lib/ios/AirGoogleMaps/AIRGoogleMapOverlay.h b/lib/ios/AirGoogleMaps/AIRGoogleMapOverlay.h new file mode 100644 index 000000000..0e2c4e278 --- /dev/null +++ b/lib/ios/AirGoogleMaps/AIRGoogleMapOverlay.h @@ -0,0 +1,23 @@ +// +// AIRGoogleMapOverlay.h +// +// Created by Taro Matsuzawa on 5/3/17. +// + +#import +#import +#import +#import "AIRMapCoordinate.h" +#import "AIRGoogleMap.h" + +@interface AIRGoogleMapOverlay : UIView + +@property (nonatomic, strong) GMSGroundOverlay *overlay; +@property (nonatomic, copy) NSString *imageSrc; +@property (nonatomic, strong, readonly) UIImage *overlayImage; +@property (nonatomic, copy) NSArray *boundsRect; +@property (nonatomic, readonly) GMSCoordinateBounds *overlayBounds; + +@property (nonatomic, weak) RCTBridge *bridge; + +@end diff --git a/lib/ios/AirGoogleMaps/AIRGoogleMapOverlay.m b/lib/ios/AirGoogleMaps/AIRGoogleMapOverlay.m new file mode 100644 index 000000000..9caf634aa --- /dev/null +++ b/lib/ios/AirGoogleMaps/AIRGoogleMapOverlay.m @@ -0,0 +1,76 @@ +// +// AIRGoogleMapOverlay.m +// Created by Nick Italiano on 3/5/17. +// + +#import "AIRGoogleMapOverlay.h" + +#import +#import +#import +#import + +@interface AIRGoogleMapOverlay() + @property (nonatomic, strong, readwrite) UIImage *overlayImage; + @property (nonatomic, readwrite) GMSCoordinateBounds *overlayBounds; +@end + +@implementation AIRGoogleMapOverlay { + RCTImageLoaderCancellationBlock _reloadImageCancellationBlock; + CLLocationCoordinate2D _southWest; + CLLocationCoordinate2D _northEast; +} + +- (instancetype)init +{ + if ((self = [super init])) { + _overlay = [[GMSGroundOverlay alloc] init]; + } + return self; +} + +- (void)setImageSrc:(NSString *)imageSrc +{ + NSLog(@">>> SET IMAGESRC: %@", imageSrc); + _imageSrc = imageSrc; + + if (_reloadImageCancellationBlock) { + _reloadImageCancellationBlock(); + _reloadImageCancellationBlock = nil; + } + + __weak typeof(self) weakSelf = self; + _reloadImageCancellationBlock = [_bridge.imageLoader loadImageWithURLRequest:[RCTConvert NSURLRequest:_imageSrc] + size:weakSelf.bounds.size + scale:RCTScreenScale() + clipped:YES + resizeMode:RCTResizeModeCenter + progressBlock:nil + partialLoadBlock:nil + completionBlock:^(NSError *error, UIImage *image) { + if (error) { + NSLog(@"%@", error); + } + dispatch_async(dispatch_get_main_queue(), ^{ + NSLog(@">>> IMAGE: %@", image); + weakSelf.overlayImage = image; + weakSelf.overlay.icon = image; + }); + }]; + +} + +- (void)setBoundsRect:(NSArray *)boundsRect +{ + _boundsRect = boundsRect; + + _southWest = CLLocationCoordinate2DMake([boundsRect[1][0] doubleValue], [boundsRect[0][1] doubleValue]); + _northEast = CLLocationCoordinate2DMake([boundsRect[0][0] doubleValue], [boundsRect[1][1] doubleValue]); + + _overlayBounds = [[GMSCoordinateBounds alloc] initWithCoordinate:_southWest + coordinate:_northEast]; + + _overlay.bounds = _overlayBounds; +} + +@end diff --git a/lib/ios/AirGoogleMaps/AIRGoogleMapOverlayManager.h b/lib/ios/AirGoogleMaps/AIRGoogleMapOverlayManager.h new file mode 100644 index 000000000..6d692c5ad --- /dev/null +++ b/lib/ios/AirGoogleMaps/AIRGoogleMapOverlayManager.h @@ -0,0 +1,10 @@ +// +// AIRGoogleMapOverlayManager.h +// Created by Taro Matsuzawa on 3/5/17. +// + +#import +#import + +@interface AIRGoogleMapOverlayManager : RCTViewManager +@end diff --git a/lib/ios/AirGoogleMaps/AIRGoogleMapOverlayManager.m b/lib/ios/AirGoogleMaps/AIRGoogleMapOverlayManager.m new file mode 100644 index 000000000..12b29e738 --- /dev/null +++ b/lib/ios/AirGoogleMaps/AIRGoogleMapOverlayManager.m @@ -0,0 +1,22 @@ +#import "AIRGoogleMapOverlayManager.h" +#import "AIRGoogleMapOverlay.h" + +@interface AIRGoogleMapOverlayManager() + +@end + +@implementation AIRGoogleMapOverlayManager + +RCT_EXPORT_MODULE() + +- (UIView *)view +{ + AIRGoogleMapOverlay *overlay = [AIRGoogleMapOverlay new]; + overlay.bridge = self.bridge; + return overlay; +} + +RCT_REMAP_VIEW_PROPERTY(bounds, boundsRect, NSArray) +RCT_REMAP_VIEW_PROPERTY(image, imageSrc, NSString) + +@end diff --git a/lib/ios/AirMaps.xcodeproj/project.pbxproj b/lib/ios/AirMaps.xcodeproj/project.pbxproj index 09d16bc36..33de9f918 100644 --- a/lib/ios/AirMaps.xcodeproj/project.pbxproj +++ b/lib/ios/AirMaps.xcodeproj/project.pbxproj @@ -23,6 +23,9 @@ 1125B2F21C4AD445007D0023 /* SMCalloutView.m in Sources */ = {isa = PBXBuildFile; fileRef = 1125B2F11C4AD445007D0023 /* SMCalloutView.m */; }; 19DABC7F1E7C9D3C00F41150 /* RCTConvert+AirMap.m in Sources */ = {isa = PBXBuildFile; fileRef = 19DABC7E1E7C9D3C00F41150 /* RCTConvert+AirMap.m */; }; 2163AA501FEAEDD100BBEC95 /* AIRMapPolylineRenderer.m in Sources */ = {isa = PBXBuildFile; fileRef = 2163AA4F1FEAEDD100BBEC95 /* AIRMapPolylineRenderer.m */; }; + 53D31636202E723B00B55447 /* AIRMapOverlayManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 53D31635202E723B00B55447 /* AIRMapOverlayManager.m */; }; + 53D3163A202E72FC00B55447 /* AIRMapOverlay.m in Sources */ = {isa = PBXBuildFile; fileRef = 53D31639202E72FC00B55447 /* AIRMapOverlay.m */; }; + 53D3163D202E734F00B55447 /* AIRMapOverlayRenderer.m in Sources */ = {isa = PBXBuildFile; fileRef = 53D3163C202E734F00B55447 /* AIRMapOverlayRenderer.m */; }; 628F81201FD16DF80058313A /* AIRMapLocalTile.m in Sources */ = {isa = PBXBuildFile; fileRef = 628F811F1FD16DF80058313A /* AIRMapLocalTile.m */; }; 628F81231FD16EFA0058313A /* AIRMapLocalTileManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 628F81221FD16EFA0058313A /* AIRMapLocalTileManager.m */; }; 62AEC4D41FD5A0AA003225E0 /* AIRMapLocalTileOverlay.m in Sources */ = {isa = PBXBuildFile; fileRef = 62AEC4D31FD5A0AA003225E0 /* AIRMapLocalTileOverlay.m */; }; @@ -76,6 +79,12 @@ 19DABC7E1E7C9D3C00F41150 /* RCTConvert+AirMap.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "RCTConvert+AirMap.m"; sourceTree = ""; }; 2163AA4E1FEAEDD100BBEC95 /* AIRMapPolylineRenderer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRMapPolylineRenderer.h; sourceTree = ""; }; 2163AA4F1FEAEDD100BBEC95 /* AIRMapPolylineRenderer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRMapPolylineRenderer.m; sourceTree = ""; }; + 53D31635202E723B00B55447 /* AIRMapOverlayManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AIRMapOverlayManager.m; sourceTree = ""; }; + 53D31637202E725E00B55447 /* AIRMapOverlayManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AIRMapOverlayManager.h; sourceTree = ""; }; + 53D31638202E72D500B55447 /* AIRMapOverlay.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AIRMapOverlay.h; sourceTree = ""; }; + 53D31639202E72FC00B55447 /* AIRMapOverlay.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AIRMapOverlay.m; sourceTree = ""; }; + 53D3163B202E732300B55447 /* AIRMapOverlayRenderer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AIRMapOverlayRenderer.h; sourceTree = ""; }; + 53D3163C202E734F00B55447 /* AIRMapOverlayRenderer.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AIRMapOverlayRenderer.m; sourceTree = ""; }; 628F811E1FD16D780058313A /* AIRMapLocalTile.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AIRMapLocalTile.h; sourceTree = ""; }; 628F811F1FD16DF80058313A /* AIRMapLocalTile.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AIRMapLocalTile.m; sourceTree = ""; }; 628F81211FD16EAB0058313A /* AIRMapLocalTileManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AIRMapLocalTileManager.h; sourceTree = ""; }; @@ -158,6 +167,12 @@ 628F811F1FD16DF80058313A /* AIRMapLocalTile.m */, 628F81211FD16EAB0058313A /* AIRMapLocalTileManager.h */, 628F81221FD16EFA0058313A /* AIRMapLocalTileManager.m */, + 53D31638202E72D500B55447 /* AIRMapOverlay.h */, + 53D31639202E72FC00B55447 /* AIRMapOverlay.m */, + 53D31637202E725E00B55447 /* AIRMapOverlayManager.h */, + 53D31635202E723B00B55447 /* AIRMapOverlayManager.m */, + 53D3163B202E732300B55447 /* AIRMapOverlayRenderer.h */, + 53D3163C202E734F00B55447 /* AIRMapOverlayRenderer.m */, ); path = AirMaps; sourceTree = ""; @@ -222,13 +237,16 @@ 1125B2E31C4AD3DA007D0023 /* AIRMapPolygon.m in Sources */, 1125B2E41C4AD3DA007D0023 /* AIRMapPolygonManager.m in Sources */, 1125B2DB1C4AD3DA007D0023 /* AIRMapCallout.m in Sources */, + 53D31636202E723B00B55447 /* AIRMapOverlayManager.m in Sources */, 1125B2E01C4AD3DA007D0023 /* AIRMapManager.m in Sources */, 1125B2E61C4AD3DA007D0023 /* AIRMapPolylineManager.m in Sources */, 1125B2DD1C4AD3DA007D0023 /* AIRMapCircle.m in Sources */, 19DABC7F1E7C9D3C00F41150 /* RCTConvert+AirMap.m in Sources */, 1125B2E51C4AD3DA007D0023 /* AIRMapPolyline.m in Sources */, DA6C263E1C9E324A0035349F /* AIRMapUrlTileManager.m in Sources */, + 53D3163A202E72FC00B55447 /* AIRMapOverlay.m in Sources */, 628F81201FD16DF80058313A /* AIRMapLocalTile.m in Sources */, + 53D3163D202E734F00B55447 /* AIRMapOverlayRenderer.m in Sources */, 1125B2DA1C4AD3DA007D0023 /* AIRMap.m in Sources */, 1125B2DF1C4AD3DA007D0023 /* AIRMapCoordinate.m in Sources */, 1125B2F21C4AD445007D0023 /* SMCalloutView.m in Sources */, diff --git a/lib/ios/AirMaps/AIRMap.m b/lib/ios/AirMaps/AIRMap.m index 647754043..797e5d42a 100644 --- a/lib/ios/AirMaps/AIRMap.m +++ b/lib/ios/AirMaps/AIRMap.m @@ -18,6 +18,7 @@ #import #import "AIRMapUrlTile.h" #import "AIRMapLocalTile.h" +#import "AIRMapOverlay.h" const CLLocationDegrees AIRMapDefaultSpan = 0.005; const NSTimeInterval AIRMapRegionChangeObserveInterval = 0.1; @@ -122,6 +123,9 @@ - (void)insertReactSubview:(id)subview atIndex:(NSInteger)atIndex } else if ([subview isKindOfClass:[AIRMapLocalTile class]]) { ((AIRMapLocalTile *)subview).map = self; [self addOverlay:(id)subview]; + } else if ([subview isKindOfClass:[AIRMapOverlay class]]) { + ((AIRMapOverlay *)subview).map = self; + [self addOverlay:(id)subview]; } else { NSArray> *childSubviews = [subview reactSubviews]; for (int i = 0; i < childSubviews.count; i++) { @@ -149,6 +153,8 @@ - (void)removeReactSubview:(id)subview { [self removeOverlay:(id ) subview]; } else if ([subview isKindOfClass:[AIRMapLocalTile class]]) { [self removeOverlay:(id ) subview]; + } else if ([subview isKindOfClass:[AIRMapOverlay class]]) { + [self removeOverlay:(id ) subview]; } else { NSArray> *childSubviews = [subview reactSubviews]; for (int i = 0; i < childSubviews.count; i++) { diff --git a/lib/ios/AirMaps/AIRMapManager.m b/lib/ios/AirMaps/AIRMapManager.m index faee9c357..d81684a2c 100644 --- a/lib/ios/AirMaps/AIRMapManager.m +++ b/lib/ios/AirMaps/AIRMapManager.m @@ -26,6 +26,7 @@ #import "AIRMapLocalTile.h" #import "AIRMapSnapshot.h" #import "RCTConvert+AirMap.h" +#import "AIRMapOverlay.h" #import @@ -456,6 +457,24 @@ - (void)handleMapTap:(UITapGestureRecognizer *)recognizer { } } } + + if ([overlay isKindOfClass:[AIRMapOverlay class]]) { + AIRMapOverlay *imageOverlay = (AIRMapOverlay*) overlay; + if (MKMapRectContainsPoint(imageOverlay.boundingMapRect, mapPoint)) { + if (imageOverlay.onPress) { + id event = @{ + @"action": @"image-overlay-press", + @"name": imageOverlay.name ?: @"unknown", + @"coordinate": @{ + @"latitude": @(imageOverlay.coordinate.latitude), + @"longitude": @(imageOverlay.coordinate.longitude) + } + }; + imageOverlay.onPress(event); + } + } + } + } if (nearestDistance <= maxMeters) { @@ -537,6 +556,8 @@ - (MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id +#import + +#import "RCTConvert+AirMap.h" +#import +#import "AIRMap.h" +#import "AIRMapOverlayRenderer.h" + +@class RCTBridge; + +@interface AIRMapOverlay : UIView + +@property (nonatomic, strong) AIRMapOverlayRenderer *renderer; +@property (nonatomic, weak) AIRMap *map; +@property (nonatomic, weak) RCTBridge *bridge; + +@property (nonatomic, strong) NSString *name; +@property (nonatomic, copy) NSString *imageSrc; +@property (nonatomic, strong, readonly) UIImage *overlayImage; +@property (nonatomic, copy) NSArray *boundsRect; +@property (nonatomic, assign) NSInteger rotation; +@property (nonatomic, assign) CGFloat transparency; +@property (nonatomic, assign) NSInteger zIndex; + +@property (nonatomic, copy) RCTBubblingEventBlock onPress; + +#pragma mark MKOverlay protocol + +@property(nonatomic, readonly) CLLocationCoordinate2D coordinate; +@property(nonatomic, readonly) MKMapRect boundingMapRect; +- (BOOL)intersectsMapRect:(MKMapRect)mapRect; +- (BOOL)canReplaceMapContent; + +@end diff --git a/lib/ios/AirMaps/AIRMapOverlay.m b/lib/ios/AirMaps/AIRMapOverlay.m new file mode 100644 index 000000000..316fd883a --- /dev/null +++ b/lib/ios/AirMaps/AIRMapOverlay.m @@ -0,0 +1,103 @@ +#import "AIRMapOverlay.h" + +#import +#import +#import +#import +#import + +@interface AIRMapOverlay() +@property (nonatomic, strong, readwrite) UIImage *overlayImage; +@end + +@implementation AIRMapOverlay { + RCTImageLoaderCancellationBlock _reloadImageCancellationBlock; + CLLocationCoordinate2D _southWest; + CLLocationCoordinate2D _northEast; + MKMapRect _mapRect; +} + +- (void)setImageSrc:(NSString *)imageSrc +{ + NSLog(@">>> SET IMAGESRC: %@", imageSrc); + _imageSrc = imageSrc; + + if (_reloadImageCancellationBlock) { + _reloadImageCancellationBlock(); + _reloadImageCancellationBlock = nil; + } + __weak typeof(self) weakSelf = self; + _reloadImageCancellationBlock = [_bridge.imageLoader loadImageWithURLRequest:[RCTConvert NSURLRequest:_imageSrc] + size:weakSelf.bounds.size + scale:RCTScreenScale() + clipped:YES + resizeMode:RCTResizeModeCenter + progressBlock:nil + partialLoadBlock:nil + completionBlock:^(NSError *error, UIImage *image) { + if (error) { + NSLog(@"%@", error); + } + dispatch_async(dispatch_get_main_queue(), ^{ + NSLog(@">>> IMAGE: %@", image); + weakSelf.overlayImage = image; + [weakSelf createOverlayRendererIfPossible]; + [weakSelf update]; + }); + }]; +} + +- (void)setBoundsRect:(NSArray *)boundsRect { + _boundsRect = boundsRect; + + _southWest = CLLocationCoordinate2DMake([boundsRect[1][0] doubleValue], [boundsRect[0][1] doubleValue]); + _northEast = CLLocationCoordinate2DMake([boundsRect[0][0] doubleValue], [boundsRect[1][1] doubleValue]); + + MKMapPoint southWest = MKMapPointForCoordinate(_southWest); + MKMapPoint northEast = MKMapPointForCoordinate(_northEast); + + _mapRect = MKMapRectMake(southWest.x, northEast.y, northEast.x - southWest.x, northEast.y - southWest.y); + + [self update]; +} + +- (void)createOverlayRendererIfPossible +{ + if (MKMapRectIsEmpty(_mapRect) || !self.overlayImage) return; + __weak typeof(self) weakSelf = self; + self.renderer = [[AIRMapOverlayRenderer alloc] initWithOverlay:weakSelf]; +} + +- (void)update +{ + if (!_renderer) return; + + if (_map == nil) return; + [_map removeOverlay:self]; + [_map addOverlay:self]; +} + + +#pragma mark MKOverlay implementation + +- (CLLocationCoordinate2D)coordinate +{ + return MKCoordinateForMapPoint(MKMapPointMake(MKMapRectGetMidX(_mapRect), MKMapRectGetMidY(_mapRect))); +} + +- (MKMapRect)boundingMapRect +{ + return _mapRect; +} + +- (BOOL)intersectsMapRect:(MKMapRect)mapRect +{ + return MKMapRectIntersectsRect(_mapRect, mapRect); +} + +- (BOOL)canReplaceMapContent +{ + return NO; +} + +@end diff --git a/lib/ios/AirMaps/AIRMapOverlayManager.h b/lib/ios/AirMaps/AIRMapOverlayManager.h new file mode 100644 index 000000000..410288d62 --- /dev/null +++ b/lib/ios/AirMaps/AIRMapOverlayManager.h @@ -0,0 +1,5 @@ +#import + +@interface AIRMapOverlayManager : RCTViewManager + +@end diff --git a/lib/ios/AirMaps/AIRMapOverlayManager.m b/lib/ios/AirMaps/AIRMapOverlayManager.m new file mode 100644 index 000000000..a6ed76533 --- /dev/null +++ b/lib/ios/AirMaps/AIRMapOverlayManager.m @@ -0,0 +1,27 @@ +#import "AIRMapOverlayManager.h" + +#import +#import +#import +#import "AIRMapOverlay.h" + +@interface AIRMapOverlayManager () + +@end + +@implementation AIRMapOverlayManager + +RCT_EXPORT_MODULE() + +- (UIView *)view +{ + AIRMapOverlay *overlay = [AIRMapOverlay new]; + overlay.bridge = self.bridge; + return overlay; +} + +RCT_REMAP_VIEW_PROPERTY(bounds, boundsRect, NSArray) +RCT_REMAP_VIEW_PROPERTY(image, imageSrc, NSString) + +@end + diff --git a/lib/ios/AirMaps/AIRMapOverlayRenderer.h b/lib/ios/AirMaps/AIRMapOverlayRenderer.h new file mode 100644 index 000000000..dfe9c883e --- /dev/null +++ b/lib/ios/AirMaps/AIRMapOverlayRenderer.h @@ -0,0 +1,8 @@ +#import + +@interface AIRMapOverlayRenderer : MKOverlayRenderer + +@property (nonatomic, assign) NSInteger rotation; +@property (nonatomic, assign) CGFloat transparency; + +@end diff --git a/lib/ios/AirMaps/AIRMapOverlayRenderer.m b/lib/ios/AirMaps/AIRMapOverlayRenderer.m new file mode 100644 index 000000000..4cd0067ea --- /dev/null +++ b/lib/ios/AirMaps/AIRMapOverlayRenderer.m @@ -0,0 +1,29 @@ +#import "AIRMapOverlayRenderer.h" +#import "AIRMapOverlay.h" + +@implementation AIRMapOverlayRenderer + +- (void)drawMapRect:(MKMapRect)mapRect zoomScale:(MKZoomScale)zoomScale inContext:(CGContextRef)context { + UIImage *image = [(AIRMapOverlay *)self.overlay overlayImage]; + + CGContextSaveGState(context); + + CGImageRef imageReference = image.CGImage; + + MKMapRect theMapRect = [self.overlay boundingMapRect]; + CGRect theRect = [self rectForMapRect:theMapRect]; + + CGContextRotateCTM(context, M_PI); + CGContextScaleCTM(context, -1.0, 1.0); + CGContextAddRect(context, theRect); + CGContextDrawImage(context, theRect, imageReference); + + CGContextRestoreGState(context); +} + +- (BOOL)canDrawMapRect:(MKMapRect)mapRect zoomScale:(MKZoomScale)zoomScale { + return [(AIRMapOverlay *)self.overlay overlayImage] != nil; +} + +@end + From 7c83231df90a23deda8fb3e321a989df717cd04d Mon Sep 17 00:00:00 2001 From: Almir Kadric Date: Wed, 21 Feb 2018 03:12:37 +0900 Subject: [PATCH 0416/1148] fixed some typescript issues (#2035) * fixed typescript issues * fixed lint error --- index.d.ts | 54 +++++++++++++++++++++++++++++++++++++++++++++++++----- index.js | 11 +++++++++-- 2 files changed, 58 insertions(+), 7 deletions(-) diff --git a/index.d.ts b/index.d.ts index cac8420f6..5f9d7b3ee 100644 --- a/index.d.ts +++ b/index.d.ts @@ -1,13 +1,14 @@ declare module "react-native-maps" { import * as React from 'react'; - + import { Animated } from 'react-native'; + export interface Region { latitude: number longitude: number latitudeDelta: number longitudeDelta: number } - + export interface LatLng { latitude: number longitude: number @@ -18,6 +19,27 @@ declare module "react-native-maps" { y: number } + export class AnimatedRegion extends Animated.AnimatedWithChildren { + latitude: Animated.Value + longitude: Animated.Value + latitudeDelta: Animated.Value + longitudeDelta: Animated.Value + + constructor(LatLng); + + setValue(value: Region): void; + setOffset(offset: Region): void; + flattenOffset(): void; + __getValue(): Region; + __attach(): void; + __detach(): void; + stopAnimation(callback?: Function): void; + addListener(callback: Function): string; + removeListener(id: string): void; + spring(config: any): any; + timing(config: any): any; + } + export interface MapViewProps { provider?: 'google'; style: any; @@ -72,8 +94,17 @@ declare module "react-native-maps" { } export default class MapView extends React.Component { - static Animated: any; - static AnimatedRegion: any; + animateToRegion(region: Region, duration?: number): void; + animateToCoordinate(latLng: LatLng, duration?: number): void; + animateToBearing(bearing: number, duration?: number): void; + animateToViewingAngle(angle: number, duration?: number): void; + fitToElements(animated: boolean): void; + fitToSuppliedMarkers(markers: string[], animated: boolean): void; + fitToCoordinates(coordinates?: LatLng[], options?:{}): void; + setMapBoundaries(northEast: LatLng, southWest: LatLng): void; + } + + export class MapViewAnimated extends React.Component { animateToRegion(region: Region, duration?: number): void; animateToCoordinate(latLng: LatLng, duration?: number): void; animateToBearing(bearing: number, duration?: number): void; @@ -95,7 +126,7 @@ declare module "react-native-maps" { image?: any; opacity?: number; pinColor?: string; - coordinate: { latitude: number; longitude: number }; + coordinate: { latitude: number; longitude: number } | AnimatedRegion; centerOffset?: { x: number; y: number }; calloutOffset?: { x: number; y: number }; anchor?: { x: number; y: number }; @@ -175,6 +206,11 @@ declare module "react-native-maps" { zIndex?: number; } + export interface MapOverlayProps { + image?: any; + bounds: LatLng[]; + } + export interface MapCalloutProps { tooltip?: boolean; onPress?: Function; @@ -191,5 +227,13 @@ declare module "react-native-maps" { export class Circle extends React.Component { } export class UrlTile extends React.Component { } export class LocalTile extends React.Component { } + export class Overlay extends React.Component { } export class Callout extends React.Component { } + + export class MarkerAnimated extends React.Component { + showCallout(): void; + hideCallout(): void; + animateMarkerToCoordinate(coordinate: LatLng, duration: number): void; + } + export class OverlayAnimated extends React.Component { } } diff --git a/index.js b/index.js index 557462129..c89dd5b92 100644 --- a/index.js +++ b/index.js @@ -1,16 +1,23 @@ import MapView from './lib/components/MapView'; +import Marker from './lib/components/MapMarker.js'; +import Overlay from './lib/components/MapOverlay.js'; -export { default as Marker } from './lib/components/MapMarker.js'; export { default as Polyline } from './lib/components/MapPolyline.js'; export { default as Polygon } from './lib/components/MapPolygon.js'; export { default as Circle } from './lib/components/MapCircle.js'; export { default as UrlTile } from './lib/components/MapUrlTile.js'; export { default as LocalTile } from './lib/components/MapLocalTile.js'; -export { default as Overlay } from './lib/components/MapOverlay.js'; export { default as Callout } from './lib/components/MapCallout.js'; export { default as AnimatedRegion } from './lib/components/AnimatedRegion.js'; export { Animated, ProviderPropType, MAP_TYPES } from './lib/components/MapView.js'; + +export { Marker, Overlay }; + export const PROVIDER_GOOGLE = MapView.PROVIDER_GOOGLE; export const PROVIDER_DEFAULT = MapView.PROVIDER_DEFAULT; +export const MarkerAnimated = Marker.Animated; +export const OverlayAnimated = Overlay.Animated; + export default MapView; + From d22f96f9115f10b50085206463143c421f8d948d Mon Sep 17 00:00:00 2001 From: Rafael Lincoln Date: Fri, 23 Feb 2018 10:41:28 -0300 Subject: [PATCH 0417/1148] Add suport for KML file (Only Markers) (#2011) * Android - Add support to kml file * IOS - Support for kml file GoogleMaps * Android - Support to kml file * Android - Add support to kml file * Update Doc * Add Google-Maps-iOS-Utils to pod * Fix lint error * Fix param to old values * Verify kml container * Render custom marker by styleid * Add event onKmlReady * Add event onKmlReady and update docs * IOS - KML support to local file * Fix crash KML Marker Android --- docs/mapview.md | 17 + example/App.js | 2 + example/examples/MapKml.js | 79 + .../AirMapsExplorer.xcodeproj/project.pbxproj | 50 +- .../xcschemes/AirMapsExplorer.xcscheme | 2 + example/ios/Podfile | 1 + example/ios/Podfile.lock | 31 +- index.d.ts | 1 + lib/android/build.gradle | 3 +- lib/android/src/main/assets/ula.kml | 1214 ++++ .../android/react/maps/AirMapManager.java | 11 +- .../android/react/maps/AirMapMarker.java | 19 + .../airbnb/android/react/maps/AirMapView.java | 146 +- .../airbnb/android/react/maps/FileUtil.java | 77 + lib/components/MapView.js | 11 + lib/ios/AirGoogleMaps/AIRGoogleMap.h | 4 + lib/ios/AirGoogleMaps/AIRGoogleMap.m | 82 +- lib/ios/AirGoogleMaps/AIRGoogleMapManager.m | 3 + lib/ios/AirMaps.xcodeproj/project.pbxproj | 124 +- lib/ios/AirMaps/AIRMapManager.m | 1 + react-native-google-maps.podspec | 1 + yarn.lock | 6000 +++++++++++++++++ 22 files changed, 7858 insertions(+), 21 deletions(-) create mode 100644 example/examples/MapKml.js create mode 100644 lib/android/src/main/assets/ula.kml create mode 100644 lib/android/src/main/java/com/airbnb/android/react/maps/FileUtil.java create mode 100644 yarn.lock diff --git a/docs/mapview.md b/docs/mapview.md index 707226b9a..80662ff18 100644 --- a/docs/mapview.md +++ b/docs/mapview.md @@ -35,6 +35,7 @@ | `loadingBackgroundColor` | `Color` | `#FFFFFF` | Sets loading background color, default to `#FFFFFF`. | `moveOnMarkerPress` | `Boolean` | `true` | `Android only` If `false` the map won't move when a marker is pressed. | `legalLabelInsets` | `EdgeInsets` | | If set, changes the position of the "Legal" label link from the OS default. **Note:** iOS only. +| `kmlSrc` | `string` | | The URL from KML file. **Note:** Google Maps and Markers only (either Android or iOS with `PROVIDER_GOOGLE`). ## Events @@ -44,6 +45,7 @@ To access event data, you will need to use `e.nativeEvent`. For example, `onPres | Event Name | Returns | Notes |---|---|---| | `onMapReady` | | Callback that is called once the map is fully loaded. +| `onKmlReady` | `KmlContainer` | Callback that is called once the kml is fully loaded. | `onRegionChange` | `Region` | Callback that is called continuously when the region changes, such as when a user is dragging the map. | `onRegionChangeComplete` | `Region` | Callback that is called once when the region changes, such as when the user is done moving the map. | `onPress` | `{ coordinate: LatLng, position: Point }` | Callback that is called when user taps on the map. @@ -127,3 +129,18 @@ type EdgeInsets { right: Number } ``` + +``` +type Marker { + id: String, + coordinate: LatLng, + title: String, + description: String +} +``` + +``` +type KmlContainer { + markers: [Marker] +} +``` diff --git a/example/App.js b/example/App.js index fd7c2b786..b21c0f4b2 100644 --- a/example/App.js +++ b/example/App.js @@ -36,6 +36,7 @@ import MapStyle from './examples/MapStyle'; import LegalLabel from './examples/LegalLabel'; import SetNativePropsOverlays from './examples/SetNativePropsOverlays'; import CustomOverlay from './examples/CustomOverlay'; +import MapKml from './examples/MapKml'; import BugMarkerWontUpdate from './examples/BugMarkerWontUpdate'; import ImageOverlayWithAssets from './examples/ImageOverlayWithAssets'; import ImageOverlayWithURL from './examples/ImageOverlayWithURL'; @@ -153,6 +154,7 @@ class App extends React.Component { [LegalLabel, 'Reposition the legal label', true], [SetNativePropsOverlays, 'Update native props', true], [CustomOverlay, 'Custom Overlay Component', true], + [MapKml, 'Load Map with KML', true], [BugMarkerWontUpdate, 'BUG: Marker Won\'t Update (Android)', true], [ImageOverlayWithAssets, 'Image Overlay Component with Assets', true], [ImageOverlayWithURL, 'Image Overlay Component with URL', true], diff --git a/example/examples/MapKml.js b/example/examples/MapKml.js new file mode 100644 index 000000000..6c9fd01c9 --- /dev/null +++ b/example/examples/MapKml.js @@ -0,0 +1,79 @@ +import React from 'react'; +import { + StyleSheet, + View, + Dimensions, +} from 'react-native'; +import MapView, { Marker } from 'react-native-maps'; + +const { width, height } = Dimensions.get('window'); + +const ASPECT_RATIO = width / height; +const LATITUDE = -18.9193508; +const LONGITUDE = -48.2830592; +const LATITUDE_DELTA = 0.0922; +const LONGITUDE_DELTA = LATITUDE_DELTA * ASPECT_RATIO; +const KML_FILE = 'https://pastebin.com/raw/jAzGpq1F'; + +class MapKml extends React.Component { + constructor(props) { + super(props); + + this.state = { + region: { + latitude: LATITUDE, + longitude: LONGITUDE, + latitudeDelta: LATITUDE_DELTA, + longitudeDelta: LONGITUDE_DELTA, + }, + }; + + this.onKmlReady = this.onKmlReady.bind(this); + } + + onKmlReady() { + this.map.fitToElements(true); + } + + render() { + return ( + + { this.map = ref; }} + provider={this.props.provider} + style={styles.map} + initialRegion={this.state.region} + kmlSrc={KML_FILE} + onKmlReady={this.onKmlReady} + > + + + + ); + } +} + +MapKml.propTypes = { + provider: MapView.ProviderPropType, +}; + +const styles = StyleSheet.create({ + container: { + justifyContent: 'flex-end', + alignItems: 'center', + }, + scrollview: { + alignItems: 'center', + paddingVertical: 40, + }, + map: { + width, + height, + }, +}); + +module.exports = MapKml; diff --git a/example/ios/AirMapsExplorer.xcodeproj/project.pbxproj b/example/ios/AirMapsExplorer.xcodeproj/project.pbxproj index f91f8c470..f709fdb4a 100644 --- a/example/ios/AirMapsExplorer.xcodeproj/project.pbxproj +++ b/example/ios/AirMapsExplorer.xcodeproj/project.pbxproj @@ -29,6 +29,20 @@ remoteGlobalIDString = 13B07F861A680F5B00A75B9A; remoteInfo = AirMapsExplorer; }; + 9B7EF7E8201949F00039273A /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 9B7EF7E3201949F00039273A /* RNFS.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = F12AFB9B1ADAF8F800E0535D; + remoteInfo = RNFS; + }; + 9B7EF7EA201949F00039273A /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 9B7EF7E3201949F00039273A /* RNFS.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 6456441F1EB8DA9100672408; + remoteInfo = "RNFS-tvOS"; + }; /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ @@ -55,6 +69,7 @@ 8490F2171E887A36000099F8 /* libicucore.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libicucore.tbd; path = usr/lib/libicucore.tbd; sourceTree = SDKROOT; }; 8490F2191E887A8F000099F8 /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; 8490F21B1E887AAC000099F8 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; }; + 9B7EF7E3201949F00039273A /* RNFS.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RNFS.xcodeproj; path = "../../node_modules/react-native-fs/RNFS.xcodeproj"; sourceTree = ""; }; BE5DE1E9AE25978F88CD940A /* Pods-AirMapsExplorer.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AirMapsExplorer.debug.xcconfig"; path = "Pods/Target Support Files/Pods-AirMapsExplorer/Pods-AirMapsExplorer.debug.xcconfig"; sourceTree = ""; }; E138AD0CDB08FE57B09B18F8 /* Pods-AirMapsExplorer.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AirMapsExplorer.release.xcconfig"; path = "Pods/Target Support Files/Pods-AirMapsExplorer/Pods-AirMapsExplorer.release.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ @@ -123,6 +138,7 @@ 2BAA8C4A80B44CFBB3F83458 /* Libraries */ = { isa = PBXGroup; children = ( + 9B7EF7E3201949F00039273A /* RNFS.xcodeproj */, ); name = Libraries; sourceTree = ""; @@ -149,6 +165,15 @@ name = Products; sourceTree = ""; }; + 9B7EF7E4201949F00039273A /* Products */ = { + isa = PBXGroup; + children = ( + 9B7EF7E9201949F00039273A /* libRNFS.a */, + 9B7EF7EB201949F00039273A /* libRNFS.a */, + ); + name = Products; + sourceTree = ""; + }; C2ED0F349F22CC794F9BC33F /* Pods */ = { isa = PBXGroup; children = ( @@ -226,6 +251,12 @@ mainGroup = 83CBB9F61A601CBA00E9B192; productRefGroup = 83CBBA001A601CBA00E9B192 /* Products */; projectDirPath = ""; + projectReferences = ( + { + ProductGroup = 9B7EF7E4201949F00039273A /* Products */; + ProjectRef = 9B7EF7E3201949F00039273A /* RNFS.xcodeproj */; + }, + ); projectRoot = ""; targets = ( 13B07F861A680F5B00A75B9A /* AirMapsExplorer */, @@ -234,6 +265,23 @@ }; /* End PBXProject section */ +/* Begin PBXReferenceProxy section */ + 9B7EF7E9201949F00039273A /* libRNFS.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libRNFS.a; + remoteRef = 9B7EF7E8201949F00039273A /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 9B7EF7EB201949F00039273A /* libRNFS.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libRNFS.a; + remoteRef = 9B7EF7EA201949F00039273A /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; +/* End PBXReferenceProxy section */ + /* Begin PBXResourcesBuildPhase section */ 00E356EC1AD99517003FC87E /* Resources */ = { isa = PBXResourcesBuildPhase; @@ -294,7 +342,7 @@ ); name = "[CP] Copy Pods Resources"; outputPaths = ( - "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/GoogleMaps.bundle", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; diff --git a/example/ios/AirMapsExplorer.xcodeproj/xcshareddata/xcschemes/AirMapsExplorer.xcscheme b/example/ios/AirMapsExplorer.xcodeproj/xcshareddata/xcschemes/AirMapsExplorer.xcscheme index 9b7c436e0..142a27d47 100644 --- a/example/ios/AirMapsExplorer.xcodeproj/xcshareddata/xcschemes/AirMapsExplorer.xcscheme +++ b/example/ios/AirMapsExplorer.xcodeproj/xcshareddata/xcschemes/AirMapsExplorer.xcscheme @@ -40,6 +40,7 @@ buildConfiguration = "Debug" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" + language = "" shouldUseLaunchSchemeArgsEnv = "YES"> void; minZoomLevel?: number; maxZoomLevel?: number; + kmlSrc?: string; } export default class MapView extends React.Component { diff --git a/lib/android/build.gradle b/lib/android/build.gradle index 326ab4bfa..ab070626a 100644 --- a/lib/android/build.gradle +++ b/lib/android/build.gradle @@ -37,4 +37,5 @@ dependencies { provided "com.facebook.react:react-native:+" compile "com.google.android.gms:play-services-base:10.2.4" compile "com.google.android.gms:play-services-maps:10.2.4" -} + compile 'com.google.maps.android:android-maps-utils:0.5+' +} \ No newline at end of file diff --git a/lib/android/src/main/assets/ula.kml b/lib/android/src/main/assets/ula.kml new file mode 100644 index 000000000..2504574a9 --- /dev/null +++ b/lib/android/src/main/assets/ula.kml @@ -0,0 +1,1214 @@ + + + + + + + + + + + + + + +20171123121441_ULA_PARCIAL + + -18.9193508,-48.2830592 + + -1 + 0 + -1 + + -48.2830592,-18.9193508 + + + CEO-ULA-00001 + + -1 + 0 + -1 + + -48.28328,-18.915815 + + + CEO-ULA-00186 + + -1 + 0 + -1 + + -48.278833,-18.919549 + + + CEO-ULA-00188 + + -1 + 0 + -1 + + -48.289805,-18.913945 + + + CEO-ULA-00229 + + -1 + 0 + -1 + + -48.288815,-18.922615 + + + CEO-ULA-00243 + + -1 + 0 + -1 + + -48.281013,-18.916794 + + + CEO-ULA-00274 + + -1 + 0 + -1 + + -48.276156,-18.91852 + + + CEO-ULA-00275 + + -1 + 0 + -1 + + -48.278656,-18.922156 + + + ST-ULA-0001 + + -1 + 0 + -1 + + -48.283467,-18.91587 + + + ST-ULA-0360 + + -1 + 0 + -1 + + -48.2917338,-18.9200969 + + + ST-ULA-0361 + + -1 + 0 + -1 + + -48.2905979,-18.921816 + + + ST-ULA-0362 + + -1 + 0 + -1 + + -48.2920103,-18.9192301 + + + ST-ULA-0399 + + -1 + 0 + -1 + + -48.29048,-18.9193956 + + + ST-ULA-0400 + + -1 + 0 + -1 + + -48.2906689,-18.918796 + + + ST-ULA-0408 + + -1 + 0 + -1 + + -48.2912278,-18.9170382 + + + CEO-ULA-00391 + + -1 + 0 + -1 + + -48.289628,-18.914507 + + + CEO-ULA-00053 + + -1 + 0 + -1 + + -48.291706,-18.920121 + + + CEO-ULA-00067 + + -1 + 0 + -1 + + -48.29045,-18.91948 + + + CEO-ULA-00288 + + -1 + 0 + -1 + + -48.274365,-18.921111 + + + CEO-ULA-00332 + + -1 + 0 + -1 + + -48.279256,-18.916275 + + + CEO-ULA-00337 + + -1 + 0 + -1 + + -48.280717,-18.916827 + + + CEO-ULA-00350 + + -1 + 0 + -1 + + -48.281085,-18.924567 + + + CEO-ULA-00369 + + -1 + 0 + -1 + + -48.288157,-18.915412 + + + CEO-ULA-00372 + + -1 + 0 + -1 + + -48.282004,-18.923989 + + + CEO-ULA-00379 + + -1 + 0 + -1 + + -48.290547,-18.919788 + + + CEO-ULA-00382 + + -1 + 0 + -1 + + -48.289297,-18.91561 + + + CEO-ULA-00386 + + -1 + 0 + -1 + + -48.280915,-18.910799 + + + CEO-ULA-00388 + + -1 + 0 + -1 + + -48.283811,-18.914334 + + + CEO-ULA-00390 + + -1 + 0 + -1 + + -48.288354,-18.918549 + + + CEO-ULA-00400 + + -1 + 0 + -1 + + -48.283629,-18.921665 + + + CEO-ULA-00394 + + -1 + 0 + -1 + + -48.284537,-18.912023 + + + CEO-ULA-00396 + + -1 + 0 + -1 + + -48.284908,-18.925537 + + + CEO-ULA-00399 + + -1 + 0 + -1 + + -48.283935,-18.925506 + + + CEO-ULA-00417 + + -1 + 0 + -1 + + -48.284404,-18.912391 + + + CEO-ULA-00495 + + -1 + 0 + -1 + + -48.275935,-18.914429 + + + CEO-ULA-00448 + + -1 + 0 + -1 + + -48.280576,-18.921918 + + + CEO-ULA-00449 + + -1 + 0 + -1 + + -48.277405,-18.917667 + + + CEO-ULA-00488 + + -1 + 0 + -1 + + -48.282118,-18.920169 + + + CEO-ULA-00489 + + -1 + 0 + -1 + + -48.280924,-18.916682 + + + CEO-ULA-00491 + + -1 + 0 + -1 + + -48.282753,-18.913711 + + + ST-ULA-2399 + + -1 + 0 + -1 + + -48.2894488,-18.9230852 + + + ST-ULA-2400 + + -1 + 0 + -1 + + -48.2782936,-18.9196916 + + + ST-ULA-2397 + + -1 + 0 + -1 + + -48.2809308,-18.9166838 + + + ST-ULA-2398 + + -1 + 0 + -1 + + -48.2887073,-18.9228568 + + + ST-ULA-2401 + + -1 + 0 + -1 + + -48.2788126,-18.919553 + + + CEO-ULA-00509 + + -1 + 0 + -1 + + -48.280852,-18.919976 + + + CEO-ULA-00531 + + -1 + 0 + -1 + + -48.289429,-18.92309 + + + ST-ULA-1579 + + -1 + 0 + -1 + + -48.2831316,-18.9231769 + + + ST-ULA-1577 + + -1 + 0 + -1 + + -48.2803822,-18.9193287 + + + ST-ULA-1578 + + -1 + 0 + -1 + + -48.281754,-18.9211827 + + + ST-ULA-1545 + + -1 + 0 + -1 + + -48.2798797,-18.9171188 + + + ST-ULA-1551 + + -1 + 0 + -1 + + -48.2822027,-18.9181888 + + + ST-ULA-1576 + + -1 + 0 + -1 + + -48.2791963,-18.917984 + + + ST-ULA-1580 + + -1 + 0 + -1 + + -48.2820288,-18.9267845 + + + ST-ULA-1736 + + -1 + 0 + -1 + + -48.290548,-18.9198029 + + + ST-ULA-1662 + + -1 + 0 + -1 + + -48.2820532,-18.9267959 + + + ST-ULA-1663 + + -1 + 0 + -1 + + -48.2837533,-18.92488 + + + ST-ULA-1735 + + -1 + 0 + -1 + + -48.2904324,-18.919494 + + + ST-ULA-1745 + + -1 + 0 + -1 + + -48.2893041,-18.9156106 + + + ST-ULA-1773 + + -1 + 0 + -1 + + -48.2896346,-18.9144805 + + + ST-ULA-1759 + + -1 + 0 + -1 + + -48.2838156,-18.9143177 + + + ST-ULA-1760 + + -1 + 0 + -1 + + -48.2840708,-18.9135214 + + + ST-ULA-1761 + + -1 + 0 + -1 + + -48.2809102,-18.9108123 + + + ST-ULA-1776 + + -1 + 0 + -1 + + -48.2845163,-18.9120761 + + + ST-ULA-1777 + + -1 + 0 + -1 + + -48.286238,-18.9147202 + + + ST-ULA-1778 + + -1 + 0 + -1 + + -48.2897804,-18.9139702 + + + ST-ULA-1785 + + -1 + 0 + -1 + + -48.2802345,-18.9267323 + + + ST-ULA-1782 + + -1 + 0 + -1 + + -48.2845618,-18.9259192 + + + ST-ULA-1783 + + -1 + 0 + -1 + + -48.2848909,-18.9255362 + + + ST-ULA-1784 + + -1 + 0 + -1 + + -48.2826035,-18.9257531 + + + ST-ULA-1788 + + -1 + 0 + -1 + + -48.283994,-18.9255066 + + + ST-ULA-1789 + + -1 + 0 + -1 + + -48.2880791,-18.92552 + + + ST-ULA-1791 + + -1 + 0 + -1 + + -48.2848777,-18.9255045 + + + ST-ULA-1792 + + -1 + 0 + -1 + + -48.2845053,-18.9269676 + + + ST-ULA-1793 + + -1 + 0 + -1 + + -48.2823102,-18.9267975 + + + ST-ULA-1794 + + -1 + 0 + -1 + + -48.2849364,-18.9255375 + + + ST-ULA-1800 + + -1 + 0 + -1 + + -48.2841773,-18.9227149 + + + ST-ULA-1801 + + -1 + 0 + -1 + + -48.2836987,-18.9216584 + + + ST-ULA-1802 + + -1 + 0 + -1 + + -48.2848919,-18.9255115 + + + ST-ULA-1838 + + -1 + 0 + -1 + + -48.284408,-18.9123794 + + + ST-ULA-1839 + + -1 + 0 + -1 + + -48.2843991,-18.9123761 + + + ST-ULA-1768 + + -1 + 0 + -1 + + -48.2896203,-18.9145271 + + + ST-ULA-1769 + + -1 + 0 + -1 + + -48.2883589,-18.9185316 + + + ST-ULA-1770 + + -1 + 0 + -1 + + -48.2896109,-18.9145329 + + + ST-ULA-1771 + + -1 + 0 + -1 + + -48.2845797,-18.9120706 + + + ST-ULA-1772 + + -1 + 0 + -1 + + -48.2872279,-18.9128471 + + + ST-ULA-1689 + + -1 + 0 + -1 + + -48.2914404,-18.9163817 + + + ST-ULA-1690 + + -1 + 0 + -1 + + -48.2881643,-18.9154096 + + + ST-ULA-1691 + + -1 + 0 + -1 + + -48.2881523,-18.9154079 + + + ST-ULA-1692 + + -1 + 0 + -1 + + -48.2859653,-18.9147849 + + + ST-ULA-1693 + + -1 + 0 + -1 + + -48.2806094,-18.9183195 + + + ST-ULA-1694 + + -1 + 0 + -1 + + -48.2818765,-18.9164378 + + + ST-ULA-1723 + + -1 + 0 + -1 + + -48.2818717,-18.9112605 + + + ST-ULA-1724 + + -1 + 0 + -1 + + -48.2832877,-18.9120452 + + + ST-ULA-1044 + + -1 + 0 + -1 + + -48.2788265,-18.9195413 + + + ST-ULA-1048 + + -1 + 0 + -1 + + -48.2898389,-18.9139479 + + + ST-ULA-1049 + + -1 + 0 + -1 + + -48.2898306,-18.9138754 + + + ST-ULA-1836 + + -1 + 0 + -1 + + -48.2897986,-18.9139428 + + + ST-ULA-1837 + + -1 + 0 + -1 + + -48.2873611,-18.9128968 + + + ST-ULA-1710 + + -1 + 0 + -1 + + -48.2820099,-18.9239905 + + + ST-ULA-1711 + + -1 + 0 + -1 + + -48.2837723,-18.9242837 + + + ST-ULA-1363 + + -1 + 0 + -1 + + -48.2776727,-18.9229224 + + + ST-ULA-1366 + + -1 + 0 + -1 + + -48.276015,-18.9200525 + + + ST-ULA-1406 + + -1 + 0 + -1 + + -48.2743386,-18.921128 + + + ST-ULA-1129 + + -1 + 0 + -1 + + -48.2881549,-18.9223935 + + + ST-ULA-1130 + + -1 + 0 + -1 + + -48.2888228,-18.9226054 + + + ST-ULA-1246 + + -1 + 0 + -1 + + -48.2809791,-18.9170914 + + + ST-ULA-2007 + + -1 + 0 + -1 + + -48.2781596,-18.9186736 + + + ST-ULA-1963 + + -1 + 0 + -1 + + -48.2788194,-18.919549 + + + ST-ULA-1956 + + -1 + 0 + -1 + + -48.2780189,-18.9123572 + + + ST-ULA-1987 + + -1 + 0 + -1 + + -48.2761483,-18.9185129 + + + ST-ULA-2006 + + -1 + 0 + -1 + + -48.2805711,-18.9219041 + + + ST-ULA-2215 + + -1 + 0 + -1 + + -48.2850344,-18.9143632 + + + ST-ULA-2226 + + -1 + 0 + -1 + + -48.2849368,-18.9255278 + + + ST-ULA-2227 + + -1 + 0 + -1 + + -48.2862061,-18.9255751 + + + ST-ULA-2008 + + -1 + 0 + -1 + + -48.2824599,-18.9242629 + + + ST-ULA-2203 + + -1 + 0 + -1 + + -48.280991,-18.9201737 + + + ST-ULA-2206 + + -1 + 0 + -1 + + -48.2803008,-18.9176824 + + + ST-ULA-2207 + + -1 + 0 + -1 + + -48.2809238,-18.9166913 + + + ST-ULA-2209 + + -1 + 0 + -1 + + -48.2807351,-18.9112935 + + + ST-ULA-2214 + + -1 + 0 + -1 + + -48.2827837,-18.9137244 + + + ST-ULA-1669 + + -1 + 0 + -1 + + -48.2764255,-18.9140386 + + + ST-ULA-1477 + + -1 + 0 + -1 + + -48.2894117,-18.9231269 + + + ST-ULA-1478 + + -1 + 0 + -1 + + -48.2899636,-18.9253263 + + + ST-ULA-1480 + + -1 + 0 + -1 + + -48.2897642,-18.9256209 + + + ST-ULA-2268 + + -1 + 0 + -1 + + -48.2743334,-18.921121 + + + ST-ULA-2281 + + -1 + 0 + -1 + + -48.2808588,-18.9199855 + + + ST-ULA-2282 + + -1 + 0 + -1 + + -48.2830492,-18.9193608 + + + ST-ULA-0330 + + -1 + 0 + -1 + + -48.2905731,-18.9197947 + + + CTO-ULA-00159 + + -1 + 0 + -1 + + -48.290652,-18.918802 + + + CTO-ULA-00160 + + -1 + 0 + -1 + + -48.291211,-18.917047 + + + CTO-ULA-00161 + + -1 + 0 + -1 + + -48.290562,-18.921833 + + + CTO-ULA-00162 + + -1 + 0 + -1 + + -48.291992,-18.919241 + + + diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java index 0770d48a7..91f3933ed 100644 --- a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java @@ -19,6 +19,7 @@ import com.google.android.gms.maps.model.LatLng; import com.google.android.gms.maps.model.LatLngBounds; import com.google.android.gms.maps.model.MapStyleOptions; +import com.google.maps.android.data.kml.KmlLayer; import java.util.Map; @@ -231,6 +232,13 @@ public void setMaxZoomLevel(AirMapView view, float maxZoomLevel) { view.map.setMaxZoomPreference(maxZoomLevel); } + @ReactProp(name = "kmlSrc") + public void setKmlSrc(AirMapView view, String kmlUrl) { + if (kmlUrl != null) { + view.setKmlSrc(kmlUrl); + } + } + @Override public void receiveCommand(AirMapView view, int commandId, @Nullable ReadableArray args) { Integer duration; @@ -312,7 +320,8 @@ public Map getExportedCustomDirectEventTypeConstants() { "onMarkerDragStart", MapBuilder.of("registrationName", "onMarkerDragStart"), "onMarkerDrag", MapBuilder.of("registrationName", "onMarkerDrag"), "onMarkerDragEnd", MapBuilder.of("registrationName", "onMarkerDragEnd"), - "onPanDrag", MapBuilder.of("registrationName", "onPanDrag") + "onPanDrag", MapBuilder.of("registrationName", "onPanDrag"), + "onKmlReady", MapBuilder.of("registrationName", "onKmlReady") )); return map; diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapMarker.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapMarker.java index f560bd40b..1ad2c3965 100644 --- a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapMarker.java +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapMarker.java @@ -115,6 +115,25 @@ public AirMapMarker(Context context) { logoHolder.onAttach(); } + public AirMapMarker(Context context, MarkerOptions options) { + super(context); + this.context = context; + logoHolder = DraweeHolder.create(createDraweeHierarchy(), context); + logoHolder.onAttach(); + + position = options.getPosition(); + setAnchor(options.getAnchorU(), options.getAnchorV()); + setCalloutAnchor(options.getInfoWindowAnchorU(), options.getInfoWindowAnchorV()); + setTitle(options.getTitle()); + setSnippet(options.getSnippet()); + setRotation(options.getRotation()); + setFlat(options.isFlat()); + setDraggable(options.isDraggable()); + setZIndex(Math.round(options.getZIndex())); + setAlpha(options.getAlpha()); + iconBitmapDescriptor = options.getIcon(); + } + private GenericDraweeHierarchy createDraweeHierarchy() { return new GenericDraweeHierarchyBuilder(getResources()) .setActualImageScaleType(ScalingUtils.ScaleType.FIT_CENTER) diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java index 20dbad12b..4980b07ed 100644 --- a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java @@ -8,7 +8,6 @@ import android.graphics.Point; import android.graphics.PorterDuff; import android.os.Build; -import android.os.Handler; import android.support.v4.view.GestureDetectorCompat; import android.support.v4.view.MotionEventCompat; import android.view.GestureDetector; @@ -23,7 +22,9 @@ import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReadableArray; import com.facebook.react.bridge.ReadableMap; +import com.facebook.react.bridge.WritableArray; import com.facebook.react.bridge.WritableMap; +import com.facebook.react.bridge.WritableNativeArray; import com.facebook.react.bridge.WritableNativeMap; import com.facebook.react.uimanager.ThemedReactContext; import com.facebook.react.uimanager.UIManagerModule; @@ -35,25 +36,36 @@ import com.google.android.gms.maps.MapView; import com.google.android.gms.maps.OnMapReadyCallback; import com.google.android.gms.maps.Projection; +import com.google.android.gms.maps.model.BitmapDescriptorFactory; import com.google.android.gms.maps.model.CameraPosition; import com.google.android.gms.maps.model.LatLng; import com.google.android.gms.maps.model.LatLngBounds; import com.google.android.gms.maps.model.Marker; +import com.google.android.gms.maps.model.MarkerOptions; import com.google.android.gms.maps.model.Polygon; import com.google.android.gms.maps.model.Polyline; -import com.google.android.gms.maps.model.VisibleRegion; +import com.google.maps.android.data.kml.KmlContainer; +import com.google.maps.android.data.kml.KmlLayer; +import com.google.maps.android.data.kml.KmlPlacemark; +import com.google.maps.android.data.kml.KmlStyle; +import org.xmlpull.v1.XmlPullParserException; + +import java.io.IOException; +import java.io.InputStream; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.concurrent.ExecutionException; import static android.support.v4.content.PermissionChecker.checkSelfPermission; public class AirMapView extends MapView implements GoogleMap.InfoWindowAdapter, GoogleMap.OnMarkerDragListener, OnMapReadyCallback { public GoogleMap map; + private KmlLayer kmlLayer; private ProgressBar mapLoadingProgressBar; private RelativeLayout mapLoadingLayout; private ImageView cacheImageView; @@ -174,7 +186,7 @@ public void onMapReady(final GoogleMap map) { @Override public boolean onMarkerClick(Marker marker) { WritableMap event; - AirMapMarker airMapMarker = markerMap.get(marker); + AirMapMarker airMapMarker = getMarkerMap(marker); event = makeClickEventData(marker.getPosition()); event.putString("action", "marker-press"); @@ -184,7 +196,7 @@ public boolean onMarkerClick(Marker marker) { event = makeClickEventData(marker.getPosition()); event.putString("action", "marker-press"); event.putString("id", airMapMarker.getIdentifier()); - manager.pushEvent(context, markerMap.get(marker), "onPress", event); + manager.pushEvent(context, airMapMarker, "onPress", event); // Return false to open the callout info window and center on the marker // https://developers.google.com/android/reference/com/google/android/gms/maps/GoogleMap @@ -227,7 +239,7 @@ public void onInfoWindowClick(Marker marker) { event = makeClickEventData(marker.getPosition()); event.putString("action", "callout-press"); - AirMapMarker markerView = markerMap.get(marker); + AirMapMarker markerView = getMarkerMap(marker); manager.pushEvent(context, markerView, "onCalloutPress", event); event = makeClickEventData(marker.getPosition()); @@ -716,13 +728,13 @@ public void setMapBoundaries(ReadableMap northEast, ReadableMap southWest) { @Override public View getInfoWindow(Marker marker) { - AirMapMarker markerView = markerMap.get(marker); + AirMapMarker markerView = getMarkerMap(marker); return markerView.getCallout(); } @Override public View getInfoContents(Marker marker) { - AirMapMarker markerView = markerMap.get(marker); + AirMapMarker markerView = getMarkerMap(marker); return markerView.getInfoContents(); } @@ -751,7 +763,7 @@ public void onMarkerDragStart(Marker marker) { WritableMap event = makeClickEventData(marker.getPosition()); manager.pushEvent(context, this, "onMarkerDragStart", event); - AirMapMarker markerView = markerMap.get(marker); + AirMapMarker markerView = getMarkerMap(marker); event = makeClickEventData(marker.getPosition()); manager.pushEvent(context, markerView, "onDragStart", event); } @@ -761,7 +773,7 @@ public void onMarkerDrag(Marker marker) { WritableMap event = makeClickEventData(marker.getPosition()); manager.pushEvent(context, this, "onMarkerDrag", event); - AirMapMarker markerView = markerMap.get(marker); + AirMapMarker markerView = getMarkerMap(marker); event = makeClickEventData(marker.getPosition()); manager.pushEvent(context, markerView, "onDrag", event); } @@ -771,7 +783,7 @@ public void onMarkerDragEnd(Marker marker) { WritableMap event = makeClickEventData(marker.getPosition()); manager.pushEvent(context, this, "onMarkerDragEnd", event); - AirMapMarker markerView = markerMap.get(marker); + AirMapMarker markerView = getMarkerMap(marker); event = makeClickEventData(marker.getPosition()); manager.pushEvent(context, markerView, "onDragEnd", event); } @@ -868,4 +880,118 @@ public void onPanDrag(MotionEvent ev) { WritableMap event = makeClickEventData(coords); manager.pushEvent(context, this, "onPanDrag", event); } + + public void setKmlSrc(String kmlSrc) { + try { + InputStream kmlStream = new FileUtil(context).execute(kmlSrc).get(); + + if (kmlStream == null) { + return; + } + + kmlLayer = new KmlLayer(map, kmlStream, context); + kmlLayer.addLayerToMap(); + + WritableMap pointers = new WritableNativeMap(); + WritableArray markers = new WritableNativeArray(); + + if (kmlLayer.getContainers() == null) { + manager.pushEvent(context, this, "onKmlReady", pointers); + return; + } + + //Retrieve a nested container within the first container + KmlContainer container = kmlLayer.getContainers().iterator().next(); + if (container == null || container.getContainers() == null) { + manager.pushEvent(context, this, "onKmlReady", pointers); + return; + } + + + if (container.getContainers().iterator().hasNext()) { + container = container.getContainers().iterator().next(); + } + + Integer index = 0; + for (KmlPlacemark placemark : container.getPlacemarks()) { + MarkerOptions options = new MarkerOptions(); + + if (placemark.getInlineStyle() != null) { + options = placemark.getMarkerOptions(); + } else { + options.icon(BitmapDescriptorFactory.defaultMarker()); + } + + LatLng latLng = ((LatLng) placemark.getGeometry().getGeometryObject()); + String title = ""; + String snippet = ""; + + if (placemark.hasProperty("name")) { + title = placemark.getProperty("name"); + } + + if (placemark.hasProperty("description")) { + snippet = placemark.getProperty("description"); + } + + options.position(latLng); + options.title(title); + options.snippet(snippet); + + AirMapMarker marker = new AirMapMarker(context, options); + + if (placemark.getInlineStyle() != null + && placemark.getInlineStyle().getIconUrl() != null) { + marker.setImage(placemark.getInlineStyle().getIconUrl()); + } else if (container.getStyle(placemark.getStyleId()) != null) { + KmlStyle style = container.getStyle(placemark.getStyleId()); + marker.setImage(style.getIconUrl()); + } + + String identifier = title + " - " + index; + + marker.setIdentifier(identifier); + + addFeature(marker, index++); + + WritableMap loadedMarker = makeClickEventData(latLng); + loadedMarker.putString("id", identifier); + loadedMarker.putString("title", title); + loadedMarker.putString("description", snippet); + + markers.pushMap(loadedMarker); + } + + pointers.putArray("markers", markers); + + manager.pushEvent(context, this, "onKmlReady", pointers); + + } catch (XmlPullParserException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } catch (InterruptedException e) { + e.printStackTrace(); + } catch (ExecutionException e) { + e.printStackTrace(); + } + } + + private AirMapMarker getMarkerMap(Marker marker) { + AirMapMarker airMarker = markerMap.get(marker); + + if (airMarker != null) { + return airMarker; + } + + for (Map.Entry entryMarker : markerMap.entrySet()) { + if (entryMarker.getKey().getPosition().equals(marker.getPosition()) + && entryMarker.getKey().getTitle().equals(marker.getTitle())) { + airMarker = entryMarker.getValue(); + break; + } + } + + return airMarker; + } } diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/FileUtil.java b/lib/android/src/main/java/com/airbnb/android/react/maps/FileUtil.java new file mode 100644 index 000000000..5fb1aa0ab --- /dev/null +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/FileUtil.java @@ -0,0 +1,77 @@ +package com.airbnb.android.react.maps; + +import android.content.Context; +import android.net.Uri; +import android.os.AsyncTask; + +import com.facebook.common.logging.FLog; +import com.facebook.react.common.ReactConstants; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.nio.channels.Channels; +import java.nio.channels.ReadableByteChannel; + +public class FileUtil extends AsyncTask { + + private final String NAME = "FileUtil"; + private final String TEMP_FILE_SUFFIX = "temp"; + + private Exception exception; + private Context context; + + public FileUtil(Context context) { + super(); + + this.context = context; + } + + protected InputStream doInBackground(String... urls) { + try { + Uri fileContentUri = Uri.parse(urls[0]); + + if (fileContentUri.getScheme().startsWith("http")) { + return getDownloadFileInputStream(context, fileContentUri); + } + return context.getContentResolver().openInputStream(fileContentUri); + } catch (Exception e) { + this.exception = e; + FLog.e( + ReactConstants.TAG, + "Could not retrieve file for contentUri " + urls[0], + e); + return null; + } + } + + private InputStream getDownloadFileInputStream(Context context, Uri uri) + throws IOException { + final File outputDir = context.getApplicationContext().getCacheDir(); + final File file = File.createTempFile(NAME, TEMP_FILE_SUFFIX, outputDir); + file.deleteOnExit(); + + final URL url = new URL(uri.toString()); + final InputStream is = url.openStream(); + try { + final ReadableByteChannel channel = Channels.newChannel(is); + try { + final FileOutputStream stream = new FileOutputStream(file); + try { + stream.getChannel().transferFrom(channel, 0, Long.MAX_VALUE); + return new FileInputStream(file); + } finally { + stream.close(); + } + } finally { + channel.close(); + } + } finally { + is.close(); + } + } + +} diff --git a/lib/components/MapView.js b/lib/components/MapView.js index a8005756e..b7e5e0a42 100644 --- a/lib/components/MapView.js +++ b/lib/components/MapView.js @@ -347,6 +347,11 @@ const propTypes = { */ onMapReady: PropTypes.func, + /** + * Callback that is called once the kml is fully loaded. + */ + onKmlReady: PropTypes.func, + /** * Callback that is called continuously when the user is dragging the map. */ @@ -424,6 +429,11 @@ const propTypes = { */ maxZoomLevel: PropTypes.number, + /** + * Url KML Source + */ + kmlSrc: PropTypes.string, + }; class MapView extends React.Component { @@ -779,6 +789,7 @@ const nativeComponent = Component => requireNativeComponent(Component, MapView, nativeOnly: { onChange: true, onMapReady: true, + onKmlReady: true, handlePanDrag: true, }, }); diff --git a/lib/ios/AirGoogleMaps/AIRGoogleMap.h b/lib/ios/AirGoogleMaps/AIRGoogleMap.h index 4aee9555a..0e56ffd0b 100644 --- a/lib/ios/AirGoogleMaps/AIRGoogleMap.h +++ b/lib/ios/AirGoogleMaps/AIRGoogleMap.h @@ -7,6 +7,7 @@ #import #import +#import #import #import #import "AIRGMSMarker.h" @@ -15,11 +16,13 @@ @interface AIRGoogleMap : GMSMapView // TODO: don't use MK region? +@property (nonatomic, weak) RCTBridge *bridge; @property (nonatomic, assign) MKCoordinateRegion initialRegion; @property (nonatomic, assign) MKCoordinateRegion region; @property (nonatomic, assign) NSString *customMapStyleString; @property (nonatomic, assign) UIEdgeInsets mapPadding; @property (nonatomic, copy) RCTBubblingEventBlock onMapReady; +@property (nonatomic, copy) RCTBubblingEventBlock onKmlReady; @property (nonatomic, copy) RCTBubblingEventBlock onPress; @property (nonatomic, copy) RCTBubblingEventBlock onLongPress; @property (nonatomic, copy) RCTBubblingEventBlock onMarkerPress; @@ -43,6 +46,7 @@ @property (nonatomic, assign) BOOL showsUserLocation; @property (nonatomic, assign) BOOL showsMyLocationButton; @property (nonatomic, assign) BOOL showsIndoorLevelPicker; +@property (nonatomic, assign) NSString *kmlSrc; - (void)didPrepareMap; - (BOOL)didTapMarker:(GMSMarker *)marker; diff --git a/lib/ios/AirGoogleMaps/AIRGoogleMap.m b/lib/ios/AirGoogleMaps/AIRGoogleMap.m index c71c355d6..df00dbb28 100644 --- a/lib/ios/AirGoogleMaps/AIRGoogleMap.m +++ b/lib/ios/AirGoogleMaps/AIRGoogleMap.m @@ -7,14 +7,20 @@ #import "AIRGoogleMap.h" #import "AIRGoogleMapMarker.h" +#import "AIRGoogleMapMarkerManager.h" #import "AIRGoogleMapPolygon.h" #import "AIRGoogleMapPolyline.h" #import "AIRGoogleMapCircle.h" #import "AIRGoogleMapUrlTile.h" #import "AIRGoogleMapOverlay.h" #import +#import "GMUKMLParser.h" +#import "GMUPlacemark.h" +#import "GMUPoint.h" +#import "GMUGeometryRenderer.h" #import #import +#import #import "RCTConvert+AirMap.h" id regionAsJSON(MKCoordinateRegion region) { @@ -201,7 +207,11 @@ - (BOOL)didTapMarker:(GMSMarker *)marker { id event = @{@"action": @"marker-press", @"id": airMarker.identifier ?: @"unknown", - }; + @"coordinate": @{ + @"latitude": @(airMarker.position.latitude), + @"longitude": @(airMarker.position.longitude) + } + }; if (airMarker.onPress) airMarker.onPress(event); if (self.onMarkerPress) self.onMarkerPress(event); @@ -399,4 +409,74 @@ + (GMSCameraPosition*) makeGMSCameraPositionFromMap:(GMSMapView *)map andMKCoord return [map cameraForBounds:bounds insets:UIEdgeInsetsZero]; } ++ (NSString *)GetIconUrl:(GMUPlacemark *) marker parser:(GMUKMLParser *) parser { + if (marker.style.styleID != nil) { + for (GMUStyle *style in parser.styles) { + if (style.styleID == marker.style.styleID) { + return style.iconUrl; + } + } + } + + return marker.style.iconUrl; +} + +- (NSString *)KmlSrc { + return _kmlSrc; +} + +- (void)setKmlSrc:(NSString *)kmlUrl { + + _kmlSrc = kmlUrl; + + NSURL *url = [NSURL URLWithString:kmlUrl]; + NSData *urlData = nil; + + if ([url isFileURL]) { + urlData = [NSData dataWithContentsOfURL:url]; + } else { + urlData = [[NSFileManager defaultManager] contentsAtPath:kmlUrl]; + } + + GMUKMLParser *parser = [[GMUKMLParser alloc] initWithData:urlData]; + [parser parse]; + + NSUInteger index = 0; + NSMutableArray *markers = [[NSMutableArray alloc]init]; + + for (GMUPlacemark *place in parser.placemarks) { + + CLLocationCoordinate2D location =((GMUPoint *) place.geometry).coordinate; + + AIRGoogleMapMarker *marker = (AIRGoogleMapMarker *)[[AIRGoogleMapMarkerManager alloc] view]; + if (!marker.bridge) { + marker.bridge = _bridge; + } + marker.identifier = place.title; + marker.coordinate = location; + marker.title = place.title; + marker.subtitle = place.snippet; + marker.pinColor = place.style.fillColor; + marker.imageSrc = [AIRGoogleMap GetIconUrl:place parser:parser]; + marker.layer.backgroundColor = [UIColor clearColor].CGColor; + marker.layer.position = CGPointZero; + + [self insertReactSubview:(UIView *) marker atIndex:index]; + + [markers addObject:@{@"id": marker.identifier, + @"title": marker.title, + @"description": marker.subtitle, + @"coordinate": @{ + @"latitude": @(location.latitude), + @"longitude": @(location.longitude) + } + }]; + + index++; + } + + id event = @{@"markers": markers}; + if (self.onKmlReady) self.onKmlReady(event); +} + @end diff --git a/lib/ios/AirGoogleMaps/AIRGoogleMapManager.m b/lib/ios/AirGoogleMaps/AIRGoogleMapManager.m index f0f78a870..2be1cc8f0 100644 --- a/lib/ios/AirGoogleMaps/AIRGoogleMapManager.m +++ b/lib/ios/AirGoogleMaps/AIRGoogleMapManager.m @@ -42,6 +42,7 @@ @implementation AIRGoogleMapManager - (UIView *)view { AIRGoogleMap *map = [AIRGoogleMap new]; + map.bridge = self.bridge; map.delegate = self; return map; } @@ -62,6 +63,7 @@ - (UIView *)view RCT_EXPORT_VIEW_PROPERTY(customMapStyleString, NSString) RCT_EXPORT_VIEW_PROPERTY(mapPadding, UIEdgeInsets) RCT_EXPORT_VIEW_PROPERTY(onMapReady, RCTBubblingEventBlock) +RCT_EXPORT_VIEW_PROPERTY(onKmlReady, RCTBubblingEventBlock) RCT_EXPORT_VIEW_PROPERTY(onPress, RCTBubblingEventBlock) RCT_EXPORT_VIEW_PROPERTY(onLongPress, RCTBubblingEventBlock) RCT_EXPORT_VIEW_PROPERTY(onChange, RCTBubblingEventBlock) @@ -71,6 +73,7 @@ - (UIView *)view RCT_EXPORT_VIEW_PROPERTY(mapType, GMSMapViewType) RCT_EXPORT_VIEW_PROPERTY(minZoomLevel, CGFloat) RCT_EXPORT_VIEW_PROPERTY(maxZoomLevel, CGFloat) +RCT_EXPORT_VIEW_PROPERTY(kmlSrc, NSString) RCT_EXPORT_METHOD(animateToRegion:(nonnull NSNumber *)reactTag withRegion:(MKCoordinateRegion)region diff --git a/lib/ios/AirMaps.xcodeproj/project.pbxproj b/lib/ios/AirMaps.xcodeproj/project.pbxproj index 33de9f918..4bb684b04 100644 --- a/lib/ios/AirMaps.xcodeproj/project.pbxproj +++ b/lib/ios/AirMaps.xcodeproj/project.pbxproj @@ -29,6 +29,25 @@ 628F81201FD16DF80058313A /* AIRMapLocalTile.m in Sources */ = {isa = PBXBuildFile; fileRef = 628F811F1FD16DF80058313A /* AIRMapLocalTile.m */; }; 628F81231FD16EFA0058313A /* AIRMapLocalTileManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 628F81221FD16EFA0058313A /* AIRMapLocalTileManager.m */; }; 62AEC4D41FD5A0AA003225E0 /* AIRMapLocalTileOverlay.m in Sources */ = {isa = PBXBuildFile; fileRef = 62AEC4D31FD5A0AA003225E0 /* AIRMapLocalTileOverlay.m */; }; + 9B9498CA2017EFB800158761 /* AIRGoogleMapUrlTile.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B9498A62017EFB400158761 /* AIRGoogleMapUrlTile.m */; }; + 9B9498CB2017EFB800158761 /* AIRGoogleMapURLTileManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B9498A72017EFB400158761 /* AIRGoogleMapURLTileManager.m */; }; + 9B9498CC2017EFB800158761 /* AIRGMSPolygon.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B9498A82017EFB400158761 /* AIRGMSPolygon.m */; }; + 9B9498CD2017EFB800158761 /* AIRGoogleMapCallout.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B9498AC2017EFB400158761 /* AIRGoogleMapCallout.m */; }; + 9B9498CE2017EFB800158761 /* AIRGMSMarker.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B9498AE2017EFB500158761 /* AIRGMSMarker.m */; }; + 9B9498CF2017EFB800158761 /* AIRGMSPolyline.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B9498AF2017EFB500158761 /* AIRGMSPolyline.m */; }; + 9B9498D02017EFB800158761 /* AIRGoogleMapPolylineManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B9498B12017EFB500158761 /* AIRGoogleMapPolylineManager.m */; }; + 9B9498D12017EFB800158761 /* AIRGoogleMapCircle.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B9498B32017EFB500158761 /* AIRGoogleMapCircle.m */; }; + 9B9498D22017EFB800158761 /* AIRGoogleMapMarkerManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B9498B52017EFB500158761 /* AIRGoogleMapMarkerManager.m */; }; + 9B9498D32017EFB800158761 /* AIRGoogleMap.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B9498B72017EFB500158761 /* AIRGoogleMap.m */; }; + 9B9498D42017EFB800158761 /* RCTConvert+GMSMapViewType.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B9498B92017EFB600158761 /* RCTConvert+GMSMapViewType.m */; }; + 9B9498D52017EFB800158761 /* AIRGoogleMapPolyline.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B9498BB2017EFB600158761 /* AIRGoogleMapPolyline.m */; }; + 9B9498D62017EFB800158761 /* AIRGoogleMapCircleManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B9498BC2017EFB600158761 /* AIRGoogleMapCircleManager.m */; }; + 9B9498D72017EFB800158761 /* AIRGoogleMapManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B9498BD2017EFB600158761 /* AIRGoogleMapManager.m */; }; + 9B9498D82017EFB800158761 /* DummyView.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B9498BF2017EFB600158761 /* DummyView.m */; }; + 9B9498D92017EFB800158761 /* AIRGoogleMapCalloutManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B9498C42017EFB700158761 /* AIRGoogleMapCalloutManager.m */; }; + 9B9498DA2017EFB800158761 /* AIRGoogleMapPolygon.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B9498C62017EFB800158761 /* AIRGoogleMapPolygon.m */; }; + 9B9498DB2017EFB800158761 /* AIRGoogleMapMarker.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B9498C72017EFB800158761 /* AIRGoogleMapMarker.m */; }; + 9B9498DC2017EFB800158761 /* AIRGoogleMapPolygonManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B9498C92017EFB800158761 /* AIRGoogleMapPolygonManager.m */; }; DA6C26381C9E2AFE0035349F /* AIRMapUrlTile.m in Sources */ = {isa = PBXBuildFile; fileRef = DA6C26371C9E2AFE0035349F /* AIRMapUrlTile.m */; }; DA6C263E1C9E324A0035349F /* AIRMapUrlTileManager.m in Sources */ = {isa = PBXBuildFile; fileRef = DA6C263D1C9E324A0035349F /* AIRMapUrlTileManager.m */; }; /* End PBXBuildFile section */ @@ -90,6 +109,44 @@ 628F81211FD16EAB0058313A /* AIRMapLocalTileManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AIRMapLocalTileManager.h; sourceTree = ""; }; 628F81221FD16EFA0058313A /* AIRMapLocalTileManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AIRMapLocalTileManager.m; sourceTree = ""; }; 62AEC4D31FD5A0AA003225E0 /* AIRMapLocalTileOverlay.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = AIRMapLocalTileOverlay.m; path = AirMaps/AIRMapLocalTileOverlay.m; sourceTree = ""; }; + 9B9498A42017EFB400158761 /* AIRGoogleMapCallout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AIRGoogleMapCallout.h; path = AirGoogleMaps/AIRGoogleMapCallout.h; sourceTree = ""; }; + 9B9498A52017EFB400158761 /* AIRGoogleMapPolygonManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AIRGoogleMapPolygonManager.h; path = AirGoogleMaps/AIRGoogleMapPolygonManager.h; sourceTree = ""; }; + 9B9498A62017EFB400158761 /* AIRGoogleMapUrlTile.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AIRGoogleMapUrlTile.m; path = AirGoogleMaps/AIRGoogleMapUrlTile.m; sourceTree = ""; }; + 9B9498A72017EFB400158761 /* AIRGoogleMapURLTileManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AIRGoogleMapURLTileManager.m; path = AirGoogleMaps/AIRGoogleMapURLTileManager.m; sourceTree = ""; }; + 9B9498A82017EFB400158761 /* AIRGMSPolygon.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AIRGMSPolygon.m; path = AirGoogleMaps/AIRGMSPolygon.m; sourceTree = ""; }; + 9B9498A92017EFB400158761 /* RCTConvert+GMSMapViewType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "RCTConvert+GMSMapViewType.h"; path = "AirGoogleMaps/RCTConvert+GMSMapViewType.h"; sourceTree = ""; }; + 9B9498AA2017EFB400158761 /* AIRGoogleMap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AIRGoogleMap.h; path = AirGoogleMaps/AIRGoogleMap.h; sourceTree = ""; }; + 9B9498AB2017EFB400158761 /* AIRGoogleMapMarkerManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AIRGoogleMapMarkerManager.h; path = AirGoogleMaps/AIRGoogleMapMarkerManager.h; sourceTree = ""; }; + 9B9498AC2017EFB400158761 /* AIRGoogleMapCallout.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AIRGoogleMapCallout.m; path = AirGoogleMaps/AIRGoogleMapCallout.m; sourceTree = ""; }; + 9B9498AD2017EFB400158761 /* AIRGoogleMapUrlTileManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AIRGoogleMapUrlTileManager.h; path = AirGoogleMaps/AIRGoogleMapUrlTileManager.h; sourceTree = ""; }; + 9B9498AE2017EFB500158761 /* AIRGMSMarker.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AIRGMSMarker.m; path = AirGoogleMaps/AIRGMSMarker.m; sourceTree = ""; }; + 9B9498AF2017EFB500158761 /* AIRGMSPolyline.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AIRGMSPolyline.m; path = AirGoogleMaps/AIRGMSPolyline.m; sourceTree = ""; }; + 9B9498B02017EFB500158761 /* AIRGoogleMapCircleManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AIRGoogleMapCircleManager.h; path = AirGoogleMaps/AIRGoogleMapCircleManager.h; sourceTree = ""; }; + 9B9498B12017EFB500158761 /* AIRGoogleMapPolylineManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AIRGoogleMapPolylineManager.m; path = AirGoogleMaps/AIRGoogleMapPolylineManager.m; sourceTree = ""; }; + 9B9498B22017EFB500158761 /* DummyView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DummyView.h; path = AirGoogleMaps/DummyView.h; sourceTree = ""; }; + 9B9498B32017EFB500158761 /* AIRGoogleMapCircle.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AIRGoogleMapCircle.m; path = AirGoogleMaps/AIRGoogleMapCircle.m; sourceTree = ""; }; + 9B9498B42017EFB500158761 /* AIRGMSPolyline.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AIRGMSPolyline.h; path = AirGoogleMaps/AIRGMSPolyline.h; sourceTree = ""; }; + 9B9498B52017EFB500158761 /* AIRGoogleMapMarkerManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AIRGoogleMapMarkerManager.m; path = AirGoogleMaps/AIRGoogleMapMarkerManager.m; sourceTree = ""; }; + 9B9498B62017EFB500158761 /* AIRGoogleMapPolylineManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AIRGoogleMapPolylineManager.h; path = AirGoogleMaps/AIRGoogleMapPolylineManager.h; sourceTree = ""; }; + 9B9498B72017EFB500158761 /* AIRGoogleMap.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AIRGoogleMap.m; path = AirGoogleMaps/AIRGoogleMap.m; sourceTree = ""; }; + 9B9498B82017EFB600158761 /* AIRGoogleMapPolyline.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AIRGoogleMapPolyline.h; path = AirGoogleMaps/AIRGoogleMapPolyline.h; sourceTree = ""; }; + 9B9498B92017EFB600158761 /* RCTConvert+GMSMapViewType.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "RCTConvert+GMSMapViewType.m"; path = "AirGoogleMaps/RCTConvert+GMSMapViewType.m"; sourceTree = ""; }; + 9B9498BA2017EFB600158761 /* AIRGMSPolygon.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AIRGMSPolygon.h; path = AirGoogleMaps/AIRGMSPolygon.h; sourceTree = ""; }; + 9B9498BB2017EFB600158761 /* AIRGoogleMapPolyline.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AIRGoogleMapPolyline.m; path = AirGoogleMaps/AIRGoogleMapPolyline.m; sourceTree = ""; }; + 9B9498BC2017EFB600158761 /* AIRGoogleMapCircleManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AIRGoogleMapCircleManager.m; path = AirGoogleMaps/AIRGoogleMapCircleManager.m; sourceTree = ""; }; + 9B9498BD2017EFB600158761 /* AIRGoogleMapManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AIRGoogleMapManager.m; path = AirGoogleMaps/AIRGoogleMapManager.m; sourceTree = ""; }; + 9B9498BE2017EFB600158761 /* AIRGoogleMapManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AIRGoogleMapManager.h; path = AirGoogleMaps/AIRGoogleMapManager.h; sourceTree = ""; }; + 9B9498BF2017EFB600158761 /* DummyView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = DummyView.m; path = AirGoogleMaps/DummyView.m; sourceTree = ""; }; + 9B9498C02017EFB700158761 /* AIRGoogleMapMarker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AIRGoogleMapMarker.h; path = AirGoogleMaps/AIRGoogleMapMarker.h; sourceTree = ""; }; + 9B9498C12017EFB700158761 /* AIRGMSMarker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AIRGMSMarker.h; path = AirGoogleMaps/AIRGMSMarker.h; sourceTree = ""; }; + 9B9498C22017EFB700158761 /* AIRGoogleMapCircle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AIRGoogleMapCircle.h; path = AirGoogleMaps/AIRGoogleMapCircle.h; sourceTree = ""; }; + 9B9498C32017EFB700158761 /* AIRGoogleMapPolygon.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AIRGoogleMapPolygon.h; path = AirGoogleMaps/AIRGoogleMapPolygon.h; sourceTree = ""; }; + 9B9498C42017EFB700158761 /* AIRGoogleMapCalloutManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AIRGoogleMapCalloutManager.m; path = AirGoogleMaps/AIRGoogleMapCalloutManager.m; sourceTree = ""; }; + 9B9498C52017EFB800158761 /* AIRGoogleMapCalloutManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AIRGoogleMapCalloutManager.h; path = AirGoogleMaps/AIRGoogleMapCalloutManager.h; sourceTree = ""; }; + 9B9498C62017EFB800158761 /* AIRGoogleMapPolygon.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AIRGoogleMapPolygon.m; path = AirGoogleMaps/AIRGoogleMapPolygon.m; sourceTree = ""; }; + 9B9498C72017EFB800158761 /* AIRGoogleMapMarker.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AIRGoogleMapMarker.m; path = AirGoogleMaps/AIRGoogleMapMarker.m; sourceTree = ""; }; + 9B9498C82017EFB800158761 /* AIRGoogleMapUrlTile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AIRGoogleMapUrlTile.h; path = AirGoogleMaps/AIRGoogleMapUrlTile.h; sourceTree = ""; }; + 9B9498C92017EFB800158761 /* AIRGoogleMapPolygonManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AIRGoogleMapPolygonManager.m; path = AirGoogleMaps/AIRGoogleMapPolygonManager.m; sourceTree = ""; }; DA6C26361C9E2AFE0035349F /* AIRMapUrlTile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRMapUrlTile.h; sourceTree = ""; }; DA6C26371C9E2AFE0035349F /* AIRMapUrlTile.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRMapUrlTile.m; sourceTree = ""; }; DA6C263C1C9E324A0035349F /* AIRMapUrlTileManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRMapUrlTileManager.h; sourceTree = ""; }; @@ -110,6 +167,7 @@ 11FA5C481C4A1296003AC2EE = { isa = PBXGroup; children = ( + 9B9498A32017EF9D00158761 /* AirGoogleMaps */, 62AEC4D31FD5A0AA003225E0 /* AIRMapLocalTileOverlay.m */, 11FA5C531C4A1296003AC2EE /* AirMaps */, 11FA5C521C4A1296003AC2EE /* Products */, @@ -177,6 +235,51 @@ path = AirMaps; sourceTree = ""; }; + 9B9498A32017EF9D00158761 /* AirGoogleMaps */ = { + isa = PBXGroup; + children = ( + 9B9498C12017EFB700158761 /* AIRGMSMarker.h */, + 9B9498AE2017EFB500158761 /* AIRGMSMarker.m */, + 9B9498BA2017EFB600158761 /* AIRGMSPolygon.h */, + 9B9498A82017EFB400158761 /* AIRGMSPolygon.m */, + 9B9498B42017EFB500158761 /* AIRGMSPolyline.h */, + 9B9498AF2017EFB500158761 /* AIRGMSPolyline.m */, + 9B9498AA2017EFB400158761 /* AIRGoogleMap.h */, + 9B9498B72017EFB500158761 /* AIRGoogleMap.m */, + 9B9498A42017EFB400158761 /* AIRGoogleMapCallout.h */, + 9B9498AC2017EFB400158761 /* AIRGoogleMapCallout.m */, + 9B9498C52017EFB800158761 /* AIRGoogleMapCalloutManager.h */, + 9B9498C42017EFB700158761 /* AIRGoogleMapCalloutManager.m */, + 9B9498C22017EFB700158761 /* AIRGoogleMapCircle.h */, + 9B9498B32017EFB500158761 /* AIRGoogleMapCircle.m */, + 9B9498B02017EFB500158761 /* AIRGoogleMapCircleManager.h */, + 9B9498BC2017EFB600158761 /* AIRGoogleMapCircleManager.m */, + 9B9498BE2017EFB600158761 /* AIRGoogleMapManager.h */, + 9B9498BD2017EFB600158761 /* AIRGoogleMapManager.m */, + 9B9498C02017EFB700158761 /* AIRGoogleMapMarker.h */, + 9B9498C72017EFB800158761 /* AIRGoogleMapMarker.m */, + 9B9498AB2017EFB400158761 /* AIRGoogleMapMarkerManager.h */, + 9B9498B52017EFB500158761 /* AIRGoogleMapMarkerManager.m */, + 9B9498C32017EFB700158761 /* AIRGoogleMapPolygon.h */, + 9B9498C62017EFB800158761 /* AIRGoogleMapPolygon.m */, + 9B9498A52017EFB400158761 /* AIRGoogleMapPolygonManager.h */, + 9B9498C92017EFB800158761 /* AIRGoogleMapPolygonManager.m */, + 9B9498B82017EFB600158761 /* AIRGoogleMapPolyline.h */, + 9B9498BB2017EFB600158761 /* AIRGoogleMapPolyline.m */, + 9B9498B62017EFB500158761 /* AIRGoogleMapPolylineManager.h */, + 9B9498B12017EFB500158761 /* AIRGoogleMapPolylineManager.m */, + 9B9498C82017EFB800158761 /* AIRGoogleMapUrlTile.h */, + 9B9498A62017EFB400158761 /* AIRGoogleMapUrlTile.m */, + 9B9498AD2017EFB400158761 /* AIRGoogleMapUrlTileManager.h */, + 9B9498A72017EFB400158761 /* AIRGoogleMapURLTileManager.m */, + 9B9498B22017EFB500158761 /* DummyView.h */, + 9B9498BF2017EFB600158761 /* DummyView.m */, + 9B9498A92017EFB400158761 /* RCTConvert+GMSMapViewType.h */, + 9B9498B92017EFB600158761 /* RCTConvert+GMSMapViewType.m */, + ); + name = AirGoogleMaps; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -234,27 +337,46 @@ buildActionMask = 2147483647; files = ( 62AEC4D41FD5A0AA003225E0 /* AIRMapLocalTileOverlay.m in Sources */, + 9B9498DC2017EFB800158761 /* AIRGoogleMapPolygonManager.m in Sources */, 1125B2E31C4AD3DA007D0023 /* AIRMapPolygon.m in Sources */, 1125B2E41C4AD3DA007D0023 /* AIRMapPolygonManager.m in Sources */, + 9B9498CB2017EFB800158761 /* AIRGoogleMapURLTileManager.m in Sources */, 1125B2DB1C4AD3DA007D0023 /* AIRMapCallout.m in Sources */, 53D31636202E723B00B55447 /* AIRMapOverlayManager.m in Sources */, 1125B2E01C4AD3DA007D0023 /* AIRMapManager.m in Sources */, 1125B2E61C4AD3DA007D0023 /* AIRMapPolylineManager.m in Sources */, + 9B9498DA2017EFB800158761 /* AIRGoogleMapPolygon.m in Sources */, + 9B9498D12017EFB800158761 /* AIRGoogleMapCircle.m in Sources */, 1125B2DD1C4AD3DA007D0023 /* AIRMapCircle.m in Sources */, + 9B9498CE2017EFB800158761 /* AIRGMSMarker.m in Sources */, + 9B9498D72017EFB800158761 /* AIRGoogleMapManager.m in Sources */, 19DABC7F1E7C9D3C00F41150 /* RCTConvert+AirMap.m in Sources */, 1125B2E51C4AD3DA007D0023 /* AIRMapPolyline.m in Sources */, + 9B9498D82017EFB800158761 /* DummyView.m in Sources */, + 9B9498D52017EFB800158761 /* AIRGoogleMapPolyline.m in Sources */, + 9B9498CF2017EFB800158761 /* AIRGMSPolyline.m in Sources */, + 9B9498D42017EFB800158761 /* RCTConvert+GMSMapViewType.m in Sources */, + 9B9498D32017EFB800158761 /* AIRGoogleMap.m in Sources */, DA6C263E1C9E324A0035349F /* AIRMapUrlTileManager.m in Sources */, - 53D3163A202E72FC00B55447 /* AIRMapOverlay.m in Sources */, + 9B9498DB2017EFB800158761 /* AIRGoogleMapMarker.m in Sources */, 628F81201FD16DF80058313A /* AIRMapLocalTile.m in Sources */, + 9B9498D92017EFB800158761 /* AIRGoogleMapCalloutManager.m in Sources */, + 53D3163A202E72FC00B55447 /* AIRMapOverlay.m in Sources */, 53D3163D202E734F00B55447 /* AIRMapOverlayRenderer.m in Sources */, 1125B2DA1C4AD3DA007D0023 /* AIRMap.m in Sources */, 1125B2DF1C4AD3DA007D0023 /* AIRMapCoordinate.m in Sources */, + 9B9498D62017EFB800158761 /* AIRGoogleMapCircleManager.m in Sources */, 1125B2F21C4AD445007D0023 /* SMCalloutView.m in Sources */, 2163AA501FEAEDD100BBEC95 /* AIRMapPolylineRenderer.m in Sources */, + 9B9498D02017EFB800158761 /* AIRGoogleMapPolylineManager.m in Sources */, 1125B2E11C4AD3DA007D0023 /* AIRMapMarker.m in Sources */, + 9B9498CA2017EFB800158761 /* AIRGoogleMapUrlTile.m in Sources */, + 9B9498CD2017EFB800158761 /* AIRGoogleMapCallout.m in Sources */, 1125B2E21C4AD3DA007D0023 /* AIRMapMarkerManager.m in Sources */, DA6C26381C9E2AFE0035349F /* AIRMapUrlTile.m in Sources */, 628F81231FD16EFA0058313A /* AIRMapLocalTileManager.m in Sources */, + 9B9498D22017EFB800158761 /* AIRGoogleMapMarkerManager.m in Sources */, + 9B9498CC2017EFB800158761 /* AIRGMSPolygon.m in Sources */, 1125B2DE1C4AD3DA007D0023 /* AIRMapCircleManager.m in Sources */, 1125B2DC1C4AD3DA007D0023 /* AIRMapCalloutManager.m in Sources */, ); diff --git a/lib/ios/AirMaps/AIRMapManager.m b/lib/ios/AirMaps/AIRMapManager.m index d81684a2c..cfc3f3c46 100644 --- a/lib/ios/AirMaps/AIRMapManager.m +++ b/lib/ios/AirMaps/AIRMapManager.m @@ -75,6 +75,7 @@ - (UIView *)view RCT_EXPORT_VIEW_PROPERTY(showsScale, BOOL) RCT_EXPORT_VIEW_PROPERTY(showsTraffic, BOOL) RCT_EXPORT_VIEW_PROPERTY(zoomEnabled, BOOL) +RCT_EXPORT_VIEW_PROPERTY(kmlSrc, NSString) RCT_EXPORT_VIEW_PROPERTY(rotateEnabled, BOOL) RCT_EXPORT_VIEW_PROPERTY(scrollEnabled, BOOL) RCT_EXPORT_VIEW_PROPERTY(pitchEnabled, BOOL) diff --git a/react-native-google-maps.podspec b/react-native-google-maps.podspec index 51dc01da1..92379cef6 100644 --- a/react-native-google-maps.podspec +++ b/react-native-google-maps.podspec @@ -18,4 +18,5 @@ Pod::Spec.new do |s| s.dependency 'React' s.dependency 'GoogleMaps', '2.5.0' + s.dependency 'Google-Maps-iOS-Utils', '2.1.0' end diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 000000000..601e05442 --- /dev/null +++ b/yarn.lock @@ -0,0 +1,6000 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +JSONStream@~1.3.1: + version "1.3.2" + resolved "https://registry.yarnpkg.com/JSONStream/-/JSONStream-1.3.2.tgz#c102371b6ec3a7cf3b847ca00c20bb0fce4c6dea" + dependencies: + jsonparse "^1.2.0" + through ">=2.2.7 <3" + +abbrev@1, abbrev@~1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" + +abbrev@~1.0.9: + version "1.0.9" + resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.0.9.tgz#91b4792588a7738c25f35dd6f63752a2f8776135" + +absolute-path@^0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/absolute-path/-/absolute-path-0.0.0.tgz#a78762fbdadfb5297be99b15d35a785b2f095bf7" + +accepts@~1.2.12, accepts@~1.2.13: + version "1.2.13" + resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.2.13.tgz#e5f1f3928c6d95fd96558c36ec3d9d0de4a6ecea" + dependencies: + mime-types "~2.1.6" + negotiator "0.5.3" + +accepts@~1.3.0: + version "1.3.4" + resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.4.tgz#86246758c7dd6d21a6474ff084a4740ec05eb21f" + dependencies: + mime-types "~2.1.16" + negotiator "0.6.1" + +acorn-jsx@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-3.0.1.tgz#afdf9488fb1ecefc8348f6fb22f464e32a58b36b" + dependencies: + acorn "^3.0.4" + +acorn@^3.0.4: + version "3.3.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-3.3.0.tgz#45e37fb39e8da3f25baee3ff5369e2bb5f22017a" + +acorn@^5.2.1: + version "5.3.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.3.0.tgz#7446d39459c54fb49a80e6ee6478149b940ec822" + +agent-base@4, agent-base@^4.1.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.2.0.tgz#9838b5c3392b962bad031e6a4c5e1024abec45ce" + dependencies: + es6-promisify "^5.0.0" + +agentkeepalive@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/agentkeepalive/-/agentkeepalive-3.3.0.tgz#6d5de5829afd3be2712201a39275fd11c651857c" + dependencies: + humanize-ms "^1.2.1" + +ajv-keywords@^1.0.0: + version "1.5.1" + resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-1.5.1.tgz#314dd0a4b3368fad3dfcdc54ede6171b886daf3c" + +ajv@^4.7.0, ajv@^4.9.1: + version "4.11.8" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.11.8.tgz#82ffb02b29e662ae53bdc20af15947706739c536" + dependencies: + co "^4.6.0" + json-stable-stringify "^1.0.1" + +ajv@^5.1.0: + version "5.5.2" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.5.2.tgz#73b5eeca3fab653e3d3f9422b341ad42205dc965" + dependencies: + co "^4.6.0" + fast-deep-equal "^1.0.0" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.3.0" + +ansi-align@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ansi-align/-/ansi-align-2.0.0.tgz#c36aeccba563b89ceb556f3690f0b1d9e3547f7f" + dependencies: + string-width "^2.0.0" + +ansi-escapes@^1.1.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-1.4.0.tgz#d3a8a83b319aa67793662b13e761c7911422306e" + +ansi-escapes@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.0.0.tgz#ec3e8b4e9f8064fc02c3ac9b65f1c275bda8ef92" + +ansi-gray@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/ansi-gray/-/ansi-gray-0.1.1.tgz#2962cf54ec9792c48510a3deb524436861ef7251" + dependencies: + ansi-wrap "0.1.0" + +ansi-regex@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" + +ansi-regex@^3.0.0, ansi-regex@~3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" + +ansi-styles@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" + +ansi-styles@^3.1.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.0.tgz#c159b8d5be0f9e5a6f346dab94f16ce022161b88" + dependencies: + color-convert "^1.9.0" + +ansi-wrap@0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/ansi-wrap/-/ansi-wrap-0.1.0.tgz#a82250ddb0015e9a27ca82e82ea603bbfa45efaf" + +ansi@^0.3.0, ansi@~0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/ansi/-/ansi-0.3.1.tgz#0c42d4fb17160d5a9af1e484bace1c66922c1b21" + +ansicolors@~0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/ansicolors/-/ansicolors-0.3.2.tgz#665597de86a9ffe3aa9bfbe6cae5c6ea426b4979" + +ansistyles@~0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/ansistyles/-/ansistyles-0.1.3.tgz#5de60415bda071bb37127854c864f41b23254539" + +anymatch@^1.3.0: + version "1.3.2" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-1.3.2.tgz#553dcb8f91e3c889845dfdba34c77721b90b9d7a" + dependencies: + micromatch "^2.1.5" + normalize-path "^2.0.0" + +aproba@^1.0.3, aproba@^1.1.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" + +aproba@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.1.2.tgz#45c6629094de4e96f693ef7eab74ae079c240fc1" + +arch@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/arch/-/arch-2.1.0.tgz#3613aa46149064b3c1f0607919bf1d4786e82889" + +archy@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/archy/-/archy-1.0.0.tgz#f9c8c13757cc1dd7bc379ac77b2c62a5c2868c40" + +are-we-there-yet@~1.1.2: + version "1.1.4" + resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.4.tgz#bb5dca382bb94f05e15194373d16fd3ba1ca110d" + dependencies: + delegates "^1.0.0" + readable-stream "^2.0.6" + +argparse@^1.0.7: + version "1.0.9" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.9.tgz#73d83bc263f86e97f8cc4f6bae1b0e90a7d22c86" + dependencies: + sprintf-js "~1.0.2" + +arr-diff@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-2.0.0.tgz#8f3b827f955a8bd669697e4a4256ac3ceae356cf" + dependencies: + arr-flatten "^1.0.1" + +arr-flatten@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" + +array-differ@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/array-differ/-/array-differ-1.0.0.tgz#eff52e3758249d33be402b8bb8e564bb2b5d4031" + +array-filter@~0.0.0: + version "0.0.1" + resolved "https://registry.yarnpkg.com/array-filter/-/array-filter-0.0.1.tgz#7da8cf2e26628ed732803581fd21f67cacd2eeec" + +array-map@~0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/array-map/-/array-map-0.0.0.tgz#88a2bab73d1cf7bcd5c1b118a003f66f665fa662" + +array-reduce@~0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/array-reduce/-/array-reduce-0.0.0.tgz#173899d3ffd1c7d9383e4479525dbe278cab5f2b" + +array-union@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39" + dependencies: + array-uniq "^1.0.1" + +array-uniq@^1.0.1, array-uniq@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" + +array-unique@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.2.1.tgz#a1d97ccafcbc2625cc70fadceb36a50c58b01a53" + +array.prototype.find@^2.0.1: + version "2.0.4" + resolved "https://registry.yarnpkg.com/array.prototype.find/-/array.prototype.find-2.0.4.tgz#556a5c5362c08648323ddaeb9de9d14bc1864c90" + dependencies: + define-properties "^1.1.2" + es-abstract "^1.7.0" + +arrify@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" + +art@^0.10.0: + version "0.10.1" + resolved "https://registry.yarnpkg.com/art/-/art-0.10.1.tgz#38541883e399225c5e193ff246e8f157cf7b2146" + +asap@^2.0.0, asap@~2.0.3: + version "2.0.6" + resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" + +asn1@~0.2.3: + version "0.2.3" + resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.3.tgz#dac8787713c9966849fc8180777ebe9c1ddf3b86" + +assert-plus@1.0.0, assert-plus@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" + +assert-plus@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-0.2.0.tgz#d74e1b87e7affc0db8aadb7021f3fe48101ab234" + +async-some@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/async-some/-/async-some-1.0.2.tgz#4d8a81620d5958791b5b98f802d3207776e95509" + dependencies: + dezalgo "^1.0.2" + +async@^2.0.1, async@^2.4.0: + version "2.6.0" + resolved "https://registry.yarnpkg.com/async/-/async-2.6.0.tgz#61a29abb6fcc026fea77e56d1c6ec53a795951f4" + dependencies: + lodash "^4.14.0" + +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + +aws-sign2@~0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.6.0.tgz#14342dd38dbcc94d0e5b87d763cd63612c0e794f" + +aws-sign2@~0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" + +aws4@^1.2.1, aws4@^1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.6.0.tgz#83ef5ca860b2b32e4a0deedee8c771b9db57471e" + +babel-code-frame@^6.16.0, babel-code-frame@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" + dependencies: + chalk "^1.1.3" + esutils "^2.0.2" + js-tokens "^3.0.2" + +babel-core@^6.24.1, babel-core@^6.26.0, babel-core@^6.7.2: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.26.0.tgz#af32f78b31a6fcef119c87b0fd8d9753f03a0bb8" + dependencies: + babel-code-frame "^6.26.0" + babel-generator "^6.26.0" + babel-helpers "^6.24.1" + babel-messages "^6.23.0" + babel-register "^6.26.0" + babel-runtime "^6.26.0" + babel-template "^6.26.0" + babel-traverse "^6.26.0" + babel-types "^6.26.0" + babylon "^6.18.0" + convert-source-map "^1.5.0" + debug "^2.6.8" + json5 "^0.5.1" + lodash "^4.17.4" + minimatch "^3.0.4" + path-is-absolute "^1.0.1" + private "^0.1.7" + slash "^1.0.0" + source-map "^0.5.6" + +babel-eslint@^6.1.2: + version "6.1.2" + resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-6.1.2.tgz#5293419fe3672d66598d327da9694567ba6a5f2f" + dependencies: + babel-traverse "^6.0.20" + babel-types "^6.0.19" + babylon "^6.0.18" + lodash.assign "^4.0.0" + lodash.pickby "^4.0.0" + +babel-generator@^6.24.1, babel-generator@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.26.0.tgz#ac1ae20070b79f6e3ca1d3269613053774f20dc5" + dependencies: + babel-messages "^6.23.0" + babel-runtime "^6.26.0" + babel-types "^6.26.0" + detect-indent "^4.0.0" + jsesc "^1.3.0" + lodash "^4.17.4" + source-map "^0.5.6" + trim-right "^1.0.1" + +babel-helper-builder-binary-assignment-operator-visitor@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz#cce4517ada356f4220bcae8a02c2b346f9a56664" + dependencies: + babel-helper-explode-assignable-expression "^6.24.1" + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-helper-builder-react-jsx@^6.24.1: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-helper-builder-react-jsx/-/babel-helper-builder-react-jsx-6.26.0.tgz#39ff8313b75c8b65dceff1f31d383e0ff2a408a0" + dependencies: + babel-runtime "^6.26.0" + babel-types "^6.26.0" + esutils "^2.0.2" + +babel-helper-call-delegate@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz#ece6aacddc76e41c3461f88bfc575bd0daa2df8d" + dependencies: + babel-helper-hoist-variables "^6.24.1" + babel-runtime "^6.22.0" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-helper-define-map@^6.24.1: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz#a5f56dab41a25f97ecb498c7ebaca9819f95be5f" + dependencies: + babel-helper-function-name "^6.24.1" + babel-runtime "^6.26.0" + babel-types "^6.26.0" + lodash "^4.17.4" + +babel-helper-explode-assignable-expression@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz#f25b82cf7dc10433c55f70592d5746400ac22caa" + dependencies: + babel-runtime "^6.22.0" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-helper-function-name@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz#d3475b8c03ed98242a25b48351ab18399d3580a9" + dependencies: + babel-helper-get-function-arity "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-helper-get-function-arity@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz#8f7782aa93407c41d3aa50908f89b031b1b6853d" + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-helper-hoist-variables@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz#1ecb27689c9d25513eadbc9914a73f5408be7a76" + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-helper-optimise-call-expression@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz#f7a13427ba9f73f8f4fa993c54a97882d1244257" + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-helper-regex@^6.24.1: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz#325c59f902f82f24b74faceed0363954f6495e72" + dependencies: + babel-runtime "^6.26.0" + babel-types "^6.26.0" + lodash "^4.17.4" + +babel-helper-remap-async-to-generator@^6.16.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz#5ec581827ad723fecdd381f1c928390676e4551b" + dependencies: + babel-helper-function-name "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-helper-replace-supers@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz#bf6dbfe43938d17369a213ca8a8bf74b6a90ab1a" + dependencies: + babel-helper-optimise-call-expression "^6.24.1" + babel-messages "^6.23.0" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-helpers@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helpers/-/babel-helpers-6.24.1.tgz#3471de9caec388e5c850e597e58a26ddf37602b2" + dependencies: + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-messages@^6.23.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-messages/-/babel-messages-6.23.0.tgz#f3cdf4703858035b2a2951c6ec5edf6c62f2630e" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-check-es2015-constants@^6.22.0, babel-plugin-check-es2015-constants@^6.5.0, babel-plugin-check-es2015-constants@^6.8.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz#35157b101426fd2ffd3da3f75c7d1e91835bbf8a" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-external-helpers@^6.18.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-external-helpers/-/babel-plugin-external-helpers-6.22.0.tgz#2285f48b02bd5dede85175caf8c62e86adccefa1" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-module-resolver@^2.3.0: + version "2.7.1" + resolved "https://registry.yarnpkg.com/babel-plugin-module-resolver/-/babel-plugin-module-resolver-2.7.1.tgz#18be3c42ddf59f7a456c9e0512cd91394f6e4be1" + dependencies: + find-babel-config "^1.0.1" + glob "^7.1.1" + resolve "^1.2.0" + +babel-plugin-react-transform@2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/babel-plugin-react-transform/-/babel-plugin-react-transform-2.0.2.tgz#515bbfa996893981142d90b1f9b1635de2995109" + dependencies: + lodash "^4.6.1" + +babel-plugin-react-transform@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/babel-plugin-react-transform/-/babel-plugin-react-transform-3.0.0.tgz#402f25137b7bb66e9b54ead75557dfbc7ecaaa74" + dependencies: + lodash "^4.6.1" + +babel-plugin-syntax-async-functions@^6.5.0, babel-plugin-syntax-async-functions@^6.8.0: + version "6.13.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz#cad9cad1191b5ad634bf30ae0872391e0647be95" + +babel-plugin-syntax-class-properties@^6.5.0, babel-plugin-syntax-class-properties@^6.8.0: + version "6.13.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz#d7eb23b79a317f8543962c505b827c7d6cac27de" + +babel-plugin-syntax-dynamic-import@^6.18.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz#8d6a26229c83745a9982a441051572caa179b1da" + +babel-plugin-syntax-exponentiation-operator@^6.8.0: + version "6.13.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz#9ee7e8337290da95288201a6a57f4170317830de" + +babel-plugin-syntax-flow@^6.18.0, babel-plugin-syntax-flow@^6.5.0, babel-plugin-syntax-flow@^6.8.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-flow/-/babel-plugin-syntax-flow-6.18.0.tgz#4c3ab20a2af26aa20cd25995c398c4eb70310c8d" + +babel-plugin-syntax-jsx@^6.3.13, babel-plugin-syntax-jsx@^6.5.0, babel-plugin-syntax-jsx@^6.8.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz#0af32a9a6e13ca7a3fd5069e62d7b0f58d0d8946" + +babel-plugin-syntax-object-rest-spread@^6.8.0: + version "6.13.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz#fd6536f2bce13836ffa3a5458c4903a597bb3bf5" + +babel-plugin-syntax-trailing-function-commas@^6.20.0, babel-plugin-syntax-trailing-function-commas@^6.5.0, babel-plugin-syntax-trailing-function-commas@^6.8.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz#ba0360937f8d06e40180a43fe0d5616fff532cf3" + +babel-plugin-transform-async-to-generator@6.16.0: + version "6.16.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.16.0.tgz#19ec36cb1486b59f9f468adfa42ce13908ca2999" + dependencies: + babel-helper-remap-async-to-generator "^6.16.0" + babel-plugin-syntax-async-functions "^6.8.0" + babel-runtime "^6.0.0" + +babel-plugin-transform-class-properties@^6.18.0, babel-plugin-transform-class-properties@^6.5.0, babel-plugin-transform-class-properties@^6.8.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-class-properties/-/babel-plugin-transform-class-properties-6.24.1.tgz#6a79763ea61d33d36f37b611aa9def81a81b46ac" + dependencies: + babel-helper-function-name "^6.24.1" + babel-plugin-syntax-class-properties "^6.8.0" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-plugin-transform-es2015-arrow-functions@^6.22.0, babel-plugin-transform-es2015-arrow-functions@^6.5.0, babel-plugin-transform-es2015-arrow-functions@^6.8.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz#452692cb711d5f79dc7f85e440ce41b9f244d221" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-block-scoped-functions@^6.22.0, babel-plugin-transform-es2015-block-scoped-functions@^6.8.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz#bbc51b49f964d70cb8d8e0b94e820246ce3a6141" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-block-scoping@^6.24.1, babel-plugin-transform-es2015-block-scoping@^6.5.0, babel-plugin-transform-es2015-block-scoping@^6.8.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz#d70f5299c1308d05c12f463813b0a09e73b1895f" + dependencies: + babel-runtime "^6.26.0" + babel-template "^6.26.0" + babel-traverse "^6.26.0" + babel-types "^6.26.0" + lodash "^4.17.4" + +babel-plugin-transform-es2015-classes@^6.24.1, babel-plugin-transform-es2015-classes@^6.5.0, babel-plugin-transform-es2015-classes@^6.8.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz#5a4c58a50c9c9461e564b4b2a3bfabc97a2584db" + dependencies: + babel-helper-define-map "^6.24.1" + babel-helper-function-name "^6.24.1" + babel-helper-optimise-call-expression "^6.24.1" + babel-helper-replace-supers "^6.24.1" + babel-messages "^6.23.0" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-computed-properties@^6.24.1, babel-plugin-transform-es2015-computed-properties@^6.5.0, babel-plugin-transform-es2015-computed-properties@^6.8.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz#6fe2a8d16895d5634f4cd999b6d3480a308159b3" + dependencies: + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-plugin-transform-es2015-destructuring@6.x, babel-plugin-transform-es2015-destructuring@^6.22.0, babel-plugin-transform-es2015-destructuring@^6.5.0, babel-plugin-transform-es2015-destructuring@^6.8.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz#997bb1f1ab967f682d2b0876fe358d60e765c56d" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-duplicate-keys@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz#73eb3d310ca969e3ef9ec91c53741a6f1576423e" + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-for-of@^6.22.0, babel-plugin-transform-es2015-for-of@^6.5.0, babel-plugin-transform-es2015-for-of@^6.8.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz#f47c95b2b613df1d3ecc2fdb7573623c75248691" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-function-name@6.x, babel-plugin-transform-es2015-function-name@^6.24.1, babel-plugin-transform-es2015-function-name@^6.5.0, babel-plugin-transform-es2015-function-name@^6.8.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz#834c89853bc36b1af0f3a4c5dbaa94fd8eacaa8b" + dependencies: + babel-helper-function-name "^6.24.1" + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-literals@^6.22.0, babel-plugin-transform-es2015-literals@^6.5.0, babel-plugin-transform-es2015-literals@^6.8.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz#4f54a02d6cd66cf915280019a31d31925377ca2e" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-modules-amd@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz#3b3e54017239842d6d19c3011c4bd2f00a00d154" + dependencies: + babel-plugin-transform-es2015-modules-commonjs "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-plugin-transform-es2015-modules-commonjs@6.x, babel-plugin-transform-es2015-modules-commonjs@^6.24.1, babel-plugin-transform-es2015-modules-commonjs@^6.5.0, babel-plugin-transform-es2015-modules-commonjs@^6.8.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.0.tgz#0d8394029b7dc6abe1a97ef181e00758dd2e5d8a" + dependencies: + babel-plugin-transform-strict-mode "^6.24.1" + babel-runtime "^6.26.0" + babel-template "^6.26.0" + babel-types "^6.26.0" + +babel-plugin-transform-es2015-modules-systemjs@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz#ff89a142b9119a906195f5f106ecf305d9407d23" + dependencies: + babel-helper-hoist-variables "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-plugin-transform-es2015-modules-umd@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz#ac997e6285cd18ed6176adb607d602344ad38468" + dependencies: + babel-plugin-transform-es2015-modules-amd "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-plugin-transform-es2015-object-super@^6.24.1, babel-plugin-transform-es2015-object-super@^6.8.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz#24cef69ae21cb83a7f8603dad021f572eb278f8d" + dependencies: + babel-helper-replace-supers "^6.24.1" + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-parameters@6.x, babel-plugin-transform-es2015-parameters@^6.24.1, babel-plugin-transform-es2015-parameters@^6.5.0, babel-plugin-transform-es2015-parameters@^6.8.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz#57ac351ab49caf14a97cd13b09f66fdf0a625f2b" + dependencies: + babel-helper-call-delegate "^6.24.1" + babel-helper-get-function-arity "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-shorthand-properties@6.x, babel-plugin-transform-es2015-shorthand-properties@^6.24.1, babel-plugin-transform-es2015-shorthand-properties@^6.5.0, babel-plugin-transform-es2015-shorthand-properties@^6.8.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz#24f875d6721c87661bbd99a4622e51f14de38aa0" + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-spread@6.x, babel-plugin-transform-es2015-spread@^6.22.0, babel-plugin-transform-es2015-spread@^6.5.0, babel-plugin-transform-es2015-spread@^6.8.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz#d6d68a99f89aedc4536c81a542e8dd9f1746f8d1" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-sticky-regex@6.x, babel-plugin-transform-es2015-sticky-regex@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz#00c1cdb1aca71112cdf0cf6126c2ed6b457ccdbc" + dependencies: + babel-helper-regex "^6.24.1" + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-template-literals@^6.22.0, babel-plugin-transform-es2015-template-literals@^6.5.0, babel-plugin-transform-es2015-template-literals@^6.8.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz#a84b3450f7e9f8f1f6839d6d687da84bb1236d8d" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-typeof-symbol@^6.22.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz#dec09f1cddff94b52ac73d505c84df59dcceb372" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-unicode-regex@6.x, babel-plugin-transform-es2015-unicode-regex@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz#d38b12f42ea7323f729387f18a7c5ae1faeb35e9" + dependencies: + babel-helper-regex "^6.24.1" + babel-runtime "^6.22.0" + regexpu-core "^2.0.0" + +babel-plugin-transform-es3-member-expression-literals@^6.5.0, babel-plugin-transform-es3-member-expression-literals@^6.8.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es3-member-expression-literals/-/babel-plugin-transform-es3-member-expression-literals-6.22.0.tgz#733d3444f3ecc41bef8ed1a6a4e09657b8969ebb" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es3-property-literals@^6.5.0, babel-plugin-transform-es3-property-literals@^6.8.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es3-property-literals/-/babel-plugin-transform-es3-property-literals-6.22.0.tgz#b2078d5842e22abf40f73e8cde9cd3711abd5758" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-exponentiation-operator@^6.5.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz#2ab0c9c7f3098fa48907772bb813fe41e8de3a0e" + dependencies: + babel-helper-builder-binary-assignment-operator-visitor "^6.24.1" + babel-plugin-syntax-exponentiation-operator "^6.8.0" + babel-runtime "^6.22.0" + +babel-plugin-transform-flow-strip-types@^6.21.0, babel-plugin-transform-flow-strip-types@^6.22.0, babel-plugin-transform-flow-strip-types@^6.5.0, babel-plugin-transform-flow-strip-types@^6.8.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-flow-strip-types/-/babel-plugin-transform-flow-strip-types-6.22.0.tgz#84cb672935d43714fdc32bce84568d87441cf7cf" + dependencies: + babel-plugin-syntax-flow "^6.18.0" + babel-runtime "^6.22.0" + +babel-plugin-transform-jscript@^6.5.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-jscript/-/babel-plugin-transform-jscript-6.22.0.tgz#6e8af12b7aba49e0a809152616ac05690b3352dc" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-object-assign@^6.5.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-object-assign/-/babel-plugin-transform-object-assign-6.22.0.tgz#f99d2f66f1a0b0d498e346c5359684740caa20ba" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-object-rest-spread@^6.20.2, babel-plugin-transform-object-rest-spread@^6.5.0, babel-plugin-transform-object-rest-spread@^6.8.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.26.0.tgz#0f36692d50fef6b7e2d4b3ac1478137a963b7b06" + dependencies: + babel-plugin-syntax-object-rest-spread "^6.8.0" + babel-runtime "^6.26.0" + +babel-plugin-transform-react-display-name@^6.23.0, babel-plugin-transform-react-display-name@^6.5.0, babel-plugin-transform-react-display-name@^6.8.0: + version "6.25.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-display-name/-/babel-plugin-transform-react-display-name-6.25.0.tgz#67e2bf1f1e9c93ab08db96792e05392bf2cc28d1" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-react-jsx-self@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-jsx-self/-/babel-plugin-transform-react-jsx-self-6.22.0.tgz#df6d80a9da2612a121e6ddd7558bcbecf06e636e" + dependencies: + babel-plugin-syntax-jsx "^6.8.0" + babel-runtime "^6.22.0" + +babel-plugin-transform-react-jsx-source@^6.22.0, babel-plugin-transform-react-jsx-source@^6.5.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-jsx-source/-/babel-plugin-transform-react-jsx-source-6.22.0.tgz#66ac12153f5cd2d17b3c19268f4bf0197f44ecd6" + dependencies: + babel-plugin-syntax-jsx "^6.8.0" + babel-runtime "^6.22.0" + +babel-plugin-transform-react-jsx@^6.24.1, babel-plugin-transform-react-jsx@^6.5.0, babel-plugin-transform-react-jsx@^6.8.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-jsx/-/babel-plugin-transform-react-jsx-6.24.1.tgz#840a028e7df460dfc3a2d29f0c0d91f6376e66a3" + dependencies: + babel-helper-builder-react-jsx "^6.24.1" + babel-plugin-syntax-jsx "^6.8.0" + babel-runtime "^6.22.0" + +babel-plugin-transform-regenerator@^6.24.1, babel-plugin-transform-regenerator@^6.5.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz#e0703696fbde27f0a3efcacf8b4dca2f7b3a8f2f" + dependencies: + regenerator-transform "^0.10.0" + +babel-plugin-transform-strict-mode@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz#d5faf7aa578a65bbe591cf5edae04a0c67020758" + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-preset-airbnb@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/babel-preset-airbnb/-/babel-preset-airbnb-1.1.1.tgz#c200f0f5505b0918ed95e08c7977238dec3a5af6" + dependencies: + babel-plugin-transform-es2015-template-literals "^6.5.0" + babel-plugin-transform-es3-member-expression-literals "^6.5.0" + babel-plugin-transform-es3-property-literals "^6.5.0" + babel-plugin-transform-exponentiation-operator "^6.5.0" + babel-plugin-transform-jscript "^6.5.0" + babel-preset-es2015 "^6.5.0" + babel-preset-react "^6.5.0" + +babel-preset-es2015-node@^6.1.1: + version "6.1.1" + resolved "https://registry.yarnpkg.com/babel-preset-es2015-node/-/babel-preset-es2015-node-6.1.1.tgz#60b23157024b0cfebf3a63554cb05ee035b4e55f" + dependencies: + babel-plugin-transform-es2015-destructuring "6.x" + babel-plugin-transform-es2015-function-name "6.x" + babel-plugin-transform-es2015-modules-commonjs "6.x" + babel-plugin-transform-es2015-parameters "6.x" + babel-plugin-transform-es2015-shorthand-properties "6.x" + babel-plugin-transform-es2015-spread "6.x" + babel-plugin-transform-es2015-sticky-regex "6.x" + babel-plugin-transform-es2015-unicode-regex "6.x" + semver "5.x" + +babel-preset-es2015@^6.5.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-preset-es2015/-/babel-preset-es2015-6.24.1.tgz#d44050d6bc2c9feea702aaf38d727a0210538939" + dependencies: + babel-plugin-check-es2015-constants "^6.22.0" + babel-plugin-transform-es2015-arrow-functions "^6.22.0" + babel-plugin-transform-es2015-block-scoped-functions "^6.22.0" + babel-plugin-transform-es2015-block-scoping "^6.24.1" + babel-plugin-transform-es2015-classes "^6.24.1" + babel-plugin-transform-es2015-computed-properties "^6.24.1" + babel-plugin-transform-es2015-destructuring "^6.22.0" + babel-plugin-transform-es2015-duplicate-keys "^6.24.1" + babel-plugin-transform-es2015-for-of "^6.22.0" + babel-plugin-transform-es2015-function-name "^6.24.1" + babel-plugin-transform-es2015-literals "^6.22.0" + babel-plugin-transform-es2015-modules-amd "^6.24.1" + babel-plugin-transform-es2015-modules-commonjs "^6.24.1" + babel-plugin-transform-es2015-modules-systemjs "^6.24.1" + babel-plugin-transform-es2015-modules-umd "^6.24.1" + babel-plugin-transform-es2015-object-super "^6.24.1" + babel-plugin-transform-es2015-parameters "^6.24.1" + babel-plugin-transform-es2015-shorthand-properties "^6.24.1" + babel-plugin-transform-es2015-spread "^6.22.0" + babel-plugin-transform-es2015-sticky-regex "^6.24.1" + babel-plugin-transform-es2015-template-literals "^6.22.0" + babel-plugin-transform-es2015-typeof-symbol "^6.22.0" + babel-plugin-transform-es2015-unicode-regex "^6.24.1" + babel-plugin-transform-regenerator "^6.24.1" + +babel-preset-fbjs@^2.1.2, babel-preset-fbjs@^2.1.4: + version "2.1.4" + resolved "https://registry.yarnpkg.com/babel-preset-fbjs/-/babel-preset-fbjs-2.1.4.tgz#22f358e6654073acf61e47a052a777d7bccf03af" + dependencies: + babel-plugin-check-es2015-constants "^6.8.0" + babel-plugin-syntax-class-properties "^6.8.0" + babel-plugin-syntax-flow "^6.8.0" + babel-plugin-syntax-jsx "^6.8.0" + babel-plugin-syntax-object-rest-spread "^6.8.0" + babel-plugin-syntax-trailing-function-commas "^6.8.0" + babel-plugin-transform-class-properties "^6.8.0" + babel-plugin-transform-es2015-arrow-functions "^6.8.0" + babel-plugin-transform-es2015-block-scoped-functions "^6.8.0" + babel-plugin-transform-es2015-block-scoping "^6.8.0" + babel-plugin-transform-es2015-classes "^6.8.0" + babel-plugin-transform-es2015-computed-properties "^6.8.0" + babel-plugin-transform-es2015-destructuring "^6.8.0" + babel-plugin-transform-es2015-for-of "^6.8.0" + babel-plugin-transform-es2015-function-name "^6.8.0" + babel-plugin-transform-es2015-literals "^6.8.0" + babel-plugin-transform-es2015-modules-commonjs "^6.8.0" + babel-plugin-transform-es2015-object-super "^6.8.0" + babel-plugin-transform-es2015-parameters "^6.8.0" + babel-plugin-transform-es2015-shorthand-properties "^6.8.0" + babel-plugin-transform-es2015-spread "^6.8.0" + babel-plugin-transform-es2015-template-literals "^6.8.0" + babel-plugin-transform-es3-member-expression-literals "^6.8.0" + babel-plugin-transform-es3-property-literals "^6.8.0" + babel-plugin-transform-flow-strip-types "^6.8.0" + babel-plugin-transform-object-rest-spread "^6.8.0" + babel-plugin-transform-react-display-name "^6.8.0" + babel-plugin-transform-react-jsx "^6.8.0" + +babel-preset-flow@^6.23.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-preset-flow/-/babel-preset-flow-6.23.0.tgz#e71218887085ae9a24b5be4169affb599816c49d" + dependencies: + babel-plugin-transform-flow-strip-types "^6.22.0" + +babel-preset-react-native@1.9.0: + version "1.9.0" + resolved "https://registry.yarnpkg.com/babel-preset-react-native/-/babel-preset-react-native-1.9.0.tgz#035fc06c65f4f2a02d0336a100b2da142f36dab1" + dependencies: + babel-plugin-check-es2015-constants "^6.5.0" + babel-plugin-react-transform "2.0.2" + babel-plugin-syntax-async-functions "^6.5.0" + babel-plugin-syntax-class-properties "^6.5.0" + babel-plugin-syntax-flow "^6.5.0" + babel-plugin-syntax-jsx "^6.5.0" + babel-plugin-syntax-trailing-function-commas "^6.5.0" + babel-plugin-transform-class-properties "^6.5.0" + babel-plugin-transform-es2015-arrow-functions "^6.5.0" + babel-plugin-transform-es2015-block-scoping "^6.5.0" + babel-plugin-transform-es2015-classes "^6.5.0" + babel-plugin-transform-es2015-computed-properties "^6.5.0" + babel-plugin-transform-es2015-destructuring "^6.5.0" + babel-plugin-transform-es2015-for-of "^6.5.0" + babel-plugin-transform-es2015-function-name "^6.5.0" + babel-plugin-transform-es2015-literals "^6.5.0" + babel-plugin-transform-es2015-modules-commonjs "^6.5.0" + babel-plugin-transform-es2015-parameters "^6.5.0" + babel-plugin-transform-es2015-shorthand-properties "^6.5.0" + babel-plugin-transform-es2015-spread "^6.5.0" + babel-plugin-transform-es2015-template-literals "^6.5.0" + babel-plugin-transform-flow-strip-types "^6.5.0" + babel-plugin-transform-object-assign "^6.5.0" + babel-plugin-transform-object-rest-spread "^6.5.0" + babel-plugin-transform-react-display-name "^6.5.0" + babel-plugin-transform-react-jsx "^6.5.0" + babel-plugin-transform-react-jsx-source "^6.5.0" + babel-plugin-transform-regenerator "^6.5.0" + react-transform-hmr "^1.0.4" + +babel-preset-react-native@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/babel-preset-react-native/-/babel-preset-react-native-4.0.0.tgz#3df80dd33a453888cdd33bdb87224d17a5d73959" + dependencies: + babel-plugin-check-es2015-constants "^6.5.0" + babel-plugin-react-transform "^3.0.0" + babel-plugin-syntax-async-functions "^6.5.0" + babel-plugin-syntax-class-properties "^6.5.0" + babel-plugin-syntax-dynamic-import "^6.18.0" + babel-plugin-syntax-flow "^6.5.0" + babel-plugin-syntax-jsx "^6.5.0" + babel-plugin-syntax-trailing-function-commas "^6.5.0" + babel-plugin-transform-class-properties "^6.5.0" + babel-plugin-transform-es2015-arrow-functions "^6.5.0" + babel-plugin-transform-es2015-block-scoping "^6.5.0" + babel-plugin-transform-es2015-classes "^6.5.0" + babel-plugin-transform-es2015-computed-properties "^6.5.0" + babel-plugin-transform-es2015-destructuring "^6.5.0" + babel-plugin-transform-es2015-for-of "^6.5.0" + babel-plugin-transform-es2015-function-name "^6.5.0" + babel-plugin-transform-es2015-literals "^6.5.0" + babel-plugin-transform-es2015-modules-commonjs "^6.5.0" + babel-plugin-transform-es2015-parameters "^6.5.0" + babel-plugin-transform-es2015-shorthand-properties "^6.5.0" + babel-plugin-transform-es2015-spread "^6.5.0" + babel-plugin-transform-es2015-template-literals "^6.5.0" + babel-plugin-transform-flow-strip-types "^6.5.0" + babel-plugin-transform-object-assign "^6.5.0" + babel-plugin-transform-object-rest-spread "^6.5.0" + babel-plugin-transform-react-display-name "^6.5.0" + babel-plugin-transform-react-jsx "^6.5.0" + babel-plugin-transform-react-jsx-source "^6.5.0" + babel-plugin-transform-regenerator "^6.5.0" + babel-template "^6.24.1" + react-transform-hmr "^1.0.4" + +babel-preset-react@^6.5.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-preset-react/-/babel-preset-react-6.24.1.tgz#ba69dfaea45fc3ec639b6a4ecea6e17702c91380" + dependencies: + babel-plugin-syntax-jsx "^6.3.13" + babel-plugin-transform-react-display-name "^6.23.0" + babel-plugin-transform-react-jsx "^6.24.1" + babel-plugin-transform-react-jsx-self "^6.22.0" + babel-plugin-transform-react-jsx-source "^6.22.0" + babel-preset-flow "^6.23.0" + +babel-register@^6.24.1, babel-register@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-register/-/babel-register-6.26.0.tgz#6ed021173e2fcb486d7acb45c6009a856f647071" + dependencies: + babel-core "^6.26.0" + babel-runtime "^6.26.0" + core-js "^2.5.0" + home-or-tmp "^2.0.0" + lodash "^4.17.4" + mkdirp "^0.5.1" + source-map-support "^0.4.15" + +babel-runtime@^6.0.0, babel-runtime@^6.18.0, babel-runtime@^6.22.0, babel-runtime@^6.23.0, babel-runtime@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe" + dependencies: + core-js "^2.4.0" + regenerator-runtime "^0.11.0" + +babel-template@^6.24.1, babel-template@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.26.0.tgz#de03e2d16396b069f46dd9fff8521fb1a0e35e02" + dependencies: + babel-runtime "^6.26.0" + babel-traverse "^6.26.0" + babel-types "^6.26.0" + babylon "^6.18.0" + lodash "^4.17.4" + +babel-traverse@^6.0.20, babel-traverse@^6.24.1, babel-traverse@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.26.0.tgz#46a9cbd7edcc62c8e5c064e2d2d8d0f4035766ee" + dependencies: + babel-code-frame "^6.26.0" + babel-messages "^6.23.0" + babel-runtime "^6.26.0" + babel-types "^6.26.0" + babylon "^6.18.0" + debug "^2.6.8" + globals "^9.18.0" + invariant "^2.2.2" + lodash "^4.17.4" + +babel-types@^6.0.19, babel-types@^6.19.0, babel-types@^6.24.1, babel-types@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.26.0.tgz#a3b073f94ab49eb6fa55cd65227a334380632497" + dependencies: + babel-runtime "^6.26.0" + esutils "^2.0.2" + lodash "^4.17.4" + to-fast-properties "^1.0.3" + +babylon@^6.0.18, babylon@^6.18.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3" + +balanced-match@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" + +base64-js@0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-0.0.8.tgz#1101e9544f4a76b1bc3b26d452ca96d7a35e7978" + +base64-js@1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.1.2.tgz#d6400cac1c4c660976d90d07a04351d89395f5e8" + +base64-js@^1.1.2: + version "1.2.1" + resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.2.1.tgz#a91947da1f4a516ea38e5b4ec0ec3773675e0886" + +base64-url@1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/base64-url/-/base64-url-1.2.1.tgz#199fd661702a0e7b7dcae6e0698bb089c52f6d78" + +bash-color@0.0.4: + version "0.0.4" + resolved "https://registry.yarnpkg.com/bash-color/-/bash-color-0.0.4.tgz#e9be8ce33540cada4881768c59bd63865736e913" + +basic-auth-connect@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/basic-auth-connect/-/basic-auth-connect-1.0.0.tgz#fdb0b43962ca7b40456a7c2bb48fe173da2d2122" + +basic-auth@~1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/basic-auth/-/basic-auth-1.0.4.tgz#030935b01de7c9b94a824b29f3fccb750d3a5290" + +batch@0.5.3: + version "0.5.3" + resolved "https://registry.yarnpkg.com/batch/-/batch-0.5.3.tgz#3f3414f380321743bfc1042f9a83ff1d5824d464" + +bcrypt-pbkdf@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz#63bc5dcb61331b92bc05fd528953c33462a06f8d" + dependencies: + tweetnacl "^0.14.3" + +beeper@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/beeper/-/beeper-1.1.1.tgz#e6d5ea8c5dad001304a70b22638447f69cb2f809" + +big-integer@^1.6.7: + version "1.6.26" + resolved "https://registry.yarnpkg.com/big-integer/-/big-integer-1.6.26.tgz#3af1672fa62daf2d5ecafacf6e5aa0d25e02c1c8" + +bl@^1.0.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/bl/-/bl-1.2.1.tgz#cac328f7bee45730d404b692203fcb590e172d5e" + dependencies: + readable-stream "^2.0.5" + +bl@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/bl/-/bl-1.1.2.tgz#fdca871a99713aa00d19e3bbba41c44787a65398" + dependencies: + readable-stream "~2.0.5" + +block-stream@*, block-stream@0.0.9: + version "0.0.9" + resolved "https://registry.yarnpkg.com/block-stream/-/block-stream-0.0.9.tgz#13ebfe778a03205cfe03751481ebb4b3300c126a" + dependencies: + inherits "~2.0.0" + +bluebird@^3.5.0, bluebird@~3.5.0: + version "3.5.1" + resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.1.tgz#d9551f9de98f1fcda1e683d17ee91a0602ee2eb9" + +body-parser@~1.13.3: + version "1.13.3" + resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.13.3.tgz#c08cf330c3358e151016a05746f13f029c97fa97" + dependencies: + bytes "2.1.0" + content-type "~1.0.1" + debug "~2.2.0" + depd "~1.0.1" + http-errors "~1.3.1" + iconv-lite "0.4.11" + on-finished "~2.3.0" + qs "4.0.0" + raw-body "~2.1.2" + type-is "~1.6.6" + +boom@2.x.x: + version "2.10.1" + resolved "https://registry.yarnpkg.com/boom/-/boom-2.10.1.tgz#39c8918ceff5799f83f9492a848f625add0c766f" + dependencies: + hoek "2.x.x" + +boom@4.x.x: + version "4.3.1" + resolved "https://registry.yarnpkg.com/boom/-/boom-4.3.1.tgz#4f8a3005cb4a7e3889f749030fd25b96e01d2e31" + dependencies: + hoek "4.x.x" + +boom@5.x.x: + version "5.2.0" + resolved "https://registry.yarnpkg.com/boom/-/boom-5.2.0.tgz#5dd9da6ee3a5f302077436290cb717d3f4a54e02" + dependencies: + hoek "4.x.x" + +boxen@^1.0.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/boxen/-/boxen-1.3.0.tgz#55c6c39a8ba58d9c61ad22cd877532deb665a20b" + dependencies: + ansi-align "^2.0.0" + camelcase "^4.0.0" + chalk "^2.0.1" + cli-boxes "^1.0.0" + string-width "^2.0.0" + term-size "^1.2.0" + widest-line "^2.0.0" + +bplist-creator@0.0.7: + version "0.0.7" + resolved "https://registry.yarnpkg.com/bplist-creator/-/bplist-creator-0.0.7.tgz#37df1536092824b87c42f957b01344117372ae45" + dependencies: + stream-buffers "~2.2.0" + +bplist-parser@0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/bplist-parser/-/bplist-parser-0.1.1.tgz#d60d5dcc20cba6dc7e1f299b35d3e1f95dafbae6" + dependencies: + big-integer "^1.6.7" + +brace-expansion@^1.1.7: + version "1.1.8" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.8.tgz#c07b211c7c952ec1f8efd51a77ef0d1d3990a292" + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +braces@^1.8.2: + version "1.8.5" + resolved "https://registry.yarnpkg.com/braces/-/braces-1.8.5.tgz#ba77962e12dff969d6b76711e914b737857bf6a7" + dependencies: + expand-range "^1.8.1" + preserve "^0.2.0" + repeat-element "^1.1.2" + +bser@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/bser/-/bser-2.0.0.tgz#9ac78d3ed5d915804fd87acb158bc797147a1719" + dependencies: + node-int64 "^0.4.0" + +buffer-shims@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/buffer-shims/-/buffer-shims-1.0.0.tgz#9978ce317388c649ad8793028c3477ef044a8b51" + +builtin-modules@^1.0.0, builtin-modules@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f" + +builtins@0.0.7: + version "0.0.7" + resolved "https://registry.yarnpkg.com/builtins/-/builtins-0.0.7.tgz#355219cd6cf18dbe7c01cc7fd2dce765cfdc549a" + +builtins@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/builtins/-/builtins-1.0.3.tgz#cb94faeb61c8696451db36534e1422f94f0aee88" + +bytes@2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-2.1.0.tgz#ac93c410e2ffc9cc7cf4b464b38289067f5e47b4" + +bytes@2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-2.4.0.tgz#7d97196f9d5baf7f6935e25985549edd2a6c2339" + +cacache@^10.0.0: + version "10.0.2" + resolved "https://registry.yarnpkg.com/cacache/-/cacache-10.0.2.tgz#105a93a162bbedf3a25da42e1939ed99ffb145f8" + dependencies: + bluebird "^3.5.0" + chownr "^1.0.1" + glob "^7.1.2" + graceful-fs "^4.1.11" + lru-cache "^4.1.1" + mississippi "^1.3.0" + mkdirp "^0.5.1" + move-concurrently "^1.0.1" + promise-inflight "^1.0.1" + rimraf "^2.6.1" + ssri "^5.0.0" + unique-filename "^1.1.0" + y18n "^3.2.1" + +cacache@^9.2.9: + version "9.3.0" + resolved "https://registry.yarnpkg.com/cacache/-/cacache-9.3.0.tgz#9cd58f2dd0b8c8cacf685b7067b416d6d3cf9db1" + dependencies: + bluebird "^3.5.0" + chownr "^1.0.1" + glob "^7.1.2" + graceful-fs "^4.1.11" + lru-cache "^4.1.1" + mississippi "^1.3.0" + mkdirp "^0.5.1" + move-concurrently "^1.0.1" + promise-inflight "^1.0.1" + rimraf "^2.6.1" + ssri "^4.1.6" + unique-filename "^1.1.0" + y18n "^3.2.1" + +cacache@~9.2.9: + version "9.2.9" + resolved "https://registry.yarnpkg.com/cacache/-/cacache-9.2.9.tgz#f9d7ffe039851ec94c28290662afa4dd4bb9e8dd" + dependencies: + bluebird "^3.5.0" + chownr "^1.0.1" + glob "^7.1.2" + graceful-fs "^4.1.11" + lru-cache "^4.1.1" + mississippi "^1.3.0" + mkdirp "^0.5.1" + move-concurrently "^1.0.1" + promise-inflight "^1.0.1" + rimraf "^2.6.1" + ssri "^4.1.6" + unique-filename "^1.1.0" + y18n "^3.2.1" + +call-limit@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/call-limit/-/call-limit-1.1.0.tgz#6fd61b03f3da42a2cd0ec2b60f02bd0e71991fea" + +caller-path@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-0.1.0.tgz#94085ef63581ecd3daa92444a8fe94e82577751f" + dependencies: + callsites "^0.2.0" + +callsites@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-0.2.0.tgz#afab96262910a7f33c19a5775825c69f34e350ca" + +camelcase@^4.0.0, camelcase@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd" + +capture-stack-trace@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/capture-stack-trace/-/capture-stack-trace-1.0.0.tgz#4a6fa07399c26bba47f0b2496b4d0fb408c5550d" + +caseless@~0.11.0: + version "0.11.0" + resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.11.0.tgz#715b96ea9841593cc33067923f5ec60ebda4f7d7" + +caseless@~0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" + +chalk@^1.0.0, chalk@^1.1.1, chalk@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" + dependencies: + ansi-styles "^2.2.1" + escape-string-regexp "^1.0.2" + has-ansi "^2.0.0" + strip-ansi "^3.0.0" + supports-color "^2.0.0" + +chalk@^2.0.0, chalk@^2.0.1: + version "2.3.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.3.0.tgz#b5ea48efc9c1793dccc9b4767c93914d3f2d52ba" + dependencies: + ansi-styles "^3.1.0" + escape-string-regexp "^1.0.5" + supports-color "^4.0.0" + +char-spinner@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/char-spinner/-/char-spinner-1.0.1.tgz#e6ea67bd247e107112983b7ab0479ed362800081" + +chardet@^0.4.0: + version "0.4.2" + resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.4.2.tgz#b5473b33dc97c424e5d98dc87d55d4d8a29c8bf2" + +chmodr@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/chmodr/-/chmodr-1.0.2.tgz#04662b932d0f02ec66deaa2b0ea42811968e3eb9" + +chownr@^1.0.1, chownr@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.0.1.tgz#e2a75042a9551908bebd25b8523d5f9769d79181" + +circular-json@^0.3.1: + version "0.3.3" + resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.3.3.tgz#815c99ea84f6809529d2f45791bdf82711352d66" + +cli-boxes@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-1.0.0.tgz#4fa917c3e59c94a004cd61f8ee509da651687143" + +cli-cursor@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-1.0.2.tgz#64da3f7d56a54412e59794bd62dc35295e8f2987" + dependencies: + restore-cursor "^1.0.1" + +cli-cursor@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5" + dependencies: + restore-cursor "^2.0.0" + +cli-width@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639" + +clipboardy@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/clipboardy/-/clipboardy-1.2.2.tgz#2ce320b9ed9be1514f79878b53ff9765420903e2" + dependencies: + arch "^2.1.0" + execa "^0.8.0" + +cliui@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-3.2.0.tgz#120601537a916d29940f934da3b48d585a39213d" + dependencies: + string-width "^1.0.1" + strip-ansi "^3.0.1" + wrap-ansi "^2.0.0" + +clone-stats@^0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/clone-stats/-/clone-stats-0.0.1.tgz#b88f94a82cf38b8791d58046ea4029ad88ca99d1" + +clone@^1.0.0, clone@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.3.tgz#298d7e2231660f40c003c2ed3140decf3f53085f" + +cmd-shim@~2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/cmd-shim/-/cmd-shim-2.0.2.tgz#6fcbda99483a8fd15d7d30a196ca69d688a2efdb" + dependencies: + graceful-fs "^4.1.2" + mkdirp "~0.5.0" + +co@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" + +code-point-at@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" + +color-convert@^1.9.0: + version "1.9.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.1.tgz#c1261107aeb2f294ebffec9ed9ecad529a6097ed" + dependencies: + color-name "^1.1.1" + +color-name@^1.1.1: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + +color-support@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-support/-/color-support-1.1.3.tgz#93834379a1cc9a0c61f82f52f0d04322251bd5a2" + +columnify@~1.5.4: + version "1.5.4" + resolved "https://registry.yarnpkg.com/columnify/-/columnify-1.5.4.tgz#4737ddf1c7b69a8a7c340570782e947eec8e78bb" + dependencies: + strip-ansi "^3.0.0" + wcwidth "^1.0.0" + +combined-stream@^1.0.5, combined-stream@~1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.5.tgz#938370a57b4a51dea2c77c15d5c5fdf895164009" + dependencies: + delayed-stream "~1.0.0" + +commander@2.11.0: + version "2.11.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.11.0.tgz#157152fd1e7a6c8d98a5b715cf376df928004563" + +commander@^2.9.0, commander@~2.13.0: + version "2.13.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.13.0.tgz#6964bca67685df7c1f1430c584f07d7597885b9c" + +compressible@~2.0.5: + version "2.0.12" + resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.12.tgz#c59a5c99db76767e9876500e271ef63b3493bd66" + dependencies: + mime-db ">= 1.30.0 < 2" + +compression@~1.5.2: + version "1.5.2" + resolved "https://registry.yarnpkg.com/compression/-/compression-1.5.2.tgz#b03b8d86e6f8ad29683cba8df91ddc6ffc77b395" + dependencies: + accepts "~1.2.12" + bytes "2.1.0" + compressible "~2.0.5" + debug "~2.2.0" + on-headers "~1.0.0" + vary "~1.0.1" + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + +concat-stream@^1.5.0, concat-stream@^1.5.2, concat-stream@^1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.0.tgz#0aac662fd52be78964d5532f694784e70110acf7" + dependencies: + inherits "^2.0.3" + readable-stream "^2.2.2" + typedarray "^0.0.6" + +config-chain@~1.1.10, config-chain@~1.1.11: + version "1.1.11" + resolved "https://registry.yarnpkg.com/config-chain/-/config-chain-1.1.11.tgz#aba09747dfbe4c3e70e766a6e41586e1859fc6f2" + dependencies: + ini "^1.3.4" + proto-list "~1.2.1" + +configstore@^3.0.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/configstore/-/configstore-3.1.1.tgz#094ee662ab83fad9917678de114faaea8fcdca90" + dependencies: + dot-prop "^4.1.0" + graceful-fs "^4.1.2" + make-dir "^1.0.0" + unique-string "^1.0.0" + write-file-atomic "^2.0.0" + xdg-basedir "^3.0.0" + +connect-timeout@~1.6.2: + version "1.6.2" + resolved "https://registry.yarnpkg.com/connect-timeout/-/connect-timeout-1.6.2.tgz#de9a5ec61e33a12b6edaab7b5f062e98c599b88e" + dependencies: + debug "~2.2.0" + http-errors "~1.3.1" + ms "0.7.1" + on-headers "~1.0.0" + +connect@^2.8.3: + version "2.30.2" + resolved "https://registry.yarnpkg.com/connect/-/connect-2.30.2.tgz#8da9bcbe8a054d3d318d74dfec903b5c39a1b609" + dependencies: + basic-auth-connect "1.0.0" + body-parser "~1.13.3" + bytes "2.1.0" + compression "~1.5.2" + connect-timeout "~1.6.2" + content-type "~1.0.1" + cookie "0.1.3" + cookie-parser "~1.3.5" + cookie-signature "1.0.6" + csurf "~1.8.3" + debug "~2.2.0" + depd "~1.0.1" + errorhandler "~1.4.2" + express-session "~1.11.3" + finalhandler "0.4.0" + fresh "0.3.0" + http-errors "~1.3.1" + method-override "~2.3.5" + morgan "~1.6.1" + multiparty "3.3.2" + on-headers "~1.0.0" + parseurl "~1.3.0" + pause "0.1.0" + qs "4.0.0" + response-time "~2.3.1" + serve-favicon "~2.3.0" + serve-index "~1.7.2" + serve-static "~1.10.0" + type-is "~1.6.6" + utils-merge "1.0.0" + vhost "~3.0.1" + +console-control-strings@^1.0.0, console-control-strings@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" + +contains-path@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/contains-path/-/contains-path-0.1.0.tgz#fe8cf184ff6670b6baef01a9d4861a5cbec4120a" + +content-type@~1.0.1: + version "1.0.4" + resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" + +convert-source-map@^1.5.0: + version "1.5.1" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.5.1.tgz#b8278097b9bc229365de5c62cf5fcaed8b5599e5" + +cookie-parser@~1.3.5: + version "1.3.5" + resolved "https://registry.yarnpkg.com/cookie-parser/-/cookie-parser-1.3.5.tgz#9d755570fb5d17890771227a02314d9be7cf8356" + dependencies: + cookie "0.1.3" + cookie-signature "1.0.6" + +cookie-signature@1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" + +cookie@0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.1.3.tgz#e734a5c1417fce472d5aef82c381cabb64d1a435" + +copy-concurrently@^1.0.0: + version "1.0.5" + resolved "https://registry.yarnpkg.com/copy-concurrently/-/copy-concurrently-1.0.5.tgz#92297398cae34937fcafd6ec8139c18051f0b5e0" + dependencies: + aproba "^1.1.1" + fs-write-stream-atomic "^1.0.8" + iferr "^0.1.5" + mkdirp "^0.5.1" + rimraf "^2.5.4" + run-queue "^1.0.0" + +core-js@^1.0.0: + version "1.2.7" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-1.2.7.tgz#652294c14651db28fa93bd2d5ff2983a4f08c636" + +core-js@^2.2.2, core-js@^2.4.0, core-js@^2.4.1, core-js@^2.5.0: + version "2.5.3" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.3.tgz#8acc38345824f16d8365b7c9b4259168e8ed603e" + +core-util-is@1.0.2, core-util-is@~1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" + +crc@3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/crc/-/crc-3.3.0.tgz#fa622e1bc388bf257309082d6b65200ce67090ba" + +create-error-class@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/create-error-class/-/create-error-class-3.0.2.tgz#06be7abef947a3f14a30fd610671d401bca8b7b6" + dependencies: + capture-stack-trace "^1.0.0" + +create-react-class@^15.5.2: + version "15.6.2" + resolved "https://registry.yarnpkg.com/create-react-class/-/create-react-class-15.6.2.tgz#cf1ed15f12aad7f14ef5f2dfe05e6c42f91ef02a" + dependencies: + fbjs "^0.8.9" + loose-envify "^1.3.1" + object-assign "^4.1.1" + +cross-spawn@^5.0.1, cross-spawn@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449" + dependencies: + lru-cache "^4.0.1" + shebang-command "^1.2.0" + which "^1.2.9" + +cryptiles@2.x.x: + version "2.0.5" + resolved "https://registry.yarnpkg.com/cryptiles/-/cryptiles-2.0.5.tgz#3bdfecdc608147c1c67202fa291e7dca59eaa3b8" + dependencies: + boom "2.x.x" + +cryptiles@3.x.x: + version "3.1.2" + resolved "https://registry.yarnpkg.com/cryptiles/-/cryptiles-3.1.2.tgz#a89fbb220f5ce25ec56e8c4aa8a4fd7b5b0d29fe" + dependencies: + boom "5.x.x" + +crypto-random-string@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-1.0.0.tgz#a230f64f568310e1498009940790ec99545bca7e" + +csrf@~3.0.0: + version "3.0.6" + resolved "https://registry.yarnpkg.com/csrf/-/csrf-3.0.6.tgz#b61120ddceeafc91e76ed5313bb5c0b2667b710a" + dependencies: + rndm "1.2.0" + tsscmp "1.0.5" + uid-safe "2.1.4" + +csurf@~1.8.3: + version "1.8.3" + resolved "https://registry.yarnpkg.com/csurf/-/csurf-1.8.3.tgz#23f2a13bf1d8fce1d0c996588394442cba86a56a" + dependencies: + cookie "0.1.3" + cookie-signature "1.0.6" + csrf "~3.0.0" + http-errors "~1.3.1" + +cyclist@~0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-0.2.2.tgz#1b33792e11e914a2fd6d6ed6447464444e5fa640" + +d@1: + version "1.0.0" + resolved "https://registry.yarnpkg.com/d/-/d-1.0.0.tgz#754bb5bfe55451da69a58b94d45f4c5b0462d58f" + dependencies: + es5-ext "^0.10.9" + +damerau-levenshtein@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/damerau-levenshtein/-/damerau-levenshtein-1.0.4.tgz#03191c432cb6eea168bb77f3a55ffdccb8978514" + +dashdash@^1.12.0: + version "1.14.1" + resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" + dependencies: + assert-plus "^1.0.0" + +dateformat@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-2.2.0.tgz#4065e2013cf9fb916ddfd82efb506ad4c6769062" + +debug@2, debug@2.6.9, debug@^2.1.1, debug@^2.2.0, debug@^2.6.8: + version "2.6.9" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + dependencies: + ms "2.0.0" + +debug@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" + dependencies: + ms "2.0.0" + +debug@~2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.2.0.tgz#f87057e995b1a1f6ae6a4960664137bc56f039da" + dependencies: + ms "0.7.1" + +debuglog@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/debuglog/-/debuglog-1.0.1.tgz#aa24ffb9ac3df9a2351837cfb2d279360cd78492" + +decamelize@^1.1.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" + +deep-extend@~0.4.0: + version "0.4.2" + resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.4.2.tgz#48b699c27e334bf89f10892be432f6e4c7d34a7f" + +deep-is@~0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" + +defaults@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.3.tgz#c656051e9817d9ff08ed881477f3fe4019f3ef7d" + dependencies: + clone "^1.0.2" + +define-properties@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.2.tgz#83a73f2fea569898fb737193c8f873caf6d45c94" + dependencies: + foreach "^2.0.5" + object-keys "^1.0.8" + +del@^2.0.2: + version "2.2.2" + resolved "https://registry.yarnpkg.com/del/-/del-2.2.2.tgz#c12c981d067846c84bcaf862cff930d907ffd1a8" + dependencies: + globby "^5.0.0" + is-path-cwd "^1.0.0" + is-path-in-cwd "^1.0.0" + object-assign "^4.0.1" + pify "^2.0.0" + pinkie-promise "^2.0.0" + rimraf "^2.2.8" + +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + +delegates@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" + +denodeify@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/denodeify/-/denodeify-1.2.1.tgz#3a36287f5034e699e7577901052c2e6c94251631" + +depd@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/depd/-/depd-1.0.1.tgz#80aec64c9d6d97e65cc2a9caa93c0aa6abf73aaa" + +depd@~1.1.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" + +destroy@~1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" + +detect-indent@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-4.0.0.tgz#f76d064352cdf43a1cb6ce619c4ee3a9475de208" + dependencies: + repeating "^2.0.0" + +detect-indent@~5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-5.0.0.tgz#3871cc0a6a002e8c3e5b3cf7f336264675f06b9d" + +detect-libc@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" + +dezalgo@^1.0.0, dezalgo@^1.0.1, dezalgo@^1.0.2, dezalgo@~1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/dezalgo/-/dezalgo-1.0.3.tgz#7f742de066fc748bc8db820569dddce49bf0d456" + dependencies: + asap "^2.0.0" + wrappy "1" + +doctrine@1.3.x: + version "1.3.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-1.3.0.tgz#13e75682b55518424276f7c173783456ef913d26" + dependencies: + esutils "^2.0.2" + isarray "^1.0.0" + +doctrine@^1.2.2: + version "1.5.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-1.5.0.tgz#379dce730f6166f76cefa4e6707a159b02c5a6fa" + dependencies: + esutils "^2.0.2" + isarray "^1.0.0" + +doctrine@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" + dependencies: + esutils "^2.0.2" + +dom-walk@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/dom-walk/-/dom-walk-0.1.1.tgz#672226dc74c8f799ad35307df936aba11acd6018" + +dot-prop@^4.1.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-4.2.0.tgz#1f19e0c2e1aa0e32797c49799f2837ac6af69c57" + dependencies: + is-obj "^1.0.0" + +duplexer2@0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/duplexer2/-/duplexer2-0.0.2.tgz#c614dcf67e2fb14995a91711e5a617e8a60a31db" + dependencies: + readable-stream "~1.1.9" + +duplexer3@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2" + +duplexify@^3.4.2, duplexify@^3.5.3: + version "3.5.3" + resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.5.3.tgz#8b5818800df92fd0125b27ab896491912858243e" + dependencies: + end-of-stream "^1.0.0" + inherits "^2.0.1" + readable-stream "^2.0.0" + stream-shift "^1.0.0" + +ecc-jsbn@~0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz#0fc73a9ed5f0d53c38193398523ef7e543777505" + dependencies: + jsbn "~0.1.0" + +editor@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/editor/-/editor-1.0.0.tgz#60c7f87bd62bcc6a894fa8ccd6afb7823a24f742" + +ee-first@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" + +encoding@^0.1.11: + version "0.1.12" + resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.12.tgz#538b66f3ee62cd1ab51ec323829d1f9480c74beb" + dependencies: + iconv-lite "~0.4.13" + +end-of-stream@^1.0.0, end-of-stream@^1.1.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.1.tgz#ed29634d19baba463b6ce6b80a37213eab71ec43" + dependencies: + once "^1.4.0" + +envinfo@^3.0.0: + version "3.11.0" + resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-3.11.0.tgz#7bde377e478bf14835412f7b05e7c6b473cb734c" + dependencies: + clipboardy "^1.2.2" + glob "^7.1.2" + minimist "^1.2.0" + os-name "^2.0.1" + which "^1.2.14" + +err-code@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/err-code/-/err-code-1.1.2.tgz#06e0116d3028f6aef4806849eb0ea6a748ae6960" + +"errno@>=0.1.1 <0.2.0-0", errno@^0.1.4: + version "0.1.6" + resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.6.tgz#c386ce8a6283f14fc09563b71560908c9bf53026" + dependencies: + prr "~1.0.1" + +error-ex@^1.2.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.1.tgz#f855a86ce61adc4e8621c3cda21e7a7612c3a8dc" + dependencies: + is-arrayish "^0.2.1" + +errorhandler@~1.4.2: + version "1.4.3" + resolved "https://registry.yarnpkg.com/errorhandler/-/errorhandler-1.4.3.tgz#b7b70ed8f359e9db88092f2d20c0f831420ad83f" + dependencies: + accepts "~1.3.0" + escape-html "~1.0.3" + +es-abstract@^1.7.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.10.0.tgz#1ecb36c197842a00d8ee4c2dfd8646bb97d60864" + dependencies: + es-to-primitive "^1.1.1" + function-bind "^1.1.1" + has "^1.0.1" + is-callable "^1.1.3" + is-regex "^1.0.4" + +es-to-primitive@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.1.1.tgz#45355248a88979034b6792e19bb81f2b7975dd0d" + dependencies: + is-callable "^1.1.1" + is-date-object "^1.0.1" + is-symbol "^1.0.1" + +es5-ext@^0.10.14, es5-ext@^0.10.35, es5-ext@^0.10.9, es5-ext@~0.10.14: + version "0.10.38" + resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.38.tgz#fa7d40d65bbc9bb8a67e1d3f9cc656a00530eed3" + dependencies: + es6-iterator "~2.0.3" + es6-symbol "~3.1.1" + +es6-iterator@^2.0.1, es6-iterator@~2.0.1, es6-iterator@~2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.3.tgz#a7de889141a05a94b0854403b2d0a0fbfa98f3b7" + dependencies: + d "1" + es5-ext "^0.10.35" + es6-symbol "^3.1.1" + +es6-map@^0.1.3: + version "0.1.5" + resolved "https://registry.yarnpkg.com/es6-map/-/es6-map-0.1.5.tgz#9136e0503dcc06a301690f0bb14ff4e364e949f0" + dependencies: + d "1" + es5-ext "~0.10.14" + es6-iterator "~2.0.1" + es6-set "~0.1.5" + es6-symbol "~3.1.1" + event-emitter "~0.3.5" + +es6-promise@^4.0.3: + version "4.2.2" + resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.2.tgz#f722d7769af88bd33bc13ec6605e1f92966b82d9" + +es6-promisify@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/es6-promisify/-/es6-promisify-5.0.0.tgz#5109d62f3e56ea967c4b63505aef08291c8a5203" + dependencies: + es6-promise "^4.0.3" + +es6-set@^0.1.4, es6-set@~0.1.5: + version "0.1.5" + resolved "https://registry.yarnpkg.com/es6-set/-/es6-set-0.1.5.tgz#d2b3ec5d4d800ced818db538d28974db0a73ccb1" + dependencies: + d "1" + es5-ext "~0.10.14" + es6-iterator "~2.0.1" + es6-symbol "3.1.1" + event-emitter "~0.3.5" + +es6-symbol@3.1.1, es6-symbol@^3.1.1, es6-symbol@~3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.1.tgz#bf00ef4fdab6ba1b46ecb7b629b4c7ed5715cc77" + dependencies: + d "1" + es5-ext "~0.10.14" + +es6-weak-map@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/es6-weak-map/-/es6-weak-map-2.0.2.tgz#5e3ab32251ffd1538a1f8e5ffa1357772f92d96f" + dependencies: + d "1" + es5-ext "^0.10.14" + es6-iterator "^2.0.1" + es6-symbol "^3.1.1" + +escape-html@1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.2.tgz#d77d32fa98e38c2f41ae85e9278e0e0e6ba1022c" + +escape-html@~1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" + +escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + +escope@^3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/escope/-/escope-3.6.0.tgz#e01975e812781a163a6dadfdd80398dc64c889c3" + dependencies: + es6-map "^0.1.3" + es6-weak-map "^2.0.1" + esrecurse "^4.1.0" + estraverse "^4.1.1" + +eslint-config-airbnb-base@^5.0.2: + version "5.0.3" + resolved "https://registry.yarnpkg.com/eslint-config-airbnb-base/-/eslint-config-airbnb-base-5.0.3.tgz#9714ac35ec2cd7fab0d44d148a9f91db2944074d" + +eslint-config-airbnb@^10.0.1: + version "10.0.1" + resolved "https://registry.yarnpkg.com/eslint-config-airbnb/-/eslint-config-airbnb-10.0.1.tgz#a470108646d6c45e1f639a03f11d504a1aa4aedc" + dependencies: + eslint-config-airbnb-base "^5.0.2" + +eslint-import-resolver-node@^0.2.0: + version "0.2.3" + resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.2.3.tgz#5add8106e8c928db2cba232bcd9efa846e3da16c" + dependencies: + debug "^2.2.0" + object-assign "^4.0.1" + resolve "^1.1.6" + +eslint-plugin-import@^1.14.0: + version "1.16.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-1.16.0.tgz#b2fa07ebcc53504d0f2a4477582ec8bff1871b9f" + dependencies: + builtin-modules "^1.1.1" + contains-path "^0.1.0" + debug "^2.2.0" + doctrine "1.3.x" + es6-map "^0.1.3" + es6-set "^0.1.4" + eslint-import-resolver-node "^0.2.0" + has "^1.0.1" + lodash.cond "^4.3.0" + lodash.endswith "^4.0.1" + lodash.find "^4.3.0" + lodash.findindex "^4.3.0" + minimatch "^3.0.3" + object-assign "^4.0.1" + pkg-dir "^1.0.0" + pkg-up "^1.0.0" + +eslint-plugin-jsx-a11y@^2.1.0: + version "2.2.3" + resolved "https://registry.yarnpkg.com/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-2.2.3.tgz#4e35cb71b8a7db702ac415c806eb8e8d9ea6c65d" + dependencies: + damerau-levenshtein "^1.0.0" + jsx-ast-utils "^1.0.0" + object-assign "^4.0.1" + +eslint-plugin-prefer-object-spread@^1.1.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-prefer-object-spread/-/eslint-plugin-prefer-object-spread-1.2.1.tgz#27fb91853690cceb3ae6101d9c8aecc6a67a402c" + +eslint-plugin-react@^6.1.2: + version "6.10.3" + resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-6.10.3.tgz#c5435beb06774e12c7db2f6abaddcbf900cd3f78" + dependencies: + array.prototype.find "^2.0.1" + doctrine "^1.2.2" + has "^1.0.1" + jsx-ast-utils "^1.3.4" + object.assign "^4.0.4" + +eslint@^3.3.1: + version "3.19.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-3.19.0.tgz#c8fc6201c7f40dd08941b87c085767386a679acc" + dependencies: + babel-code-frame "^6.16.0" + chalk "^1.1.3" + concat-stream "^1.5.2" + debug "^2.1.1" + doctrine "^2.0.0" + escope "^3.6.0" + espree "^3.4.0" + esquery "^1.0.0" + estraverse "^4.2.0" + esutils "^2.0.2" + file-entry-cache "^2.0.0" + glob "^7.0.3" + globals "^9.14.0" + ignore "^3.2.0" + imurmurhash "^0.1.4" + inquirer "^0.12.0" + is-my-json-valid "^2.10.0" + is-resolvable "^1.0.0" + js-yaml "^3.5.1" + json-stable-stringify "^1.0.0" + levn "^0.3.0" + lodash "^4.0.0" + mkdirp "^0.5.0" + natural-compare "^1.4.0" + optionator "^0.8.2" + path-is-inside "^1.0.1" + pluralize "^1.2.1" + progress "^1.1.8" + require-uncached "^1.0.2" + shelljs "^0.7.5" + strip-bom "^3.0.0" + strip-json-comments "~2.0.1" + table "^3.7.8" + text-table "~0.2.0" + user-home "^2.0.0" + +espree@^3.4.0: + version "3.5.2" + resolved "https://registry.yarnpkg.com/espree/-/espree-3.5.2.tgz#756ada8b979e9dcfcdb30aad8d1a9304a905e1ca" + dependencies: + acorn "^5.2.1" + acorn-jsx "^3.0.0" + +esprima@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.0.tgz#4499eddcd1110e0b218bacf2fa7f7f59f55ca804" + +esquery@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.0.0.tgz#cfba8b57d7fba93f17298a8a006a04cda13d80fa" + dependencies: + estraverse "^4.0.0" + +esrecurse@^4.1.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.2.0.tgz#fa9568d98d3823f9a41d91e902dcab9ea6e5b163" + dependencies: + estraverse "^4.1.0" + object-assign "^4.0.1" + +estraverse@^4.0.0, estraverse@^4.1.0, estraverse@^4.1.1, estraverse@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.2.0.tgz#0dee3fed31fcd469618ce7342099fc1afa0bdb13" + +esutils@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b" + +etag@~1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/etag/-/etag-1.7.0.tgz#03d30b5f67dd6e632d2945d30d6652731a34d5d8" + +event-emitter@~0.3.5: + version "0.3.5" + resolved "https://registry.yarnpkg.com/event-emitter/-/event-emitter-0.3.5.tgz#df8c69eef1647923c7157b9ce83840610b02cc39" + dependencies: + d "1" + es5-ext "~0.10.14" + +event-target-shim@^1.0.5: + version "1.1.1" + resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-1.1.1.tgz#a86e5ee6bdaa16054475da797ccddf0c55698491" + +exec-sh@^0.2.0: + version "0.2.1" + resolved "https://registry.yarnpkg.com/exec-sh/-/exec-sh-0.2.1.tgz#163b98a6e89e6b65b47c2a28d215bc1f63989c38" + dependencies: + merge "^1.1.3" + +execa@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-0.7.0.tgz#944becd34cc41ee32a63a9faf27ad5a65fc59777" + dependencies: + cross-spawn "^5.0.1" + get-stream "^3.0.0" + is-stream "^1.1.0" + npm-run-path "^2.0.0" + p-finally "^1.0.0" + signal-exit "^3.0.0" + strip-eof "^1.0.0" + +execa@^0.8.0: + version "0.8.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-0.8.0.tgz#d8d76bbc1b55217ed190fd6dd49d3c774ecfc8da" + dependencies: + cross-spawn "^5.0.1" + get-stream "^3.0.0" + is-stream "^1.1.0" + npm-run-path "^2.0.0" + p-finally "^1.0.0" + signal-exit "^3.0.0" + strip-eof "^1.0.0" + +exit-hook@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/exit-hook/-/exit-hook-1.1.1.tgz#f05ca233b48c05d54fff07765df8507e95c02ff8" + +expand-brackets@^0.1.4: + version "0.1.5" + resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-0.1.5.tgz#df07284e342a807cd733ac5af72411e581d1177b" + dependencies: + is-posix-bracket "^0.1.0" + +expand-range@^1.8.1: + version "1.8.2" + resolved "https://registry.yarnpkg.com/expand-range/-/expand-range-1.8.2.tgz#a299effd335fe2721ebae8e257ec79644fc85337" + dependencies: + fill-range "^2.1.0" + +express-session@~1.11.3: + version "1.11.3" + resolved "https://registry.yarnpkg.com/express-session/-/express-session-1.11.3.tgz#5cc98f3f5ff84ed835f91cbf0aabd0c7107400af" + dependencies: + cookie "0.1.3" + cookie-signature "1.0.6" + crc "3.3.0" + debug "~2.2.0" + depd "~1.0.1" + on-headers "~1.0.0" + parseurl "~1.3.0" + uid-safe "~2.0.0" + utils-merge "1.0.0" + +extend@~3.0.0, extend@~3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.1.tgz#a755ea7bc1adfcc5a31ce7e762dbaadc5e636444" + +external-editor@^2.0.4: + version "2.1.0" + resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-2.1.0.tgz#3d026a21b7f95b5726387d4200ac160d372c3b48" + dependencies: + chardet "^0.4.0" + iconv-lite "^0.4.17" + tmp "^0.0.33" + +extglob@^0.3.1: + version "0.3.2" + resolved "https://registry.yarnpkg.com/extglob/-/extglob-0.3.2.tgz#2e18ff3d2f49ab2765cec9023f011daa8d8349a1" + dependencies: + is-extglob "^1.0.0" + +extsprintf@1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" + +extsprintf@^1.2.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" + +fancy-log@^1.1.0: + version "1.3.2" + resolved "https://registry.yarnpkg.com/fancy-log/-/fancy-log-1.3.2.tgz#f41125e3d84f2e7d89a43d06d958c8f78be16be1" + dependencies: + ansi-gray "^0.1.1" + color-support "^1.1.3" + time-stamp "^1.0.0" + +fast-deep-equal@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz#96256a3bc975595eb36d82e9929d060d893439ff" + +fast-json-stable-stringify@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" + +fast-levenshtein@~2.0.4: + version "2.0.6" + resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + +fb-watchman@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.0.tgz#54e9abf7dfa2f26cd9b1636c588c1afc05de5d58" + dependencies: + bser "^2.0.0" + +fbjs-scripts@^0.8.1: + version "0.8.1" + resolved "https://registry.yarnpkg.com/fbjs-scripts/-/fbjs-scripts-0.8.1.tgz#c1c6efbecb7f008478468976b783880c2f669765" + dependencies: + babel-core "^6.7.2" + babel-preset-fbjs "^2.1.2" + core-js "^2.4.1" + cross-spawn "^5.1.0" + gulp-util "^3.0.4" + object-assign "^4.0.1" + semver "^5.1.0" + through2 "^2.0.0" + +fbjs@^0.8.14, fbjs@^0.8.16, fbjs@^0.8.9: + version "0.8.16" + resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-0.8.16.tgz#5e67432f550dc41b572bf55847b8aca64e5337db" + dependencies: + core-js "^1.0.0" + isomorphic-fetch "^2.1.1" + loose-envify "^1.0.0" + object-assign "^4.1.0" + promise "^7.1.1" + setimmediate "^1.0.5" + ua-parser-js "^0.7.9" + +figures@^1.3.5: + version "1.7.0" + resolved "https://registry.yarnpkg.com/figures/-/figures-1.7.0.tgz#cbe1e3affcf1cd44b80cadfed28dc793a9701d2e" + dependencies: + escape-string-regexp "^1.0.5" + object-assign "^4.1.0" + +figures@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962" + dependencies: + escape-string-regexp "^1.0.5" + +file-entry-cache@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-2.0.0.tgz#c392990c3e684783d838b8c84a45d8a048458361" + dependencies: + flat-cache "^1.2.1" + object-assign "^4.0.1" + +filename-regex@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.1.tgz#c1c4b9bee3e09725ddb106b75c1e301fe2f18b26" + +fill-range@^2.1.0: + version "2.2.3" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-2.2.3.tgz#50b77dfd7e469bc7492470963699fe7a8485a723" + dependencies: + is-number "^2.1.0" + isobject "^2.0.0" + randomatic "^1.1.3" + repeat-element "^1.1.2" + repeat-string "^1.5.2" + +finalhandler@0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-0.4.0.tgz#965a52d9e8d05d2b857548541fb89b53a2497d9b" + dependencies: + debug "~2.2.0" + escape-html "1.0.2" + on-finished "~2.3.0" + unpipe "~1.0.0" + +find-babel-config@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/find-babel-config/-/find-babel-config-1.1.0.tgz#acc01043a6749fec34429be6b64f542ebb5d6355" + dependencies: + json5 "^0.5.1" + path-exists "^3.0.0" + +find-up@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f" + dependencies: + path-exists "^2.0.0" + pinkie-promise "^2.0.0" + +find-up@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" + dependencies: + locate-path "^2.0.0" + +flat-cache@^1.2.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-1.3.0.tgz#d3030b32b38154f4e3b7e9c709f490f7ef97c481" + dependencies: + circular-json "^0.3.1" + del "^2.0.2" + graceful-fs "^4.1.2" + write "^0.2.1" + +flush-write-stream@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/flush-write-stream/-/flush-write-stream-1.0.2.tgz#c81b90d8746766f1a609a46809946c45dd8ae417" + dependencies: + inherits "^2.0.1" + readable-stream "^2.0.4" + +for-in@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" + +for-own@^0.1.4: + version "0.1.5" + resolved "https://registry.yarnpkg.com/for-own/-/for-own-0.1.5.tgz#5265c681a4f294dabbf17c9509b6763aa84510ce" + dependencies: + for-in "^1.0.1" + +foreach@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/foreach/-/foreach-2.0.5.tgz#0bee005018aeb260d0a3af3ae658dd0136ec1b99" + +forever-agent@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" + +form-data@~1.0.0-rc4: + version "1.0.1" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-1.0.1.tgz#ae315db9a4907fa065502304a66d7733475ee37c" + dependencies: + async "^2.0.1" + combined-stream "^1.0.5" + mime-types "^2.1.11" + +form-data@~2.1.1: + version "2.1.4" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.1.4.tgz#33c183acf193276ecaa98143a69e94bfee1750d1" + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.5" + mime-types "^2.1.12" + +form-data@~2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.1.tgz#6fb94fbd71885306d73d15cc497fe4cc4ecd44bf" + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.5" + mime-types "^2.1.12" + +fresh@0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.3.0.tgz#651f838e22424e7566de161d8358caa199f83d4f" + +from2@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/from2/-/from2-1.3.0.tgz#88413baaa5f9a597cfde9221d86986cd3c061dfd" + dependencies: + inherits "~2.0.1" + readable-stream "~1.1.10" + +from2@^2.1.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/from2/-/from2-2.3.0.tgz#8bfb5502bde4a4d36cfdeea007fcca21d7e382af" + dependencies: + inherits "^2.0.1" + readable-stream "^2.0.0" + +fs-extra@3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-3.0.1.tgz#3794f378c58b342ea7dbbb23095109c4b3b62291" + dependencies: + graceful-fs "^4.1.2" + jsonfile "^3.0.0" + universalify "^0.1.0" + +fs-extra@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-1.0.0.tgz#cd3ce5f7e7cb6145883fcae3191e9877f8587950" + dependencies: + graceful-fs "^4.1.2" + jsonfile "^2.1.0" + klaw "^1.0.0" + +fs-vacuum@~1.2.10, fs-vacuum@~1.2.9: + version "1.2.10" + resolved "https://registry.yarnpkg.com/fs-vacuum/-/fs-vacuum-1.2.10.tgz#b7629bec07a4031a2548fdf99f5ecf1cc8b31e36" + dependencies: + graceful-fs "^4.1.2" + path-is-inside "^1.0.1" + rimraf "^2.5.2" + +fs-write-stream-atomic@^1.0.8, fs-write-stream-atomic@~1.0.10, fs-write-stream-atomic@~1.0.8: + version "1.0.10" + resolved "https://registry.yarnpkg.com/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz#b47df53493ef911df75731e70a9ded0189db40c9" + dependencies: + graceful-fs "^4.1.2" + iferr "^0.1.5" + imurmurhash "^0.1.4" + readable-stream "1 || 2" + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + +fsevents@^1.1.1: + version "1.1.3" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.1.3.tgz#11f82318f5fe7bb2cd22965a108e9306208216d8" + dependencies: + nan "^2.3.0" + node-pre-gyp "^0.6.39" + +fstream-ignore@^1.0.0, fstream-ignore@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/fstream-ignore/-/fstream-ignore-1.0.5.tgz#9c31dae34767018fe1d249b24dada67d092da105" + dependencies: + fstream "^1.0.0" + inherits "2" + minimatch "^3.0.0" + +fstream-npm@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/fstream-npm/-/fstream-npm-1.1.1.tgz#6b9175db6239a83d8209e232426c494dbb29690c" + dependencies: + fstream-ignore "^1.0.0" + inherits "2" + +fstream-npm@~1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/fstream-npm/-/fstream-npm-1.2.1.tgz#08c4a452f789dcbac4c89a4563c902b2c862fd5b" + dependencies: + fstream-ignore "^1.0.0" + inherits "2" + +fstream@^1.0.0, fstream@^1.0.10, fstream@^1.0.2, fstream@~1.0.10, fstream@~1.0.11: + version "1.0.11" + resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.11.tgz#5c1fb1f117477114f0632a0eb4b71b3cb0fd3171" + dependencies: + graceful-fs "^4.1.2" + inherits "~2.0.0" + mkdirp ">=0.5 0" + rimraf "2" + +function-bind@^1.0.2, function-bind@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + +gauge@~1.2.5: + version "1.2.7" + resolved "https://registry.yarnpkg.com/gauge/-/gauge-1.2.7.tgz#e9cec5483d3d4ee0ef44b60a7d99e4935e136d93" + dependencies: + ansi "^0.3.0" + has-unicode "^2.0.0" + lodash.pad "^4.1.0" + lodash.padend "^4.1.0" + lodash.padstart "^4.1.0" + +gauge@~2.6.0: + version "2.6.0" + resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.6.0.tgz#d35301ad18e96902b4751dcbbe40f4218b942a46" + dependencies: + aproba "^1.0.3" + console-control-strings "^1.0.0" + has-color "^0.1.7" + has-unicode "^2.0.0" + object-assign "^4.1.0" + signal-exit "^3.0.0" + string-width "^1.0.1" + strip-ansi "^3.0.1" + wide-align "^1.1.0" + +gauge@~2.7.3: + version "2.7.4" + resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" + dependencies: + aproba "^1.0.3" + console-control-strings "^1.0.0" + has-unicode "^2.0.0" + object-assign "^4.1.0" + signal-exit "^3.0.0" + string-width "^1.0.1" + strip-ansi "^3.0.1" + wide-align "^1.1.0" + +generate-function@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/generate-function/-/generate-function-2.0.0.tgz#6858fe7c0969b7d4e9093337647ac79f60dfbe74" + +generate-object-property@^1.1.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/generate-object-property/-/generate-object-property-1.2.0.tgz#9c0e1c40308ce804f4783618b937fa88f99d50d0" + dependencies: + is-property "^1.0.0" + +genfun@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/genfun/-/genfun-4.0.1.tgz#ed10041f2e4a7f1b0a38466d17a5c3e27df1dfc1" + +get-caller-file@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.2.tgz#f702e63127e7e231c160a80c1554acb70d5047e5" + +get-stream@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" + +getpass@^0.1.1: + version "0.1.7" + resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" + dependencies: + assert-plus "^1.0.0" + +gitbook-cli@^2.3.0: + version "2.3.2" + resolved "https://registry.yarnpkg.com/gitbook-cli/-/gitbook-cli-2.3.2.tgz#5e893582e1f743f6fa920c3c3eb36b62ea4a31a0" + dependencies: + bash-color "0.0.4" + commander "2.11.0" + fs-extra "3.0.1" + lodash "4.17.4" + npm "5.1.0" + npmi "1.0.1" + optimist "0.6.1" + q "1.5.0" + semver "5.3.0" + tmp "0.0.31" + user-home "2.0.0" + +github-url-from-git@~1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/github-url-from-git/-/github-url-from-git-1.4.0.tgz#285e6b520819001bde128674704379e4ff03e0de" + +github-url-from-username-repo@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/github-url-from-username-repo/-/github-url-from-username-repo-1.0.2.tgz#7dd79330d2abe69c10c2cef79714c97215791dfa" + +glob-base@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/glob-base/-/glob-base-0.3.0.tgz#dbb164f6221b1c0b1ccf82aea328b497df0ea3c4" + dependencies: + glob-parent "^2.0.0" + is-glob "^2.0.0" + +glob-parent@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-2.0.0.tgz#81383d72db054fcccf5336daa902f182f6edbb28" + dependencies: + is-glob "^2.0.0" + +glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.1.1, glob@^7.1.2, glob@~7.1.2: + version "7.1.2" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +glob@~7.0.6: + version "7.0.6" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.0.6.tgz#211bafaf49e525b8cd93260d14ab136152b3f57a" + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.2" + once "^1.3.0" + path-is-absolute "^1.0.0" + +global@^4.3.0: + version "4.3.2" + resolved "https://registry.yarnpkg.com/global/-/global-4.3.2.tgz#e76989268a6c74c38908b1305b10fc0e394e9d0f" + dependencies: + min-document "^2.19.0" + process "~0.5.1" + +globals@^9.14.0, globals@^9.18.0: + version "9.18.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a" + +globby@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/globby/-/globby-5.0.0.tgz#ebd84667ca0dbb330b99bcfc68eac2bc54370e0d" + dependencies: + array-union "^1.0.1" + arrify "^1.0.0" + glob "^7.0.3" + object-assign "^4.0.1" + pify "^2.0.0" + pinkie-promise "^2.0.0" + +glogg@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/glogg/-/glogg-1.0.0.tgz#7fe0f199f57ac906cf512feead8f90ee4a284fc5" + dependencies: + sparkles "^1.0.0" + +got@^6.7.1: + version "6.7.1" + resolved "https://registry.yarnpkg.com/got/-/got-6.7.1.tgz#240cd05785a9a18e561dc1b44b41c763ef1e8db0" + dependencies: + create-error-class "^3.0.0" + duplexer3 "^0.1.4" + get-stream "^3.0.0" + is-redirect "^1.0.0" + is-retry-allowed "^1.0.0" + is-stream "^1.0.0" + lowercase-keys "^1.0.0" + safe-buffer "^5.0.1" + timed-out "^4.0.0" + unzip-response "^2.0.1" + url-parse-lax "^1.0.0" + +graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.3, graceful-fs@^4.1.6, graceful-fs@^4.1.9, graceful-fs@~4.1.11, graceful-fs@~4.1.6: + version "4.1.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" + +growly@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081" + +gulp-util@^3.0.4: + version "3.0.8" + resolved "https://registry.yarnpkg.com/gulp-util/-/gulp-util-3.0.8.tgz#0054e1e744502e27c04c187c3ecc505dd54bbb4f" + dependencies: + array-differ "^1.0.0" + array-uniq "^1.0.2" + beeper "^1.0.0" + chalk "^1.0.0" + dateformat "^2.0.0" + fancy-log "^1.1.0" + gulplog "^1.0.0" + has-gulplog "^0.1.0" + lodash._reescape "^3.0.0" + lodash._reevaluate "^3.0.0" + lodash._reinterpolate "^3.0.0" + lodash.template "^3.0.0" + minimist "^1.1.0" + multipipe "^0.1.2" + object-assign "^3.0.0" + replace-ext "0.0.1" + through2 "^2.0.0" + vinyl "^0.5.0" + +gulplog@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/gulplog/-/gulplog-1.0.0.tgz#e28c4d45d05ecbbed818363ce8f9c5926229ffe5" + dependencies: + glogg "^1.0.0" + +har-schema@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-1.0.5.tgz#d263135f43307c02c602afc8fe95970c0151369e" + +har-schema@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" + +har-validator@~2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-2.0.6.tgz#cdcbc08188265ad119b6a5a7c8ab70eecfb5d27d" + dependencies: + chalk "^1.1.1" + commander "^2.9.0" + is-my-json-valid "^2.12.4" + pinkie-promise "^2.0.0" + +har-validator@~4.2.1: + version "4.2.1" + resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-4.2.1.tgz#33481d0f1bbff600dd203d75812a6a5fba002e2a" + dependencies: + ajv "^4.9.1" + har-schema "^1.0.5" + +har-validator@~5.0.3: + version "5.0.3" + resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.0.3.tgz#ba402c266194f15956ef15e0fcf242993f6a7dfd" + dependencies: + ajv "^5.1.0" + har-schema "^2.0.0" + +has-ansi@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" + dependencies: + ansi-regex "^2.0.0" + +has-color@^0.1.7: + version "0.1.7" + resolved "https://registry.yarnpkg.com/has-color/-/has-color-0.1.7.tgz#67144a5260c34fc3cca677d041daf52fe7b78b2f" + +has-flag@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-2.0.0.tgz#e8207af1cc7b30d446cc70b734b5e8be18f88d51" + +has-gulplog@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/has-gulplog/-/has-gulplog-0.1.0.tgz#6414c82913697da51590397dafb12f22967811ce" + dependencies: + sparkles "^1.0.0" + +has-symbols@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.0.tgz#ba1a8f1af2a0fc39650f5c850367704122063b44" + +has-unicode@^2.0.0, has-unicode@~2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" + +has@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.1.tgz#8461733f538b0837c9361e39a9ab9e9704dc2f28" + dependencies: + function-bind "^1.0.2" + +hawk@3.1.3, hawk@~3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/hawk/-/hawk-3.1.3.tgz#078444bd7c1640b0fe540d2c9b73d59678e8e1c4" + dependencies: + boom "2.x.x" + cryptiles "2.x.x" + hoek "2.x.x" + sntp "1.x.x" + +hawk@~6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/hawk/-/hawk-6.0.2.tgz#af4d914eb065f9b5ce4d9d11c1cb2126eecc3038" + dependencies: + boom "4.x.x" + cryptiles "3.x.x" + hoek "4.x.x" + sntp "2.x.x" + +hoek@2.x.x: + version "2.16.3" + resolved "https://registry.yarnpkg.com/hoek/-/hoek-2.16.3.tgz#20bb7403d3cea398e91dc4710a8ff1b8274a25ed" + +hoek@4.x.x: + version "4.2.0" + resolved "https://registry.yarnpkg.com/hoek/-/hoek-4.2.0.tgz#72d9d0754f7fe25ca2d01ad8f8f9a9449a89526d" + +home-or-tmp@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/home-or-tmp/-/home-or-tmp-2.0.0.tgz#e36c3f2d2cae7d746a857e38d18d5f32a7882db8" + dependencies: + os-homedir "^1.0.0" + os-tmpdir "^1.0.1" + +hosted-git-info@^2.1.4, hosted-git-info@^2.1.5, hosted-git-info@^2.4.2, hosted-git-info@~2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.5.0.tgz#6d60e34b3abbc8313062c3b798ef8d901a07af3c" + +hosted-git-info@~2.1.5: + version "2.1.5" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.1.5.tgz#0ba81d90da2e25ab34a332e6ec77936e1598118b" + +http-cache-semantics@^3.8.0: + version "3.8.1" + resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz#39b0e16add9b605bf0a9ef3d9daaf4843b4cacd2" + +http-errors@~1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.3.1.tgz#197e22cdebd4198585e8694ef6786197b91ed942" + dependencies: + inherits "~2.0.1" + statuses "1" + +http-proxy-agent@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-2.0.0.tgz#46482a2f0523a4d6082551709f469cb3e4a85ff4" + dependencies: + agent-base "4" + debug "2" + +http-signature@~1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.1.1.tgz#df72e267066cd0ac67fb76adf8e134a8fbcf91bf" + dependencies: + assert-plus "^0.2.0" + jsprim "^1.2.2" + sshpk "^1.7.0" + +http-signature@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" + dependencies: + assert-plus "^1.0.0" + jsprim "^1.2.2" + sshpk "^1.7.0" + +https-proxy-agent@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-2.1.1.tgz#a7ce4382a1ba8266ee848578778122d491260fd9" + dependencies: + agent-base "^4.1.0" + debug "^3.1.0" + +humanize-ms@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/humanize-ms/-/humanize-ms-1.2.1.tgz#c46e3159a293f6b896da29316d8b6fe8bb79bbed" + dependencies: + ms "^2.0.0" + +iconv-lite@0.4.11: + version "0.4.11" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.11.tgz#2ecb42fd294744922209a2e7c404dac8793d8ade" + +iconv-lite@0.4.13: + version "0.4.13" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.13.tgz#1f88aba4ab0b1508e8312acc39345f36e992e2f2" + +iconv-lite@^0.4.17, iconv-lite@~0.4.13: + version "0.4.19" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.19.tgz#f7468f60135f5e5dad3399c0a81be9a1603a082b" + +iferr@^0.1.5, iferr@~0.1.5: + version "0.1.5" + resolved "https://registry.yarnpkg.com/iferr/-/iferr-0.1.5.tgz#c60eed69e6d8fdb6b3104a1fcbca1c192dc5b501" + +ignore@^3.2.0: + version "3.3.7" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.7.tgz#612289bfb3c220e186a58118618d5be8c1bab021" + +image-size@^0.6.0: + version "0.6.2" + resolved "https://registry.yarnpkg.com/image-size/-/image-size-0.6.2.tgz#8ee316d4298b028b965091b673d5f1537adee5b4" + +import-lazy@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-2.1.0.tgz#05698e3d45c88e8d7e9d92cb0584e77f096f3e43" + +imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + +inflight@^1.0.4, inflight@~1.0.4, inflight@~1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.0, inherits@~2.0.1, inherits@~2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" + +ini@^1.3.4, ini@~1.3.0, ini@~1.3.4: + version "1.3.5" + resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" + +init-package-json@~1.10.1: + version "1.10.1" + resolved "https://registry.yarnpkg.com/init-package-json/-/init-package-json-1.10.1.tgz#cd873a167796befb99612b28762a0b6393fd8f6a" + dependencies: + glob "^7.1.1" + npm-package-arg "^4.0.0 || ^5.0.0" + promzard "^0.3.0" + read "~1.0.1" + read-package-json "1 || 2" + semver "2.x || 3.x || 4 || 5" + validate-npm-package-license "^3.0.1" + validate-npm-package-name "^3.0.0" + +init-package-json@~1.9.4: + version "1.9.6" + resolved "https://registry.yarnpkg.com/init-package-json/-/init-package-json-1.9.6.tgz#789fc2b74466a4952b9ea77c0575bc78ebd60a61" + dependencies: + glob "^7.1.1" + npm-package-arg "^4.0.0 || ^5.0.0" + promzard "^0.3.0" + read "~1.0.1" + read-package-json "1 || 2" + semver "2.x || 3.x || 4 || 5" + validate-npm-package-license "^3.0.1" + validate-npm-package-name "^3.0.0" + +inquirer@^0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-0.12.0.tgz#1ef2bfd63504df0bc75785fff8c2c41df12f077e" + dependencies: + ansi-escapes "^1.1.0" + ansi-regex "^2.0.0" + chalk "^1.0.0" + cli-cursor "^1.0.1" + cli-width "^2.0.0" + figures "^1.3.5" + lodash "^4.3.0" + readline2 "^1.0.1" + run-async "^0.1.0" + rx-lite "^3.1.2" + string-width "^1.0.1" + strip-ansi "^3.0.0" + through "^2.3.6" + +inquirer@^3.0.6: + version "3.3.0" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-3.3.0.tgz#9dd2f2ad765dcab1ff0443b491442a20ba227dc9" + dependencies: + ansi-escapes "^3.0.0" + chalk "^2.0.0" + cli-cursor "^2.1.0" + cli-width "^2.0.0" + external-editor "^2.0.4" + figures "^2.0.0" + lodash "^4.3.0" + mute-stream "0.0.7" + run-async "^2.2.0" + rx-lite "^4.0.8" + rx-lite-aggregates "^4.0.8" + string-width "^2.1.0" + strip-ansi "^4.0.0" + through "^2.3.6" + +interpret@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.1.0.tgz#7ed1b1410c6a0e0f78cf95d3b8440c63f78b8614" + +invariant@^2.2.2: + version "2.2.2" + resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.2.tgz#9e1f56ac0acdb6bf303306f338be3b204ae60360" + dependencies: + loose-envify "^1.0.0" + +invert-kv@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6" + +ip@^1.1.4: + version "1.1.5" + resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a" + +is-arrayish@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" + +is-buffer@^1.1.5: + version "1.1.6" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" + +is-builtin-module@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-builtin-module/-/is-builtin-module-1.0.0.tgz#540572d34f7ac3119f8f76c30cbc1b1e037affbe" + dependencies: + builtin-modules "^1.0.0" + +is-callable@^1.1.1, is-callable@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.3.tgz#86eb75392805ddc33af71c92a0eedf74ee7604b2" + +is-date-object@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.1.tgz#9aa20eb6aeebbff77fbd33e74ca01b33581d3a16" + +is-dotfile@^1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/is-dotfile/-/is-dotfile-1.0.3.tgz#a6a2f32ffd2dfb04f5ca25ecd0f6b83cf798a1e1" + +is-equal-shallow@^0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz#2238098fc221de0bcfa5d9eac4c45d638aa1c534" + dependencies: + is-primitive "^2.0.0" + +is-extendable@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" + +is-extglob@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-1.0.0.tgz#ac468177c4943405a092fc8f29760c6ffc6206c0" + +is-finite@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.0.2.tgz#cc6677695602be550ef11e8b4aa6305342b6d0aa" + dependencies: + number-is-nan "^1.0.0" + +is-fullwidth-code-point@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" + dependencies: + number-is-nan "^1.0.0" + +is-fullwidth-code-point@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" + +is-glob@^2.0.0, is-glob@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-2.0.1.tgz#d096f926a3ded5600f3fdfd91198cb0888c2d863" + dependencies: + is-extglob "^1.0.0" + +is-my-json-valid@^2.10.0, is-my-json-valid@^2.12.4: + version "2.17.1" + resolved "https://registry.yarnpkg.com/is-my-json-valid/-/is-my-json-valid-2.17.1.tgz#3da98914a70a22f0a8563ef1511a246c6fc55471" + dependencies: + generate-function "^2.0.0" + generate-object-property "^1.1.0" + jsonpointer "^4.0.0" + xtend "^4.0.0" + +is-npm@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-npm/-/is-npm-1.0.0.tgz#f2fb63a65e4905b406c86072765a1a4dc793b9f4" + +is-number@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-2.1.0.tgz#01fcbbb393463a548f2f466cce16dece49db908f" + dependencies: + kind-of "^3.0.2" + +is-number@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" + dependencies: + kind-of "^3.0.2" + +is-obj@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" + +is-path-cwd@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-1.0.0.tgz#d225ec23132e89edd38fda767472e62e65f1106d" + +is-path-in-cwd@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz#6477582b8214d602346094567003be8a9eac04dc" + dependencies: + is-path-inside "^1.0.0" + +is-path-inside@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-1.0.1.tgz#8ef5b7de50437a3fdca6b4e865ef7aa55cb48036" + dependencies: + path-is-inside "^1.0.1" + +is-posix-bracket@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz#3334dc79774368e92f016e6fbc0a88f5cd6e6bc4" + +is-primitive@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-primitive/-/is-primitive-2.0.0.tgz#207bab91638499c07b2adf240a41a87210034575" + +is-promise@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa" + +is-property@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-property/-/is-property-1.0.2.tgz#57fe1c4e48474edd65b09911f26b1cd4095dda84" + +is-redirect@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-redirect/-/is-redirect-1.0.0.tgz#1d03dded53bd8db0f30c26e4f95d36fc7c87dc24" + +is-regex@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.4.tgz#5517489b547091b0930e095654ced25ee97e9491" + dependencies: + has "^1.0.1" + +is-resolvable@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.1.0.tgz#fb18f87ce1feb925169c9a407c19318a3206ed88" + +is-retry-allowed@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz#11a060568b67339444033d0125a61a20d564fb34" + +is-stream@^1.0.0, is-stream@^1.0.1, is-stream@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" + +is-symbol@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.1.tgz#3cc59f00025194b6ab2e38dbae6689256b660572" + +is-typedarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" + +isarray@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" + +isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + +isobject@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" + dependencies: + isarray "1.0.0" + +isomorphic-fetch@^2.1.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz#611ae1acf14f5e81f729507472819fe9733558a9" + dependencies: + node-fetch "^1.0.1" + whatwg-fetch ">=0.10.0" + +isstream@~0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" + +jest-docblock@^21, jest-docblock@^21.2.0: + version "21.2.0" + resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-21.2.0.tgz#51529c3b30d5fd159da60c27ceedc195faf8d414" + +jest-haste-map@^21: + version "21.2.0" + resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-21.2.0.tgz#1363f0a8bb4338f24f001806571eff7a4b2ff3d8" + dependencies: + fb-watchman "^2.0.0" + graceful-fs "^4.1.11" + jest-docblock "^21.2.0" + micromatch "^2.3.11" + sane "^2.0.0" + worker-farm "^1.3.1" + +js-tokens@^3.0.0, js-tokens@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" + +js-yaml@^3.5.1: + version "3.10.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.10.0.tgz#2e78441646bd4682e963f22b6e92823c309c62dc" + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + +jsbn@~0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" + +jsesc@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b" + +jsesc@~0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" + +json-parse-better-errors@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.1.tgz#50183cd1b2d25275de069e9e71b467ac9eab973a" + +json-schema-traverse@^0.3.0: + version "0.3.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz#349a6d44c53a51de89b40805c5d5e59b417d3340" + +json-schema@0.2.3: + version "0.2.3" + resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" + +json-stable-stringify@^1.0.0, json-stable-stringify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz#9a759d39c5f2ff503fd5300646ed445f88c4f9af" + dependencies: + jsonify "~0.0.0" + +json-stringify-safe@~5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" + +json5@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/json5/-/json5-0.4.0.tgz#054352e4c4c80c86c0923877d449de176a732c8d" + +json5@^0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821" + +jsonfile@^2.1.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-2.4.0.tgz#3736a2b428b87bbda0cc83b53fa3d633a35c2ae8" + optionalDependencies: + graceful-fs "^4.1.6" + +jsonfile@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-3.0.1.tgz#a5ecc6f65f53f662c4415c7675a0331d0992ec66" + optionalDependencies: + graceful-fs "^4.1.6" + +jsonify@~0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" + +jsonparse@^1.2.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280" + +jsonpointer@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/jsonpointer/-/jsonpointer-4.0.1.tgz#4fd92cb34e0e9db3c89c8622ecf51f9b978c6cb9" + +jsprim@^1.2.2: + version "1.4.1" + resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" + dependencies: + assert-plus "1.0.0" + extsprintf "1.3.0" + json-schema "0.2.3" + verror "1.10.0" + +jsx-ast-utils@^1.0.0, jsx-ast-utils@^1.3.4: + version "1.4.1" + resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-1.4.1.tgz#3867213e8dd79bf1e8f2300c0cfc1efb182c0df1" + +kind-of@^3.0.2: + version "3.2.2" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" + dependencies: + is-buffer "^1.1.5" + +kind-of@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57" + dependencies: + is-buffer "^1.1.5" + +klaw@^1.0.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/klaw/-/klaw-1.3.1.tgz#4088433b46b3b1ba259d78785d8e96f73ba02439" + optionalDependencies: + graceful-fs "^4.1.9" + +latest-version@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/latest-version/-/latest-version-3.1.0.tgz#a205383fea322b33b5ae3b18abee0dc2f356ee15" + dependencies: + package-json "^4.0.0" + +lazy-property@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/lazy-property/-/lazy-property-1.0.0.tgz#84ddc4b370679ba8bd4cdcfa4c06b43d57111147" + +lcid@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835" + dependencies: + invert-kv "^1.0.0" + +left-pad@^1.1.3: + version "1.2.0" + resolved "https://registry.yarnpkg.com/left-pad/-/left-pad-1.2.0.tgz#d30a73c6b8201d8f7d8e7956ba9616087a68e0ee" + +levn@^0.3.0, levn@~0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" + dependencies: + prelude-ls "~1.1.2" + type-check "~0.3.2" + +load-json-file@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-2.0.0.tgz#7947e42149af80d696cbf797bcaabcfe1fe29ca8" + dependencies: + graceful-fs "^4.1.2" + parse-json "^2.2.0" + pify "^2.0.0" + strip-bom "^3.0.0" + +locate-path@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" + dependencies: + p-locate "^2.0.0" + path-exists "^3.0.0" + +lockfile@~1.0.1, lockfile@~1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/lockfile/-/lockfile-1.0.3.tgz#2638fc39a0331e9cac1a04b71799931c9c50df79" + +lodash._basecopy@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz#8da0e6a876cf344c0ad8a54882111dd3c5c7ca36" + +lodash._basetostring@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/lodash._basetostring/-/lodash._basetostring-3.0.1.tgz#d1861d877f824a52f669832dcaf3ee15566a07d5" + +lodash._baseuniq@~4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/lodash._baseuniq/-/lodash._baseuniq-4.6.0.tgz#0ebb44e456814af7905c6212fa2c9b2d51b841e8" + dependencies: + lodash._createset "~4.0.0" + lodash._root "~3.0.0" + +lodash._basevalues@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/lodash._basevalues/-/lodash._basevalues-3.0.0.tgz#5b775762802bde3d3297503e26300820fdf661b7" + +lodash._createset@~4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/lodash._createset/-/lodash._createset-4.0.3.tgz#0f4659fbb09d75194fa9e2b88a6644d363c9fe26" + +lodash._getnative@^3.0.0: + version "3.9.1" + resolved "https://registry.yarnpkg.com/lodash._getnative/-/lodash._getnative-3.9.1.tgz#570bc7dede46d61cdcde687d65d3eecbaa3aaff5" + +lodash._isiterateecall@^3.0.0: + version "3.0.9" + resolved "https://registry.yarnpkg.com/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz#5203ad7ba425fae842460e696db9cf3e6aac057c" + +lodash._reescape@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/lodash._reescape/-/lodash._reescape-3.0.0.tgz#2b1d6f5dfe07c8a355753e5f27fac7f1cde1616a" + +lodash._reevaluate@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/lodash._reevaluate/-/lodash._reevaluate-3.0.0.tgz#58bc74c40664953ae0b124d806996daca431e2ed" + +lodash._reinterpolate@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d" + +lodash._root@^3.0.0, lodash._root@~3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/lodash._root/-/lodash._root-3.0.1.tgz#fba1c4524c19ee9a5f8136b4609f017cf4ded692" + +lodash.assign@^4.0.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/lodash.assign/-/lodash.assign-4.2.0.tgz#0d99f3ccd7a6d261d19bdaeb9245005d285808e7" + +lodash.clonedeep@~4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef" + +lodash.cond@^4.3.0: + version "4.5.2" + resolved "https://registry.yarnpkg.com/lodash.cond/-/lodash.cond-4.5.2.tgz#f471a1da486be60f6ab955d17115523dd1d255d5" + +lodash.endswith@^4.0.1: + version "4.2.1" + resolved "https://registry.yarnpkg.com/lodash.endswith/-/lodash.endswith-4.2.1.tgz#fed59ac1738ed3e236edd7064ec456448b37bc09" + +lodash.escape@^3.0.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/lodash.escape/-/lodash.escape-3.2.0.tgz#995ee0dc18c1b48cc92effae71a10aab5b487698" + dependencies: + lodash._root "^3.0.0" + +lodash.find@^4.3.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/lodash.find/-/lodash.find-4.6.0.tgz#cb0704d47ab71789ffa0de8b97dd926fb88b13b1" + +lodash.findindex@^4.3.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/lodash.findindex/-/lodash.findindex-4.6.0.tgz#a3245dee61fb9b6e0624b535125624bb69c11106" + +lodash.isarguments@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz#2f573d85c6a24289ff00663b491c1d338ff3458a" + +lodash.isarray@^3.0.0: + version "3.0.4" + resolved "https://registry.yarnpkg.com/lodash.isarray/-/lodash.isarray-3.0.4.tgz#79e4eb88c36a8122af86f844aa9bcd851b5fbb55" + +lodash.keys@^3.0.0: + version "3.1.2" + resolved "https://registry.yarnpkg.com/lodash.keys/-/lodash.keys-3.1.2.tgz#4dbc0472b156be50a0b286855d1bd0b0c656098a" + dependencies: + lodash._getnative "^3.0.0" + lodash.isarguments "^3.0.0" + lodash.isarray "^3.0.0" + +lodash.pad@^4.1.0: + version "4.5.1" + resolved "https://registry.yarnpkg.com/lodash.pad/-/lodash.pad-4.5.1.tgz#4330949a833a7c8da22cc20f6a26c4d59debba70" + +lodash.padend@^4.1.0: + version "4.6.1" + resolved "https://registry.yarnpkg.com/lodash.padend/-/lodash.padend-4.6.1.tgz#53ccba047d06e158d311f45da625f4e49e6f166e" + +lodash.padstart@^4.1.0: + version "4.6.1" + resolved "https://registry.yarnpkg.com/lodash.padstart/-/lodash.padstart-4.6.1.tgz#d2e3eebff0d9d39ad50f5cbd1b52a7bce6bb611b" + +lodash.pickby@^4.0.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/lodash.pickby/-/lodash.pickby-4.6.0.tgz#7dea21d8c18d7703a27c704c15d3b84a67e33aff" + +lodash.restparam@^3.0.0: + version "3.6.1" + resolved "https://registry.yarnpkg.com/lodash.restparam/-/lodash.restparam-3.6.1.tgz#936a4e309ef330a7645ed4145986c85ae5b20805" + +lodash.template@^3.0.0: + version "3.6.2" + resolved "https://registry.yarnpkg.com/lodash.template/-/lodash.template-3.6.2.tgz#f8cdecc6169a255be9098ae8b0c53d378931d14f" + dependencies: + lodash._basecopy "^3.0.0" + lodash._basetostring "^3.0.0" + lodash._basevalues "^3.0.0" + lodash._isiterateecall "^3.0.0" + lodash._reinterpolate "^3.0.0" + lodash.escape "^3.0.0" + lodash.keys "^3.0.0" + lodash.restparam "^3.0.0" + lodash.templatesettings "^3.0.0" + +lodash.templatesettings@^3.0.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz#fb307844753b66b9f1afa54e262c745307dba8e5" + dependencies: + lodash._reinterpolate "^3.0.0" + lodash.escape "^3.0.0" + +lodash.union@~4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/lodash.union/-/lodash.union-4.6.0.tgz#48bb5088409f16f1821666641c44dd1aaae3cd88" + +lodash.uniq@~4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" + +lodash.without@~4.4.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/lodash.without/-/lodash.without-4.4.0.tgz#3cd4574a00b67bae373a94b748772640507b7aac" + +lodash@4.17.4, lodash@^4.0.0, lodash@^4.14.0, lodash@^4.16.6, lodash@^4.17.2, lodash@^4.17.4, lodash@^4.3.0, lodash@^4.6.1: + version "4.17.4" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae" + +lodash@^3.5.0: + version "3.10.1" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-3.10.1.tgz#5bf45e8e49ba4189e17d482789dfd15bd140b7b6" + +loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.3.1.tgz#d1a8ad33fa9ce0e713d65fdd0ac8b748d478c848" + dependencies: + js-tokens "^3.0.0" + +lowercase-keys@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.0.tgz#4e3366b39e7f5457e35f1324bdf6f88d0bfc7306" + +lru-cache@^4.0.1, lru-cache@^4.1.1, lru-cache@~4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.1.tgz#622e32e82488b49279114a4f9ecf45e7cd6bba55" + dependencies: + pseudomap "^1.0.2" + yallist "^2.1.2" + +lru-cache@~4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.0.2.tgz#1d17679c069cda5d040991a09dbc2c0db377e55e" + dependencies: + pseudomap "^1.0.1" + yallist "^2.0.0" + +macos-release@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/macos-release/-/macos-release-1.1.0.tgz#831945e29365b470aa8724b0ab36c8f8959d10fb" + +make-dir@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.1.0.tgz#19b4369fe48c116f53c2af95ad102c0e39e85d51" + dependencies: + pify "^3.0.0" + +make-fetch-happen@^2.4.13: + version "2.6.0" + resolved "https://registry.yarnpkg.com/make-fetch-happen/-/make-fetch-happen-2.6.0.tgz#8474aa52198f6b1ae4f3094c04e8370d35ea8a38" + dependencies: + agentkeepalive "^3.3.0" + cacache "^10.0.0" + http-cache-semantics "^3.8.0" + http-proxy-agent "^2.0.0" + https-proxy-agent "^2.1.0" + lru-cache "^4.1.1" + mississippi "^1.2.0" + node-fetch-npm "^2.0.2" + promise-retry "^1.1.1" + socks-proxy-agent "^3.0.1" + ssri "^5.0.0" + +makeerror@1.0.x: + version "1.0.11" + resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.11.tgz#e01a5c9109f2af79660e4e8b9587790184f5a96c" + dependencies: + tmpl "1.0.x" + +media-typer@0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" + +mem@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/mem/-/mem-1.1.0.tgz#5edd52b485ca1d900fe64895505399a0dfa45f76" + dependencies: + mimic-fn "^1.0.0" + +merge-stream@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-1.0.1.tgz#4041202d508a342ba00174008df0c251b8c135e1" + dependencies: + readable-stream "^2.0.1" + +merge@^1.1.3: + version "1.2.0" + resolved "https://registry.yarnpkg.com/merge/-/merge-1.2.0.tgz#7531e39d4949c281a66b8c5a6e0265e8b05894da" + +method-override@~2.3.5: + version "2.3.10" + resolved "https://registry.yarnpkg.com/method-override/-/method-override-2.3.10.tgz#e3daf8d5dee10dd2dce7d4ae88d62bbee77476b4" + dependencies: + debug "2.6.9" + methods "~1.1.2" + parseurl "~1.3.2" + vary "~1.1.2" + +methods@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" + +metro-bundler@^0.20.0: + version "0.20.3" + resolved "https://registry.yarnpkg.com/metro-bundler/-/metro-bundler-0.20.3.tgz#0ded01b64e8963117017b106f75b83cfc34f3656" + dependencies: + absolute-path "^0.0.0" + async "^2.4.0" + babel-core "^6.24.1" + babel-generator "^6.24.1" + babel-plugin-external-helpers "^6.18.0" + babel-preset-es2015-node "^6.1.1" + babel-preset-fbjs "^2.1.4" + babel-preset-react-native "^4.0.0" + babel-register "^6.24.1" + babylon "^6.18.0" + chalk "^1.1.1" + concat-stream "^1.6.0" + core-js "^2.2.2" + debug "^2.2.0" + denodeify "^1.2.1" + fbjs "^0.8.14" + graceful-fs "^4.1.3" + image-size "^0.6.0" + jest-docblock "^21" + jest-haste-map "^21" + json-stable-stringify "^1.0.1" + json5 "^0.4.0" + left-pad "^1.1.3" + lodash "^4.16.6" + merge-stream "^1.0.1" + mime-types "2.1.11" + mkdirp "^0.5.1" + request "^2.79.0" + rimraf "^2.5.4" + source-map "^0.5.6" + temp "0.8.3" + throat "^4.1.0" + uglify-es "^3.1.8" + wordwrap "^1.0.0" + write-file-atomic "^1.2.0" + xpipe "^1.0.5" + +micromatch@^2.1.5, micromatch@^2.3.11: + version "2.3.11" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-2.3.11.tgz#86677c97d1720b363431d04d0d15293bd38c1565" + dependencies: + arr-diff "^2.0.0" + array-unique "^0.2.1" + braces "^1.8.2" + expand-brackets "^0.1.4" + extglob "^0.3.1" + filename-regex "^2.0.0" + is-extglob "^1.0.0" + is-glob "^2.0.1" + kind-of "^3.0.2" + normalize-path "^2.0.1" + object.omit "^2.0.0" + parse-glob "^3.0.4" + regex-cache "^0.4.2" + +"mime-db@>= 1.30.0 < 2": + version "1.32.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.32.0.tgz#485b3848b01a3cda5f968b4882c0771e58e09414" + +mime-db@~1.23.0: + version "1.23.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.23.0.tgz#a31b4070adaea27d732ea333740a64d0ec9a6659" + +mime-db@~1.30.0: + version "1.30.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.30.0.tgz#74c643da2dd9d6a45399963465b26d5ca7d71f01" + +mime-types@2.1.11: + version "2.1.11" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.11.tgz#c259c471bda808a85d6cd193b430a5fae4473b3c" + dependencies: + mime-db "~1.23.0" + +mime-types@^2.1.11, mime-types@^2.1.12, mime-types@~2.1.15, mime-types@~2.1.16, mime-types@~2.1.17, mime-types@~2.1.6, mime-types@~2.1.7, mime-types@~2.1.9: + version "2.1.17" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.17.tgz#09d7a393f03e995a79f8af857b70a9e0ab16557a" + dependencies: + mime-db "~1.30.0" + +mime@1.3.4: + version "1.3.4" + resolved "https://registry.yarnpkg.com/mime/-/mime-1.3.4.tgz#115f9e3b6b3daf2959983cb38f149a2d40eb5d53" + +mime@^1.3.4: + version "1.6.0" + resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" + +mimic-fn@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.1.0.tgz#e667783d92e89dbd342818b5230b9d62a672ad18" + +min-document@^2.19.0: + version "2.19.0" + resolved "https://registry.yarnpkg.com/min-document/-/min-document-2.19.0.tgz#7bd282e3f5842ed295bb748cdd9f1ffa2c824685" + dependencies: + dom-walk "^0.1.0" + +minimatch@^3.0.0, minimatch@^3.0.2, minimatch@^3.0.3, minimatch@^3.0.4, minimatch@~3.0.3: + version "3.0.4" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" + dependencies: + brace-expansion "^1.1.7" + +minimist@0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" + +minimist@^1.1.0, minimist@^1.1.1, minimist@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" + +minimist@~0.0.1: + version "0.0.10" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf" + +mississippi@^1.2.0, mississippi@^1.3.0, mississippi@~1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/mississippi/-/mississippi-1.3.0.tgz#d201583eb12327e3c5c1642a404a9cacf94e34f5" + dependencies: + concat-stream "^1.5.0" + duplexify "^3.4.2" + end-of-stream "^1.1.0" + flush-write-stream "^1.0.0" + from2 "^2.1.0" + parallel-transform "^1.1.0" + pump "^1.0.0" + pumpify "^1.3.3" + stream-each "^1.1.0" + through2 "^2.0.0" + +"mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0, mkdirp@~0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" + dependencies: + minimist "0.0.8" + +morgan@~1.6.1: + version "1.6.1" + resolved "https://registry.yarnpkg.com/morgan/-/morgan-1.6.1.tgz#5fd818398c6819cba28a7cd6664f292fe1c0bbf2" + dependencies: + basic-auth "~1.0.3" + debug "~2.2.0" + depd "~1.0.1" + on-finished "~2.3.0" + on-headers "~1.0.0" + +move-concurrently@^1.0.1, move-concurrently@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/move-concurrently/-/move-concurrently-1.0.1.tgz#be2c005fda32e0b29af1f05d7c4b33214c701f92" + dependencies: + aproba "^1.1.1" + copy-concurrently "^1.0.0" + fs-write-stream-atomic "^1.0.8" + mkdirp "^0.5.1" + rimraf "^2.5.4" + run-queue "^1.0.3" + +ms@0.7.1: + version "0.7.1" + resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.1.tgz#9cd13c03adbff25b65effde7ce864ee952017098" + +ms@0.7.2: + version "0.7.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.2.tgz#ae25cf2512b3885a1d95d7f037868d8431124765" + +ms@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + +ms@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" + +multiparty@3.3.2: + version "3.3.2" + resolved "https://registry.yarnpkg.com/multiparty/-/multiparty-3.3.2.tgz#35de6804dc19643e5249f3d3e3bdc6c8ce301d3f" + dependencies: + readable-stream "~1.1.9" + stream-counter "~0.2.0" + +multipipe@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/multipipe/-/multipipe-0.1.2.tgz#2a8f2ddf70eed564dff2d57f1e1a137d9f05078b" + dependencies: + duplexer2 "0.0.2" + +mute-stream@0.0.5: + version "0.0.5" + resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.5.tgz#8fbfabb0a98a253d3184331f9e8deb7372fac6c0" + +mute-stream@0.0.7, mute-stream@~0.0.4: + version "0.0.7" + resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" + +nan@^2.3.0: + version "2.8.0" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.8.0.tgz#ed715f3fe9de02b57a5e6252d90a96675e1f085a" + +natural-compare@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" + +negotiator@0.5.3: + version "0.5.3" + resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.5.3.tgz#269d5c476810ec92edbe7b6c2f28316384f9a7e8" + +negotiator@0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.1.tgz#2b327184e8992101177b28563fb5e7102acd0ca9" + +node-fetch-npm@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/node-fetch-npm/-/node-fetch-npm-2.0.2.tgz#7258c9046182dca345b4208eda918daf33697ff7" + dependencies: + encoding "^0.1.11" + json-parse-better-errors "^1.0.0" + safe-buffer "^5.1.1" + +node-fetch@^1.0.1, node-fetch@^1.3.3: + version "1.7.3" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.7.3.tgz#980f6f72d85211a5347c6b2bc18c5b84c3eb47ef" + dependencies: + encoding "^0.1.11" + is-stream "^1.0.1" + +node-gyp@~3.6.0, node-gyp@~3.6.2: + version "3.6.2" + resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-3.6.2.tgz#9bfbe54562286284838e750eac05295853fa1c60" + dependencies: + fstream "^1.0.0" + glob "^7.0.3" + graceful-fs "^4.1.2" + minimatch "^3.0.2" + mkdirp "^0.5.0" + nopt "2 || 3" + npmlog "0 || 1 || 2 || 3 || 4" + osenv "0" + request "2" + rimraf "2" + semver "~5.3.0" + tar "^2.0.0" + which "1" + +node-int64@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" + +node-notifier@^5.1.2: + version "5.2.1" + resolved "https://registry.yarnpkg.com/node-notifier/-/node-notifier-5.2.1.tgz#fa313dd08f5517db0e2502e5758d664ac69f9dea" + dependencies: + growly "^1.3.0" + semver "^5.4.1" + shellwords "^0.1.1" + which "^1.3.0" + +node-pre-gyp@^0.6.39: + version "0.6.39" + resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.6.39.tgz#c00e96860b23c0e1420ac7befc5044e1d78d8649" + dependencies: + detect-libc "^1.0.2" + hawk "3.1.3" + mkdirp "^0.5.1" + nopt "^4.0.1" + npmlog "^4.0.2" + rc "^1.1.7" + request "2.81.0" + rimraf "^2.6.1" + semver "^5.3.0" + tar "^2.2.1" + tar-pack "^3.4.0" + +node-uuid@~1.4.7: + version "1.4.8" + resolved "https://registry.yarnpkg.com/node-uuid/-/node-uuid-1.4.8.tgz#b040eb0923968afabf8d32fb1f17f1167fdab907" + +"nopt@2 || 3", nopt@~3.0.6: + version "3.0.6" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9" + dependencies: + abbrev "1" + +nopt@^4.0.1, nopt@~4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.1.tgz#d0d4685afd5415193c8c7505602d0d17cd64474d" + dependencies: + abbrev "1" + osenv "^0.1.4" + +normalize-git-url@~3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/normalize-git-url/-/normalize-git-url-3.0.2.tgz#8e5f14be0bdaedb73e07200310aa416c27350fc4" + +normalize-package-data@^2.0.0, normalize-package-data@^2.3.2, normalize-package-data@^2.4.0, "normalize-package-data@~1.0.1 || ^2.0.0", normalize-package-data@~2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.4.0.tgz#12f95a307d58352075a04907b84ac8be98ac012f" + dependencies: + hosted-git-info "^2.1.4" + is-builtin-module "^1.0.0" + semver "2 || 3 || 4 || 5" + validate-npm-package-license "^3.0.1" + +normalize-package-data@~2.3.5: + version "2.3.8" + resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.3.8.tgz#d819eda2a9dedbd1ffa563ea4071d936782295bb" + dependencies: + hosted-git-info "^2.1.4" + is-builtin-module "^1.0.0" + semver "2 || 3 || 4 || 5" + validate-npm-package-license "^3.0.1" + +normalize-path@^2.0.0, normalize-path@^2.0.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" + dependencies: + remove-trailing-separator "^1.0.1" + +npm-cache-filename@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/npm-cache-filename/-/npm-cache-filename-1.0.2.tgz#ded306c5b0bfc870a9e9faf823bc5f283e05ae11" + +npm-install-checks@~1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/npm-install-checks/-/npm-install-checks-1.0.7.tgz#6d91aeda0ac96801f1ed7aadee116a6c0a086a57" + dependencies: + npmlog "0.1 || 1 || 2" + semver "^2.3.0 || 3.x || 4 || 5" + +npm-install-checks@~3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/npm-install-checks/-/npm-install-checks-3.0.0.tgz#d4aecdfd51a53e3723b7b2f93b2ee28e307bc0d7" + dependencies: + semver "^2.3.0 || 3.x || 4 || 5" + +"npm-package-arg@^3.0.0 || ^4.0.0", npm-package-arg@^4.1.1: + version "4.2.1" + resolved "https://registry.yarnpkg.com/npm-package-arg/-/npm-package-arg-4.2.1.tgz#593303fdea85f7c422775f17f9eb7670f680e3ec" + dependencies: + hosted-git-info "^2.1.5" + semver "^5.1.0" + +"npm-package-arg@^3.0.0 || ^4.0.0 || ^5.0.0", "npm-package-arg@^4.0.0 || ^5.0.0", npm-package-arg@^5.1.2, npm-package-arg@~5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/npm-package-arg/-/npm-package-arg-5.1.2.tgz#fb18d17bb61e60900d6312619919bd753755ab37" + dependencies: + hosted-git-info "^2.4.2" + osenv "^0.1.4" + semver "^5.1.0" + validate-npm-package-name "^3.0.0" + +npm-package-arg@~4.1.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/npm-package-arg/-/npm-package-arg-4.1.1.tgz#86d9dca985b4c5e5d59772dfd5de6919998a495a" + dependencies: + hosted-git-info "^2.1.4" + semver "4 || 5" + +npm-pick-manifest@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/npm-pick-manifest/-/npm-pick-manifest-1.0.4.tgz#a5ee6510c1fe7221c0bc0414e70924c14045f7e8" + dependencies: + npm-package-arg "^5.1.2" + semver "^5.3.0" + +npm-registry-client@~7.2.1: + version "7.2.1" + resolved "https://registry.yarnpkg.com/npm-registry-client/-/npm-registry-client-7.2.1.tgz#c792266b088cc313f8525e7e35248626c723db75" + dependencies: + concat-stream "^1.5.2" + graceful-fs "^4.1.6" + normalize-package-data "~1.0.1 || ^2.0.0" + npm-package-arg "^3.0.0 || ^4.0.0" + once "^1.3.3" + request "^2.74.0" + retry "^0.10.0" + semver "2 >=2.2.1 || 3.x || 4 || 5" + slide "^1.1.3" + optionalDependencies: + npmlog "~2.0.0 || ~3.1.0" + +npm-registry-client@~8.4.0: + version "8.4.0" + resolved "https://registry.yarnpkg.com/npm-registry-client/-/npm-registry-client-8.4.0.tgz#d52b901685647fc62a4c03eafecb6ceaa5018d4c" + dependencies: + concat-stream "^1.5.2" + graceful-fs "^4.1.6" + normalize-package-data "~1.0.1 || ^2.0.0" + npm-package-arg "^3.0.0 || ^4.0.0 || ^5.0.0" + once "^1.3.3" + request "^2.74.0" + retry "^0.10.0" + semver "2 >=2.2.1 || 3.x || 4 || 5" + slide "^1.1.3" + ssri "^4.1.2" + optionalDependencies: + npmlog "2 || ^3.1.0 || ^4.0.0" + +npm-run-path@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" + dependencies: + path-key "^2.0.0" + +npm-user-validate@~0.1.5: + version "0.1.5" + resolved "https://registry.yarnpkg.com/npm-user-validate/-/npm-user-validate-0.1.5.tgz#52465d50c2d20294a57125b996baedbf56c5004b" + +npm-user-validate@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/npm-user-validate/-/npm-user-validate-1.0.0.tgz#8ceca0f5cea04d4e93519ef72d0557a75122e951" + +npm@5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/npm/-/npm-5.1.0.tgz#cf8201e044018e9c89532041c90094541982b2c0" + dependencies: + JSONStream "~1.3.1" + abbrev "~1.1.0" + ansi-regex "~3.0.0" + ansicolors "~0.3.2" + ansistyles "~0.1.3" + aproba "~1.1.2" + archy "~1.0.0" + bluebird "~3.5.0" + cacache "~9.2.9" + call-limit "~1.1.0" + chownr "~1.0.1" + cmd-shim "~2.0.2" + columnify "~1.5.4" + config-chain "~1.1.11" + detect-indent "~5.0.0" + dezalgo "~1.0.3" + editor "~1.0.0" + fs-vacuum "~1.2.10" + fs-write-stream-atomic "~1.0.10" + fstream "~1.0.11" + fstream-npm "~1.2.1" + glob "~7.1.2" + graceful-fs "~4.1.11" + has-unicode "~2.0.1" + hosted-git-info "~2.5.0" + iferr "~0.1.5" + inflight "~1.0.6" + inherits "~2.0.3" + ini "~1.3.4" + init-package-json "~1.10.1" + lazy-property "~1.0.0" + lockfile "~1.0.3" + lodash._baseuniq "~4.6.0" + lodash.clonedeep "~4.5.0" + lodash.union "~4.6.0" + lodash.uniq "~4.5.0" + lodash.without "~4.4.0" + lru-cache "~4.1.1" + mississippi "~1.3.0" + mkdirp "~0.5.1" + move-concurrently "~1.0.1" + node-gyp "~3.6.2" + nopt "~4.0.1" + normalize-package-data "~2.4.0" + npm-cache-filename "~1.0.2" + npm-install-checks "~3.0.0" + npm-package-arg "~5.1.2" + npm-registry-client "~8.4.0" + npm-user-validate "~1.0.0" + npmlog "~4.1.2" + once "~1.4.0" + opener "~1.4.3" + osenv "~0.1.4" + pacote "~2.7.38" + path-is-inside "~1.0.2" + promise-inflight "~1.0.1" + read "~1.0.7" + read-cmd-shim "~1.0.1" + read-installed "~4.0.3" + read-package-json "~2.0.9" + read-package-tree "~5.1.6" + readable-stream "~2.3.2" + request "~2.81.0" + retry "~0.10.1" + rimraf "~2.6.1" + safe-buffer "~5.1.1" + semver "~5.3.0" + sha "~2.0.1" + slide "~1.1.6" + sorted-object "~2.0.1" + sorted-union-stream "~2.1.3" + ssri "~4.1.6" + strip-ansi "~4.0.0" + tar "~2.2.1" + text-table "~0.2.0" + uid-number "0.0.6" + umask "~1.1.0" + unique-filename "~1.1.0" + unpipe "~1.0.0" + update-notifier "~2.2.0" + uuid "~3.1.0" + validate-npm-package-name "~3.0.0" + which "~1.2.14" + worker-farm "~1.3.1" + wrappy "~1.0.2" + write-file-atomic "~2.1.0" + +npm@^2.1.12: + version "2.15.12" + resolved "https://registry.yarnpkg.com/npm/-/npm-2.15.12.tgz#df7c3ed5a277c3f9d4b5d819b05311d10a200ae6" + dependencies: + abbrev "~1.0.9" + ansi "~0.3.1" + ansicolors "~0.3.2" + ansistyles "~0.1.3" + archy "~1.0.0" + async-some "~1.0.2" + block-stream "0.0.9" + char-spinner "~1.0.1" + chmodr "~1.0.2" + chownr "~1.0.1" + cmd-shim "~2.0.2" + columnify "~1.5.4" + config-chain "~1.1.10" + dezalgo "~1.0.3" + editor "~1.0.0" + fs-vacuum "~1.2.9" + fs-write-stream-atomic "~1.0.8" + fstream "~1.0.10" + fstream-npm "~1.1.1" + github-url-from-git "~1.4.0" + github-url-from-username-repo "~1.0.2" + glob "~7.0.6" + graceful-fs "~4.1.6" + hosted-git-info "~2.1.5" + inflight "~1.0.4" + inherits "~2.0.3" + ini "~1.3.4" + init-package-json "~1.9.4" + lockfile "~1.0.1" + lru-cache "~4.0.1" + minimatch "~3.0.3" + mkdirp "~0.5.1" + node-gyp "~3.6.0" + nopt "~3.0.6" + normalize-git-url "~3.0.2" + normalize-package-data "~2.3.5" + npm-cache-filename "~1.0.2" + npm-install-checks "~1.0.7" + npm-package-arg "~4.1.0" + npm-registry-client "~7.2.1" + npm-user-validate "~0.1.5" + npmlog "~2.0.4" + once "~1.4.0" + opener "~1.4.1" + osenv "~0.1.3" + path-is-inside "~1.0.0" + read "~1.0.7" + read-installed "~4.0.3" + read-package-json "~2.0.4" + readable-stream "~2.1.5" + realize-package-specifier "~3.0.1" + request "~2.74.0" + retry "~0.10.0" + rimraf "~2.5.4" + semver "~5.1.0" + sha "~2.0.1" + slide "~1.1.6" + sorted-object "~2.0.0" + spdx-license-ids "~1.2.2" + strip-ansi "~3.0.1" + tar "~2.2.1" + text-table "~0.2.0" + uid-number "0.0.6" + umask "~1.1.0" + validate-npm-package-license "~3.0.1" + validate-npm-package-name "~2.2.2" + which "~1.2.11" + wrappy "~1.0.2" + write-file-atomic "~1.1.4" + +npmi@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/npmi/-/npmi-1.0.1.tgz#15d769273547545e6809dcf0ce18aed48b0290e2" + dependencies: + npm "^2.1.12" + semver "^4.1.0" + +"npmlog@0 || 1 || 2 || 3 || 4", "npmlog@2 || ^3.1.0 || ^4.0.0", npmlog@^4.0.2, npmlog@~4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" + dependencies: + are-we-there-yet "~1.1.2" + console-control-strings "~1.1.0" + gauge "~2.7.3" + set-blocking "~2.0.0" + +"npmlog@0.1 || 1 || 2", npmlog@^2.0.4, npmlog@~2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-2.0.4.tgz#98b52530f2514ca90d09ec5b22c8846722375692" + dependencies: + ansi "~0.3.1" + are-we-there-yet "~1.1.2" + gauge "~1.2.5" + +"npmlog@~2.0.0 || ~3.1.0": + version "3.1.2" + resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-3.1.2.tgz#2d46fa874337af9498a2f12bb43d8d0be4a36873" + dependencies: + are-we-there-yet "~1.1.2" + console-control-strings "~1.1.0" + gauge "~2.6.0" + set-blocking "~2.0.0" + +number-is-nan@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" + +oauth-sign@~0.8.1, oauth-sign@~0.8.2: + version "0.8.2" + resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.8.2.tgz#46a6ab7f0aead8deae9ec0565780b7d4efeb9d43" + +object-assign@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-3.0.0.tgz#9bedd5ca0897949bca47e7ff408062d549f587f2" + +object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + +object-keys@^1.0.11, object-keys@^1.0.8: + version "1.0.11" + resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.0.11.tgz#c54601778ad560f1142ce0e01bcca8b56d13426d" + +object.assign@^4.0.4: + version "4.1.0" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.0.tgz#968bf1100d7956bb3ca086f006f846b3bc4008da" + dependencies: + define-properties "^1.1.2" + function-bind "^1.1.1" + has-symbols "^1.0.0" + object-keys "^1.0.11" + +object.omit@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/object.omit/-/object.omit-2.0.1.tgz#1a9c744829f39dbb858c76ca3579ae2a54ebd1fa" + dependencies: + for-own "^0.1.4" + is-extendable "^0.1.1" + +on-finished@~2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" + dependencies: + ee-first "1.1.1" + +on-headers@~1.0.0, on-headers@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.1.tgz#928f5d0f470d49342651ea6794b0857c100693f7" + +once@^1.3.0, once@^1.3.1, once@^1.3.3, once@^1.4.0, once@~1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + dependencies: + wrappy "1" + +onetime@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-1.1.0.tgz#a1f7838f8314c516f05ecefcbc4ccfe04b4ed789" + +onetime@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4" + dependencies: + mimic-fn "^1.0.0" + +opener@~1.4.1, opener@~1.4.3: + version "1.4.3" + resolved "https://registry.yarnpkg.com/opener/-/opener-1.4.3.tgz#5c6da2c5d7e5831e8ffa3964950f8d6674ac90b8" + +opn@^3.0.2: + version "3.0.3" + resolved "https://registry.yarnpkg.com/opn/-/opn-3.0.3.tgz#b6d99e7399f78d65c3baaffef1fb288e9b85243a" + dependencies: + object-assign "^4.0.1" + +optimist@0.6.1, optimist@^0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686" + dependencies: + minimist "~0.0.1" + wordwrap "~0.0.2" + +optionator@^0.8.2: + version "0.8.2" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.2.tgz#364c5e409d3f4d6301d6c0b4c05bba50180aeb64" + dependencies: + deep-is "~0.1.3" + fast-levenshtein "~2.0.4" + levn "~0.3.0" + prelude-ls "~1.1.2" + type-check "~0.3.2" + wordwrap "~1.0.0" + +options@>=0.0.5: + version "0.0.6" + resolved "https://registry.yarnpkg.com/options/-/options-0.0.6.tgz#ec22d312806bb53e731773e7cdaefcf1c643128f" + +os-homedir@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" + +os-locale@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-2.1.0.tgz#42bc2900a6b5b8bd17376c8e882b65afccf24bf2" + dependencies: + execa "^0.7.0" + lcid "^1.0.0" + mem "^1.1.0" + +os-name@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/os-name/-/os-name-2.0.1.tgz#b9a386361c17ae3a21736ef0599405c9a8c5dc5e" + dependencies: + macos-release "^1.0.0" + win-release "^1.0.0" + +os-tmpdir@^1.0.0, os-tmpdir@^1.0.1, os-tmpdir@~1.0.1, os-tmpdir@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" + +osenv@0, osenv@^0.1.4, osenv@~0.1.3, osenv@~0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.4.tgz#42fe6d5953df06c8064be6f176c3d05aaaa34644" + dependencies: + os-homedir "^1.0.0" + os-tmpdir "^1.0.0" + +p-finally@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" + +p-limit@^1.1.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.2.0.tgz#0e92b6bedcb59f022c13d0f1949dc82d15909f1c" + dependencies: + p-try "^1.0.0" + +p-locate@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" + dependencies: + p-limit "^1.1.0" + +p-try@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" + +package-json@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/package-json/-/package-json-4.0.1.tgz#8869a0401253661c4c4ca3da6c2121ed555f5eed" + dependencies: + got "^6.7.1" + registry-auth-token "^3.0.1" + registry-url "^3.0.3" + semver "^5.1.0" + +pacote@~2.7.38: + version "2.7.38" + resolved "https://registry.yarnpkg.com/pacote/-/pacote-2.7.38.tgz#5091f8774298c26c3eca24606037f1bb73db74c1" + dependencies: + bluebird "^3.5.0" + cacache "^9.2.9" + glob "^7.1.2" + lru-cache "^4.1.1" + make-fetch-happen "^2.4.13" + minimatch "^3.0.4" + mississippi "^1.2.0" + normalize-package-data "^2.4.0" + npm-package-arg "^5.1.2" + npm-pick-manifest "^1.0.4" + osenv "^0.1.4" + promise-inflight "^1.0.1" + promise-retry "^1.1.1" + protoduck "^4.0.0" + safe-buffer "^5.1.1" + semver "^5.3.0" + ssri "^4.1.6" + tar-fs "^1.15.3" + tar-stream "^1.5.4" + unique-filename "^1.1.0" + which "^1.2.12" + +parallel-transform@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/parallel-transform/-/parallel-transform-1.1.0.tgz#d410f065b05da23081fcd10f28854c29bda33b06" + dependencies: + cyclist "~0.2.2" + inherits "^2.0.3" + readable-stream "^2.1.5" + +parse-glob@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/parse-glob/-/parse-glob-3.0.4.tgz#b2c376cfb11f35513badd173ef0bb6e3a388391c" + dependencies: + glob-base "^0.3.0" + is-dotfile "^1.0.0" + is-extglob "^1.0.0" + is-glob "^2.0.0" + +parse-json@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" + dependencies: + error-ex "^1.2.0" + +parseurl@~1.3.0, parseurl@~1.3.1, parseurl@~1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.2.tgz#fc289d4ed8993119460c156253262cdc8de65bf3" + +path-exists@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b" + dependencies: + pinkie-promise "^2.0.0" + +path-exists@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" + +path-is-absolute@^1.0.0, path-is-absolute@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + +path-is-inside@^1.0.1, path-is-inside@~1.0.0, path-is-inside@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" + +path-key@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" + +path-parse@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.5.tgz#3c1adf871ea9cd6c9431b6ea2bd74a0ff055c4c1" + +path-type@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-2.0.0.tgz#f012ccb8415b7096fc2daa1054c3d72389594c73" + dependencies: + pify "^2.0.0" + +pause@0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/pause/-/pause-0.1.0.tgz#ebc8a4a8619ff0b8a81ac1513c3434ff469fdb74" + +pegjs@^0.10.0: + version "0.10.0" + resolved "https://registry.yarnpkg.com/pegjs/-/pegjs-0.10.0.tgz#cf8bafae6eddff4b5a7efb185269eaaf4610ddbd" + +performance-now@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-0.2.0.tgz#33ef30c5c77d4ea21c5a53869d91b56d8f2555e5" + +performance-now@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" + +pify@^2.0.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" + +pify@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176" + +pinkie-promise@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" + dependencies: + pinkie "^2.0.0" + +pinkie@^2.0.0: + version "2.0.4" + resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" + +pkg-dir@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-1.0.0.tgz#7a4b508a8d5bb2d629d447056ff4e9c9314cf3d4" + dependencies: + find-up "^1.0.0" + +pkg-up@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/pkg-up/-/pkg-up-1.0.0.tgz#3e08fb461525c4421624a33b9f7e6d0af5b05a26" + dependencies: + find-up "^1.0.0" + +plist@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/plist/-/plist-2.0.1.tgz#0a32ca9481b1c364e92e18dc55c876de9d01da8b" + dependencies: + base64-js "1.1.2" + xmlbuilder "8.2.2" + xmldom "0.1.x" + +plist@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/plist/-/plist-1.2.0.tgz#084b5093ddc92506e259f874b8d9b1afb8c79593" + dependencies: + base64-js "0.0.8" + util-deprecate "1.0.2" + xmlbuilder "4.0.0" + xmldom "0.1.x" + +pluralize@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-1.2.1.tgz#d1a21483fd22bb41e58a12fa3421823140897c45" + +prelude-ls@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" + +prepend-http@^1.0.1: + version "1.0.4" + resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc" + +preserve@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b" + +pretty-format@^4.2.1: + version "4.3.1" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-4.3.1.tgz#530be5c42b3c05b36414a7a2a4337aa80acd0e8d" + +private@^0.1.6, private@^0.1.7: + version "0.1.8" + resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff" + +process-nextick-args@~1.0.6: + version "1.0.7" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3" + +process@~0.5.1: + version "0.5.2" + resolved "https://registry.yarnpkg.com/process/-/process-0.5.2.tgz#1638d8a8e34c2f440a91db95ab9aeb677fc185cf" + +progress@^1.1.8: + version "1.1.8" + resolved "https://registry.yarnpkg.com/progress/-/progress-1.1.8.tgz#e260c78f6161cdd9b0e56cc3e0a85de17c7a57be" + +promise-inflight@^1.0.1, promise-inflight@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3" + +promise-retry@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/promise-retry/-/promise-retry-1.1.1.tgz#6739e968e3051da20ce6497fb2b50f6911df3d6d" + dependencies: + err-code "^1.0.0" + retry "^0.10.0" + +promise@^7.1.1: + version "7.3.1" + resolved "https://registry.yarnpkg.com/promise/-/promise-7.3.1.tgz#064b72602b18f90f29192b8b1bc418ffd1ebd3bf" + dependencies: + asap "~2.0.3" + +promzard@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/promzard/-/promzard-0.3.0.tgz#26a5d6ee8c7dee4cb12208305acfb93ba382a9ee" + dependencies: + read "1" + +prop-types@^15.5.10, prop-types@^15.5.8, prop-types@^15.6.0: + version "15.6.0" + resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.6.0.tgz#ceaf083022fc46b4a35f69e13ef75aed0d639856" + dependencies: + fbjs "^0.8.16" + loose-envify "^1.3.1" + object-assign "^4.1.1" + +proto-list@~1.2.1: + version "1.2.4" + resolved "https://registry.yarnpkg.com/proto-list/-/proto-list-1.2.4.tgz#212d5bfe1318306a420f6402b8e26ff39647a849" + +protoduck@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/protoduck/-/protoduck-4.0.0.tgz#fe4874d8c7913366cfd9ead12453a22cd3657f8e" + dependencies: + genfun "^4.0.1" + +prr@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476" + +pseudomap@^1.0.1, pseudomap@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" + +pump@^1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/pump/-/pump-1.0.3.tgz#5dfe8311c33bbf6fc18261f9f34702c47c08a954" + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" + +pump@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/pump/-/pump-2.0.1.tgz#12399add6e4cf7526d973cbc8b5ce2e2908b3909" + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" + +pumpify@^1.3.3: + version "1.4.0" + resolved "https://registry.yarnpkg.com/pumpify/-/pumpify-1.4.0.tgz#80b7c5df7e24153d03f0e7ac8a05a5d068bd07fb" + dependencies: + duplexify "^3.5.3" + inherits "^2.0.3" + pump "^2.0.0" + +punycode@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" + +q@1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/q/-/q-1.5.0.tgz#dd01bac9d06d30e6f219aecb8253ee9ebdc308f1" + +qs@4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/qs/-/qs-4.0.0.tgz#c31d9b74ec27df75e543a86c78728ed8d4623607" + +qs@~6.2.0: + version "6.2.3" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.2.3.tgz#1cfcb25c10a9b2b483053ff39f5dfc9233908cfe" + +qs@~6.4.0: + version "6.4.0" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.4.0.tgz#13e26d28ad6b0ffaa91312cd3bf708ed351e7233" + +qs@~6.5.1: + version "6.5.1" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.1.tgz#349cdf6eef89ec45c12d7d5eb3fc0c870343a6d8" + +random-bytes@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/random-bytes/-/random-bytes-1.0.0.tgz#4f68a1dc0ae58bd3fb95848c30324db75d64360b" + +randomatic@^1.1.3: + version "1.1.7" + resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-1.1.7.tgz#c7abe9cc8b87c0baa876b19fde83fd464797e38c" + dependencies: + is-number "^3.0.0" + kind-of "^4.0.0" + +range-parser@~1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.0.3.tgz#6872823535c692e2c2a0103826afd82c2e0ff175" + +raw-body@~2.1.2: + version "2.1.7" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.1.7.tgz#adfeace2e4fb3098058014d08c072dcc59758774" + dependencies: + bytes "2.4.0" + iconv-lite "0.4.13" + unpipe "1.0.0" + +rc@^1.0.1, rc@^1.1.6, rc@^1.1.7: + version "1.2.4" + resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.4.tgz#a0f606caae2a3b862bbd0ef85482c0125b315fa3" + dependencies: + deep-extend "~0.4.0" + ini "~1.3.0" + minimist "^1.2.0" + strip-json-comments "~2.0.1" + +react-clone-referenced-element@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/react-clone-referenced-element/-/react-clone-referenced-element-1.0.1.tgz#2bba8c69404c5e4a944398600bcc4c941f860682" + +react-deep-force-update@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/react-deep-force-update/-/react-deep-force-update-1.1.1.tgz#bcd31478027b64b3339f108921ab520b4313dc2c" + +react-devtools-core@^2.5.0: + version "2.5.2" + resolved "https://registry.yarnpkg.com/react-devtools-core/-/react-devtools-core-2.5.2.tgz#f97bec5afae5d9318d16778065e0c214c4d5714c" + dependencies: + shell-quote "^1.6.1" + ws "^2.0.3" + +react-native@0.51.0: + version "0.51.0" + resolved "https://registry.yarnpkg.com/react-native/-/react-native-0.51.0.tgz#fe25934b3030fd323f3ca1a70f034133465955ed" + dependencies: + absolute-path "^0.0.0" + art "^0.10.0" + babel-core "^6.24.1" + babel-plugin-syntax-trailing-function-commas "^6.20.0" + babel-plugin-transform-async-to-generator "6.16.0" + babel-plugin-transform-class-properties "^6.18.0" + babel-plugin-transform-exponentiation-operator "^6.5.0" + babel-plugin-transform-flow-strip-types "^6.21.0" + babel-plugin-transform-object-rest-spread "^6.20.2" + babel-register "^6.24.1" + babel-runtime "^6.23.0" + base64-js "^1.1.2" + chalk "^1.1.1" + commander "^2.9.0" + connect "^2.8.3" + create-react-class "^15.5.2" + debug "^2.2.0" + denodeify "^1.2.1" + envinfo "^3.0.0" + event-target-shim "^1.0.5" + fbjs "^0.8.14" + fbjs-scripts "^0.8.1" + fs-extra "^1.0.0" + glob "^7.1.1" + graceful-fs "^4.1.3" + inquirer "^3.0.6" + lodash "^4.16.6" + metro-bundler "^0.20.0" + mime "^1.3.4" + minimist "^1.2.0" + mkdirp "^0.5.1" + node-fetch "^1.3.3" + node-notifier "^5.1.2" + npmlog "^2.0.4" + opn "^3.0.2" + optimist "^0.6.1" + plist "^1.2.0" + pretty-format "^4.2.1" + promise "^7.1.1" + prop-types "^15.5.8" + react-clone-referenced-element "^1.0.1" + react-devtools-core "^2.5.0" + react-timer-mixin "^0.13.2" + regenerator-runtime "^0.11.0" + rimraf "^2.5.4" + semver "^5.0.3" + shell-quote "1.6.1" + stacktrace-parser "^0.1.3" + whatwg-fetch "^1.0.0" + ws "^1.1.0" + xcode "^0.9.1" + xmldoc "^0.4.0" + yargs "^9.0.0" + +react-proxy@^1.1.7: + version "1.1.8" + resolved "https://registry.yarnpkg.com/react-proxy/-/react-proxy-1.1.8.tgz#9dbfd9d927528c3aa9f444e4558c37830ab8c26a" + dependencies: + lodash "^4.6.1" + react-deep-force-update "^1.0.0" + +react-timer-mixin@^0.13.2: + version "0.13.3" + resolved "https://registry.yarnpkg.com/react-timer-mixin/-/react-timer-mixin-0.13.3.tgz#0da8b9f807ec07dc3e854d082c737c65605b3d22" + +react-transform-hmr@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/react-transform-hmr/-/react-transform-hmr-1.0.4.tgz#e1a40bd0aaefc72e8dfd7a7cda09af85066397bb" + dependencies: + global "^4.3.0" + react-proxy "^1.1.7" + +react@16.0.0: + version "16.0.0" + resolved "https://registry.yarnpkg.com/react/-/react-16.0.0.tgz#ce7df8f1941b036f02b2cca9dbd0cb1f0e855e2d" + dependencies: + fbjs "^0.8.16" + loose-envify "^1.1.0" + object-assign "^4.1.1" + prop-types "^15.6.0" + +read-cmd-shim@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/read-cmd-shim/-/read-cmd-shim-1.0.1.tgz#2d5d157786a37c055d22077c32c53f8329e91c7b" + dependencies: + graceful-fs "^4.1.2" + +read-installed@~4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/read-installed/-/read-installed-4.0.3.tgz#ff9b8b67f187d1e4c29b9feb31f6b223acd19067" + dependencies: + debuglog "^1.0.1" + read-package-json "^2.0.0" + readdir-scoped-modules "^1.0.0" + semver "2 || 3 || 4 || 5" + slide "~1.1.3" + util-extend "^1.0.1" + optionalDependencies: + graceful-fs "^4.1.2" + +"read-package-json@1 || 2", read-package-json@^2.0.0, read-package-json@~2.0.4, read-package-json@~2.0.9: + version "2.0.12" + resolved "https://registry.yarnpkg.com/read-package-json/-/read-package-json-2.0.12.tgz#68ea45f98b3741cb6e10ae3bbd42a605026a6951" + dependencies: + glob "^7.1.1" + json-parse-better-errors "^1.0.0" + normalize-package-data "^2.0.0" + slash "^1.0.0" + optionalDependencies: + graceful-fs "^4.1.2" + +read-package-tree@~5.1.6: + version "5.1.6" + resolved "https://registry.yarnpkg.com/read-package-tree/-/read-package-tree-5.1.6.tgz#4f03e83d0486856fb60d97c94882841c2a7b1b7a" + dependencies: + debuglog "^1.0.1" + dezalgo "^1.0.0" + once "^1.3.0" + read-package-json "^2.0.0" + readdir-scoped-modules "^1.0.0" + +read-pkg-up@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-2.0.0.tgz#6b72a8048984e0c41e79510fd5e9fa99b3b549be" + dependencies: + find-up "^2.0.0" + read-pkg "^2.0.0" + +read-pkg@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-2.0.0.tgz#8ef1c0623c6a6db0dc6713c4bfac46332b2368f8" + dependencies: + load-json-file "^2.0.0" + normalize-package-data "^2.3.2" + path-type "^2.0.0" + +read@1, read@~1.0.1, read@~1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/read/-/read-1.0.7.tgz#b3da19bd052431a97671d44a42634adf710b40c4" + dependencies: + mute-stream "~0.0.4" + +"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.4, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.1.4, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@~2.3.2: + version "2.3.3" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.3.tgz#368f2512d79f9d46fdfc71349ae7878bbc1eb95c" + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~1.0.6" + safe-buffer "~5.1.1" + string_decoder "~1.0.3" + util-deprecate "~1.0.1" + +readable-stream@~1.1.10, readable-stream@~1.1.8, readable-stream@~1.1.9: + version "1.1.14" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9" + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.1" + isarray "0.0.1" + string_decoder "~0.10.x" + +readable-stream@~2.0.5: + version "2.0.6" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.0.6.tgz#8f90341e68a53ccc928788dacfcd11b36eb9b78e" + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.1" + isarray "~1.0.0" + process-nextick-args "~1.0.6" + string_decoder "~0.10.x" + util-deprecate "~1.0.1" + +readable-stream@~2.1.5: + version "2.1.5" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.1.5.tgz#66fa8b720e1438b364681f2ad1a63c618448c9d0" + dependencies: + buffer-shims "^1.0.0" + core-util-is "~1.0.0" + inherits "~2.0.1" + isarray "~1.0.0" + process-nextick-args "~1.0.6" + string_decoder "~0.10.x" + util-deprecate "~1.0.1" + +readdir-scoped-modules@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/readdir-scoped-modules/-/readdir-scoped-modules-1.0.2.tgz#9fafa37d286be5d92cbaebdee030dc9b5f406747" + dependencies: + debuglog "^1.0.1" + dezalgo "^1.0.0" + graceful-fs "^4.1.2" + once "^1.3.0" + +readline2@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/readline2/-/readline2-1.0.1.tgz#41059608ffc154757b715d9989d199ffbf372e35" + dependencies: + code-point-at "^1.0.0" + is-fullwidth-code-point "^1.0.0" + mute-stream "0.0.5" + +realize-package-specifier@~3.0.1: + version "3.0.3" + resolved "https://registry.yarnpkg.com/realize-package-specifier/-/realize-package-specifier-3.0.3.tgz#d0def882952b8de3f67eba5e91199661271f41f4" + dependencies: + dezalgo "^1.0.1" + npm-package-arg "^4.1.1" + +rechoir@^0.6.2: + version "0.6.2" + resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384" + dependencies: + resolve "^1.1.6" + +regenerate@^1.2.1: + version "1.3.3" + resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.3.3.tgz#0c336d3980553d755c39b586ae3b20aa49c82b7f" + +regenerator-runtime@^0.11.0: + version "0.11.1" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" + +regenerator-transform@^0.10.0: + version "0.10.1" + resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.10.1.tgz#1e4996837231da8b7f3cf4114d71b5691a0680dd" + dependencies: + babel-runtime "^6.18.0" + babel-types "^6.19.0" + private "^0.1.6" + +regex-cache@^0.4.2: + version "0.4.4" + resolved "https://registry.yarnpkg.com/regex-cache/-/regex-cache-0.4.4.tgz#75bdc58a2a1496cec48a12835bc54c8d562336dd" + dependencies: + is-equal-shallow "^0.1.3" + +regexpu-core@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-2.0.0.tgz#49d038837b8dcf8bfa5b9a42139938e6ea2ae240" + dependencies: + regenerate "^1.2.1" + regjsgen "^0.2.0" + regjsparser "^0.1.4" + +registry-auth-token@^3.0.1: + version "3.3.1" + resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-3.3.1.tgz#fb0d3289ee0d9ada2cbb52af5dfe66cb070d3006" + dependencies: + rc "^1.1.6" + safe-buffer "^5.0.1" + +registry-url@^3.0.3: + version "3.1.0" + resolved "https://registry.yarnpkg.com/registry-url/-/registry-url-3.1.0.tgz#3d4ef870f73dde1d77f0cf9a381432444e174942" + dependencies: + rc "^1.0.1" + +regjsgen@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.2.0.tgz#6c016adeac554f75823fe37ac05b92d5a4edb1f7" + +regjsparser@^0.1.4: + version "0.1.5" + resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.1.5.tgz#7ee8f84dc6fa792d3fd0ae228d24bd949ead205c" + dependencies: + jsesc "~0.5.0" + +remove-trailing-separator@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" + +repeat-element@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.2.tgz#ef089a178d1483baae4d93eb98b4f9e4e11d990a" + +repeat-string@^1.5.2: + version "1.6.1" + resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" + +repeating@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda" + dependencies: + is-finite "^1.0.0" + +replace-ext@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-0.0.1.tgz#29bbd92078a739f0bcce2b4ee41e837953522924" + +request@2, request@^2.74.0, request@^2.79.0: + version "2.83.0" + resolved "https://registry.yarnpkg.com/request/-/request-2.83.0.tgz#ca0b65da02ed62935887808e6f510381034e3356" + dependencies: + aws-sign2 "~0.7.0" + aws4 "^1.6.0" + caseless "~0.12.0" + combined-stream "~1.0.5" + extend "~3.0.1" + forever-agent "~0.6.1" + form-data "~2.3.1" + har-validator "~5.0.3" + hawk "~6.0.2" + http-signature "~1.2.0" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" + mime-types "~2.1.17" + oauth-sign "~0.8.2" + performance-now "^2.1.0" + qs "~6.5.1" + safe-buffer "^5.1.1" + stringstream "~0.0.5" + tough-cookie "~2.3.3" + tunnel-agent "^0.6.0" + uuid "^3.1.0" + +request@2.81.0, request@~2.81.0: + version "2.81.0" + resolved "https://registry.yarnpkg.com/request/-/request-2.81.0.tgz#c6928946a0e06c5f8d6f8a9333469ffda46298a0" + dependencies: + aws-sign2 "~0.6.0" + aws4 "^1.2.1" + caseless "~0.12.0" + combined-stream "~1.0.5" + extend "~3.0.0" + forever-agent "~0.6.1" + form-data "~2.1.1" + har-validator "~4.2.1" + hawk "~3.1.3" + http-signature "~1.1.0" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" + mime-types "~2.1.7" + oauth-sign "~0.8.1" + performance-now "^0.2.0" + qs "~6.4.0" + safe-buffer "^5.0.1" + stringstream "~0.0.4" + tough-cookie "~2.3.0" + tunnel-agent "^0.6.0" + uuid "^3.0.0" + +request@~2.74.0: + version "2.74.0" + resolved "https://registry.yarnpkg.com/request/-/request-2.74.0.tgz#7693ca768bbb0ea5c8ce08c084a45efa05b892ab" + dependencies: + aws-sign2 "~0.6.0" + aws4 "^1.2.1" + bl "~1.1.2" + caseless "~0.11.0" + combined-stream "~1.0.5" + extend "~3.0.0" + forever-agent "~0.6.1" + form-data "~1.0.0-rc4" + har-validator "~2.0.6" + hawk "~3.1.3" + http-signature "~1.1.0" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" + mime-types "~2.1.7" + node-uuid "~1.4.7" + oauth-sign "~0.8.1" + qs "~6.2.0" + stringstream "~0.0.4" + tough-cookie "~2.3.0" + tunnel-agent "~0.4.1" + +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + +require-main-filename@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1" + +require-uncached@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/require-uncached/-/require-uncached-1.0.3.tgz#4e0d56d6c9662fd31e43011c4b95aa49955421d3" + dependencies: + caller-path "^0.1.0" + resolve-from "^1.0.0" + +resolve-from@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-1.0.1.tgz#26cbfe935d1aeeeabb29bc3fe5aeb01e93d44226" + +resolve@^1.1.6, resolve@^1.2.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.5.0.tgz#1f09acce796c9a762579f31b2c1cc4c3cddf9f36" + dependencies: + path-parse "^1.0.5" + +response-time@~2.3.1: + version "2.3.2" + resolved "https://registry.yarnpkg.com/response-time/-/response-time-2.3.2.tgz#ffa71bab952d62f7c1d49b7434355fbc68dffc5a" + dependencies: + depd "~1.1.0" + on-headers "~1.0.1" + +restore-cursor@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-1.0.1.tgz#34661f46886327fed2991479152252df92daa541" + dependencies: + exit-hook "^1.0.0" + onetime "^1.0.0" + +restore-cursor@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf" + dependencies: + onetime "^2.0.0" + signal-exit "^3.0.2" + +retry@^0.10.0, retry@~0.10.0, retry@~0.10.1: + version "0.10.1" + resolved "https://registry.yarnpkg.com/retry/-/retry-0.10.1.tgz#e76388d217992c252750241d3d3956fed98d8ff4" + +rimraf@2, rimraf@^2.2.8, rimraf@^2.5.1, rimraf@^2.5.2, rimraf@^2.5.4, rimraf@^2.6.1, rimraf@~2.6.1: + version "2.6.2" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.2.tgz#2ed8150d24a16ea8651e6d6ef0f47c4158ce7a36" + dependencies: + glob "^7.0.5" + +rimraf@~2.2.6: + version "2.2.8" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.2.8.tgz#e439be2aaee327321952730f99a8929e4fc50582" + +rimraf@~2.5.4: + version "2.5.4" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.5.4.tgz#96800093cbf1a0c86bd95b4625467535c29dfa04" + dependencies: + glob "^7.0.5" + +rndm@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/rndm/-/rndm-1.2.0.tgz#f33fe9cfb52bbfd520aa18323bc65db110a1b76c" + +run-async@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/run-async/-/run-async-0.1.0.tgz#c8ad4a5e110661e402a7d21b530e009f25f8e389" + dependencies: + once "^1.3.0" + +run-async@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.3.0.tgz#0371ab4ae0bdd720d4166d7dfda64ff7a445a6c0" + dependencies: + is-promise "^2.1.0" + +run-queue@^1.0.0, run-queue@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/run-queue/-/run-queue-1.0.3.tgz#e848396f057d223f24386924618e25694161ec47" + dependencies: + aproba "^1.1.1" + +rx-lite-aggregates@^4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz#753b87a89a11c95467c4ac1626c4efc4e05c67be" + dependencies: + rx-lite "*" + +rx-lite@*, rx-lite@^4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-4.0.8.tgz#0b1e11af8bc44836f04a6407e92da42467b79444" + +rx-lite@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-3.1.2.tgz#19ce502ca572665f3b647b10939f97fd1615f102" + +safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@~5.1.0, safe-buffer@~5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853" + +safe-buffer@~5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.0.1.tgz#d263ca54696cd8a306b5ca6551e92de57918fbe7" + +sane@^2.0.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/sane/-/sane-2.3.0.tgz#3f3df584abf69e63d4bb74f0f8c42468e4d7d46b" + dependencies: + anymatch "^1.3.0" + exec-sh "^0.2.0" + fb-watchman "^2.0.0" + minimatch "^3.0.2" + minimist "^1.1.1" + walker "~1.0.5" + watch "~0.18.0" + optionalDependencies: + fsevents "^1.1.1" + +sax@~1.1.1: + version "1.1.6" + resolved "https://registry.yarnpkg.com/sax/-/sax-1.1.6.tgz#5d616be8a5e607d54e114afae55b7eaf2fcc3240" + +semver-diff@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/semver-diff/-/semver-diff-2.1.0.tgz#4bbb8437c8d37e4b0cf1a68fd726ec6d645d6d36" + dependencies: + semver "^5.0.3" + +"semver@2 >=2.2.1 || 3.x || 4 || 5", "semver@2 || 3 || 4 || 5", "semver@2.x || 3.x || 4 || 5", "semver@4 || 5", semver@5.x, "semver@^2.3.0 || 3.x || 4 || 5", semver@^5.0.1, semver@^5.0.3, semver@^5.1.0, semver@^5.3.0, semver@^5.4.1: + version "5.5.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab" + +semver@5.3.0, semver@~5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f" + +semver@^4.1.0: + version "4.3.6" + resolved "https://registry.yarnpkg.com/semver/-/semver-4.3.6.tgz#300bc6e0e86374f7ba61068b5b1ecd57fc6532da" + +semver@~5.1.0: + version "5.1.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.1.1.tgz#a3292a373e6f3e0798da0b20641b9a9c5bc47e19" + +send@0.13.2: + version "0.13.2" + resolved "https://registry.yarnpkg.com/send/-/send-0.13.2.tgz#765e7607c8055452bba6f0b052595350986036de" + dependencies: + debug "~2.2.0" + depd "~1.1.0" + destroy "~1.0.4" + escape-html "~1.0.3" + etag "~1.7.0" + fresh "0.3.0" + http-errors "~1.3.1" + mime "1.3.4" + ms "0.7.1" + on-finished "~2.3.0" + range-parser "~1.0.3" + statuses "~1.2.1" + +serve-favicon@~2.3.0: + version "2.3.2" + resolved "https://registry.yarnpkg.com/serve-favicon/-/serve-favicon-2.3.2.tgz#dd419e268de012ab72b319d337f2105013f9381f" + dependencies: + etag "~1.7.0" + fresh "0.3.0" + ms "0.7.2" + parseurl "~1.3.1" + +serve-index@~1.7.2: + version "1.7.3" + resolved "https://registry.yarnpkg.com/serve-index/-/serve-index-1.7.3.tgz#7a057fc6ee28dc63f64566e5fa57b111a86aecd2" + dependencies: + accepts "~1.2.13" + batch "0.5.3" + debug "~2.2.0" + escape-html "~1.0.3" + http-errors "~1.3.1" + mime-types "~2.1.9" + parseurl "~1.3.1" + +serve-static@~1.10.0: + version "1.10.3" + resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.10.3.tgz#ce5a6ecd3101fed5ec09827dac22a9c29bfb0535" + dependencies: + escape-html "~1.0.3" + parseurl "~1.3.1" + send "0.13.2" + +set-blocking@^2.0.0, set-blocking@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" + +setimmediate@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" + +sha@~2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/sha/-/sha-2.0.1.tgz#6030822fbd2c9823949f8f72ed6411ee5cf25aae" + dependencies: + graceful-fs "^4.1.2" + readable-stream "^2.0.2" + +shebang-command@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" + dependencies: + shebang-regex "^1.0.0" + +shebang-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" + +shell-quote@1.6.1, shell-quote@^1.6.1: + version "1.6.1" + resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.6.1.tgz#f4781949cce402697127430ea3b3c5476f481767" + dependencies: + array-filter "~0.0.0" + array-map "~0.0.0" + array-reduce "~0.0.0" + jsonify "~0.0.0" + +shelljs@^0.7.5: + version "0.7.8" + resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.7.8.tgz#decbcf874b0d1e5fb72e14b164a9683048e9acb3" + dependencies: + glob "^7.0.0" + interpret "^1.0.0" + rechoir "^0.6.2" + +shellwords@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/shellwords/-/shellwords-0.1.1.tgz#d6b9181c1a48d397324c84871efbcfc73fc0654b" + +signal-exit@^3.0.0, signal-exit@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" + +simple-plist@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/simple-plist/-/simple-plist-0.2.1.tgz#71766db352326928cf3a807242ba762322636723" + dependencies: + bplist-creator "0.0.7" + bplist-parser "0.1.1" + plist "2.0.1" + +slash@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55" + +slice-ansi@0.0.4: + version "0.0.4" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-0.0.4.tgz#edbf8903f66f7ce2f8eafd6ceed65e264c831b35" + +slide@^1.1.3, slide@^1.1.5, slide@~1.1.3, slide@~1.1.6: + version "1.1.6" + resolved "https://registry.yarnpkg.com/slide/-/slide-1.1.6.tgz#56eb027d65b4d2dce6cb2e2d32c4d4afc9e1d707" + +smart-buffer@^1.0.13: + version "1.1.15" + resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-1.1.15.tgz#7f114b5b65fab3e2a35aa775bb12f0d1c649bf16" + +sntp@1.x.x: + version "1.0.9" + resolved "https://registry.yarnpkg.com/sntp/-/sntp-1.0.9.tgz#6541184cc90aeea6c6e7b35e2659082443c66198" + dependencies: + hoek "2.x.x" + +sntp@2.x.x: + version "2.1.0" + resolved "https://registry.yarnpkg.com/sntp/-/sntp-2.1.0.tgz#2c6cec14fedc2222739caf9b5c3d85d1cc5a2cc8" + dependencies: + hoek "4.x.x" + +socks-proxy-agent@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-3.0.1.tgz#2eae7cf8e2a82d34565761539a7f9718c5617659" + dependencies: + agent-base "^4.1.0" + socks "^1.1.10" + +socks@^1.1.10: + version "1.1.10" + resolved "https://registry.yarnpkg.com/socks/-/socks-1.1.10.tgz#5b8b7fc7c8f341c53ed056e929b7bf4de8ba7b5a" + dependencies: + ip "^1.1.4" + smart-buffer "^1.0.13" + +sorted-object@~2.0.0, sorted-object@~2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/sorted-object/-/sorted-object-2.0.1.tgz#7d631f4bd3a798a24af1dffcfbfe83337a5df5fc" + +sorted-union-stream@~2.1.3: + version "2.1.3" + resolved "https://registry.yarnpkg.com/sorted-union-stream/-/sorted-union-stream-2.1.3.tgz#c7794c7e077880052ff71a8d4a2dbb4a9a638ac7" + dependencies: + from2 "^1.3.0" + stream-iterate "^1.1.0" + +source-map-support@^0.4.15: + version "0.4.18" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.18.tgz#0286a6de8be42641338594e97ccea75f0a2c585f" + dependencies: + source-map "^0.5.6" + +source-map@^0.5.6: + version "0.5.7" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" + +source-map@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + +sparkles@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/sparkles/-/sparkles-1.0.0.tgz#1acbbfb592436d10bbe8f785b7cc6f82815012c3" + +spdx-correct@~1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-1.0.2.tgz#4b3073d933ff51f3912f03ac5519498a4150db40" + dependencies: + spdx-license-ids "^1.0.2" + +spdx-expression-parse@~1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-1.0.4.tgz#9bdf2f20e1f40ed447fbe273266191fced51626c" + +spdx-license-ids@^1.0.2, spdx-license-ids@~1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz#c9df7a3424594ade6bd11900d596696dc06bac57" + +sprintf-js@~1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + +sshpk@^1.7.0: + version "1.13.1" + resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.13.1.tgz#512df6da6287144316dc4c18fe1cf1d940739be3" + dependencies: + asn1 "~0.2.3" + assert-plus "^1.0.0" + dashdash "^1.12.0" + getpass "^0.1.1" + optionalDependencies: + bcrypt-pbkdf "^1.0.0" + ecc-jsbn "~0.1.1" + jsbn "~0.1.0" + tweetnacl "~0.14.0" + +ssri@^4.1.2, ssri@^4.1.6, ssri@~4.1.6: + version "4.1.6" + resolved "https://registry.yarnpkg.com/ssri/-/ssri-4.1.6.tgz#0cb49b6ac84457e7bdd466cb730c3cb623e9a25b" + dependencies: + safe-buffer "^5.1.0" + +ssri@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/ssri/-/ssri-5.1.0.tgz#2cbf1df36b74d0fc91fcf89640a4b3e1d10b1899" + dependencies: + safe-buffer "^5.1.0" + +stacktrace-parser@^0.1.3: + version "0.1.4" + resolved "https://registry.yarnpkg.com/stacktrace-parser/-/stacktrace-parser-0.1.4.tgz#01397922e5f62ecf30845522c95c4fe1d25e7d4e" + +statuses@1: + version "1.4.0" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.4.0.tgz#bb73d446da2796106efcc1b601a253d6c46bd087" + +statuses@~1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.2.1.tgz#dded45cc18256d51ed40aec142489d5c61026d28" + +stream-buffers@~2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/stream-buffers/-/stream-buffers-2.2.0.tgz#91d5f5130d1cef96dcfa7f726945188741d09ee4" + +stream-counter@~0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/stream-counter/-/stream-counter-0.2.0.tgz#ded266556319c8b0e222812b9cf3b26fa7d947de" + dependencies: + readable-stream "~1.1.8" + +stream-each@^1.1.0: + version "1.2.2" + resolved "https://registry.yarnpkg.com/stream-each/-/stream-each-1.2.2.tgz#8e8c463f91da8991778765873fe4d960d8f616bd" + dependencies: + end-of-stream "^1.1.0" + stream-shift "^1.0.0" + +stream-iterate@^1.1.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/stream-iterate/-/stream-iterate-1.2.0.tgz#2bd7c77296c1702a46488b8ad41f79865eecd4e1" + dependencies: + readable-stream "^2.1.5" + stream-shift "^1.0.0" + +stream-shift@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.0.tgz#d5c752825e5367e786f78e18e445ea223a155952" + +string-width@^1.0.1, string-width@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" + dependencies: + code-point-at "^1.0.0" + is-fullwidth-code-point "^1.0.0" + strip-ansi "^3.0.0" + +string-width@^2.0.0, string-width@^2.1.0, string-width@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" + dependencies: + is-fullwidth-code-point "^2.0.0" + strip-ansi "^4.0.0" + +string_decoder@~0.10.x: + version "0.10.31" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" + +string_decoder@~1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.0.3.tgz#0fc67d7c141825de94282dd536bec6b9bce860ab" + dependencies: + safe-buffer "~5.1.0" + +stringstream@~0.0.4, stringstream@~0.0.5: + version "0.0.5" + resolved "https://registry.yarnpkg.com/stringstream/-/stringstream-0.0.5.tgz#4e484cd4de5a0bbbee18e46307710a8a81621878" + +strip-ansi@^3.0.0, strip-ansi@^3.0.1, strip-ansi@~3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" + dependencies: + ansi-regex "^2.0.0" + +strip-ansi@^4.0.0, strip-ansi@~4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" + dependencies: + ansi-regex "^3.0.0" + +strip-bom@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" + +strip-eof@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" + +strip-json-comments@~2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" + +supports-color@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" + +supports-color@^4.0.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-4.5.0.tgz#be7a0de484dec5c5cddf8b3d59125044912f635b" + dependencies: + has-flag "^2.0.0" + +table@^3.7.8: + version "3.8.3" + resolved "https://registry.yarnpkg.com/table/-/table-3.8.3.tgz#2bbc542f0fda9861a755d3947fefd8b3f513855f" + dependencies: + ajv "^4.7.0" + ajv-keywords "^1.0.0" + chalk "^1.1.1" + lodash "^4.0.0" + slice-ansi "0.0.4" + string-width "^2.0.0" + +tar-fs@^1.15.3: + version "1.16.0" + resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-1.16.0.tgz#e877a25acbcc51d8c790da1c57c9cf439817b896" + dependencies: + chownr "^1.0.1" + mkdirp "^0.5.1" + pump "^1.0.0" + tar-stream "^1.1.2" + +tar-pack@^3.4.0: + version "3.4.1" + resolved "https://registry.yarnpkg.com/tar-pack/-/tar-pack-3.4.1.tgz#e1dbc03a9b9d3ba07e896ad027317eb679a10a1f" + dependencies: + debug "^2.2.0" + fstream "^1.0.10" + fstream-ignore "^1.0.5" + once "^1.3.3" + readable-stream "^2.1.4" + rimraf "^2.5.1" + tar "^2.2.1" + uid-number "^0.0.6" + +tar-stream@^1.1.2, tar-stream@^1.5.4: + version "1.5.5" + resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-1.5.5.tgz#5cad84779f45c83b1f2508d96b09d88c7218af55" + dependencies: + bl "^1.0.0" + end-of-stream "^1.0.0" + readable-stream "^2.0.0" + xtend "^4.0.0" + +tar@^2.0.0, tar@^2.2.1, tar@~2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/tar/-/tar-2.2.1.tgz#8e4d2a256c0e2185c6b18ad694aec968b83cb1d1" + dependencies: + block-stream "*" + fstream "^1.0.2" + inherits "2" + +temp@0.8.3: + version "0.8.3" + resolved "https://registry.yarnpkg.com/temp/-/temp-0.8.3.tgz#e0c6bc4d26b903124410e4fed81103014dfc1f59" + dependencies: + os-tmpdir "^1.0.0" + rimraf "~2.2.6" + +term-size@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/term-size/-/term-size-1.2.0.tgz#458b83887f288fc56d6fffbfad262e26638efa69" + dependencies: + execa "^0.7.0" + +text-table@~0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" + +throat@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/throat/-/throat-4.1.0.tgz#89037cbc92c56ab18926e6ba4cbb200e15672a6a" + +through2@^2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.3.tgz#0004569b37c7c74ba39c43f3ced78d1ad94140be" + dependencies: + readable-stream "^2.1.5" + xtend "~4.0.1" + +"through@>=2.2.7 <3", through@^2.3.6: + version "2.3.8" + resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" + +time-stamp@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/time-stamp/-/time-stamp-1.1.0.tgz#764a5a11af50561921b133f3b44e618687e0f5c3" + +timed-out@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-4.0.1.tgz#f32eacac5a175bea25d7fab565ab3ed8741ef56f" + +tmp@0.0.31: + version "0.0.31" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.31.tgz#8f38ab9438e17315e5dbd8b3657e8bfb277ae4a7" + dependencies: + os-tmpdir "~1.0.1" + +tmp@^0.0.33: + version "0.0.33" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" + dependencies: + os-tmpdir "~1.0.2" + +tmpl@1.0.x: + version "1.0.4" + resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.4.tgz#23640dd7b42d00433911140820e5cf440e521dd1" + +to-fast-properties@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47" + +tough-cookie@~2.3.0, tough-cookie@~2.3.3: + version "2.3.3" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.3.tgz#0b618a5565b6dea90bf3425d04d55edc475a7561" + dependencies: + punycode "^1.4.1" + +trim-right@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" + +tsscmp@1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/tsscmp/-/tsscmp-1.0.5.tgz#7dc4a33af71581ab4337da91d85ca5427ebd9a97" + +tunnel-agent@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" + dependencies: + safe-buffer "^5.0.1" + +tunnel-agent@~0.4.1: + version "0.4.3" + resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.4.3.tgz#6373db76909fe570e08d73583365ed828a74eeeb" + +tweetnacl@^0.14.3, tweetnacl@~0.14.0: + version "0.14.5" + resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" + +type-check@~0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" + dependencies: + prelude-ls "~1.1.2" + +type-is@~1.6.6: + version "1.6.15" + resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.15.tgz#cab10fb4909e441c82842eafe1ad646c81804410" + dependencies: + media-typer "0.3.0" + mime-types "~2.1.15" + +typedarray@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" + +ua-parser-js@^0.7.9: + version "0.7.17" + resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.17.tgz#e9ec5f9498b9ec910e7ae3ac626a805c4d09ecac" + +uglify-es@^3.1.8: + version "3.3.8" + resolved "https://registry.yarnpkg.com/uglify-es/-/uglify-es-3.3.8.tgz#f2c68e6cff0d0f9dc9577e4da207151c2e753b7e" + dependencies: + commander "~2.13.0" + source-map "~0.6.1" + +uid-number@0.0.6, uid-number@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/uid-number/-/uid-number-0.0.6.tgz#0ea10e8035e8eb5b8e4449f06da1c730663baa81" + +uid-safe@2.1.4: + version "2.1.4" + resolved "https://registry.yarnpkg.com/uid-safe/-/uid-safe-2.1.4.tgz#3ad6f38368c6d4c8c75ec17623fb79aa1d071d81" + dependencies: + random-bytes "~1.0.0" + +uid-safe@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/uid-safe/-/uid-safe-2.0.0.tgz#a7f3c6ca64a1f6a5d04ec0ef3e4c3d5367317137" + dependencies: + base64-url "1.2.1" + +ultron@1.0.x: + version "1.0.2" + resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.0.2.tgz#ace116ab557cd197386a4e88f4685378c8b2e4fa" + +ultron@~1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.1.1.tgz#9fe1536a10a664a65266a1e3ccf85fd36302bc9c" + +umask@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/umask/-/umask-1.1.0.tgz#f29cebf01df517912bb58ff9c4e50fde8e33320d" + +unique-filename@^1.1.0, unique-filename@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/unique-filename/-/unique-filename-1.1.0.tgz#d05f2fe4032560871f30e93cbe735eea201514f3" + dependencies: + unique-slug "^2.0.0" + +unique-slug@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/unique-slug/-/unique-slug-2.0.0.tgz#db6676e7c7cc0629878ff196097c78855ae9f4ab" + dependencies: + imurmurhash "^0.1.4" + +unique-string@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unique-string/-/unique-string-1.0.0.tgz#9e1057cca851abb93398f8b33ae187b99caec11a" + dependencies: + crypto-random-string "^1.0.0" + +universalify@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.1.tgz#fa71badd4437af4c148841e3b3b165f9e9e590b7" + +unpipe@1.0.0, unpipe@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" + +unzip-response@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/unzip-response/-/unzip-response-2.0.1.tgz#d2f0f737d16b0615e72a6935ed04214572d56f97" + +update-notifier@~2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-2.2.0.tgz#1b5837cf90c0736d88627732b661c138f86de72f" + dependencies: + boxen "^1.0.0" + chalk "^1.0.0" + configstore "^3.0.0" + import-lazy "^2.1.0" + is-npm "^1.0.0" + latest-version "^3.0.0" + semver-diff "^2.0.0" + xdg-basedir "^3.0.0" + +url-parse-lax@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-1.0.0.tgz#7af8f303645e9bd79a272e7a14ac68bc0609da73" + dependencies: + prepend-http "^1.0.1" + +user-home@2.0.0, user-home@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/user-home/-/user-home-2.0.0.tgz#9c70bfd8169bc1dcbf48604e0f04b8b49cde9e9f" + dependencies: + os-homedir "^1.0.0" + +util-deprecate@1.0.2, util-deprecate@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + +util-extend@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/util-extend/-/util-extend-1.0.3.tgz#a7c216d267545169637b3b6edc6ca9119e2ff93f" + +utils-merge@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.0.tgz#0294fb922bb9375153541c4f7096231f287c8af8" + +uuid@3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.0.1.tgz#6544bba2dfda8c1cf17e629a3a305e2bb1fee6c1" + +uuid@^3.0.0, uuid@^3.1.0: + version "3.2.1" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.2.1.tgz#12c528bb9d58d0b9265d9a2f6f0fe8be17ff1f14" + +uuid@~3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.1.0.tgz#3dd3d3e790abc24d7b0d3a034ffababe28ebbc04" + +validate-npm-package-license@^3.0.1, validate-npm-package-license@~3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz#2804babe712ad3379459acfbe24746ab2c303fbc" + dependencies: + spdx-correct "~1.0.0" + spdx-expression-parse "~1.0.0" + +validate-npm-package-name@^3.0.0, validate-npm-package-name@~3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/validate-npm-package-name/-/validate-npm-package-name-3.0.0.tgz#5fa912d81eb7d0c74afc140de7317f0ca7df437e" + dependencies: + builtins "^1.0.3" + +validate-npm-package-name@~2.2.2: + version "2.2.2" + resolved "https://registry.yarnpkg.com/validate-npm-package-name/-/validate-npm-package-name-2.2.2.tgz#f65695b22f7324442019a3c7fa39a6e7fd299085" + dependencies: + builtins "0.0.7" + +vary@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/vary/-/vary-1.0.1.tgz#99e4981566a286118dfb2b817357df7993376d10" + +vary@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" + +verror@1.10.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" + dependencies: + assert-plus "^1.0.0" + core-util-is "1.0.2" + extsprintf "^1.2.0" + +vhost@~3.0.1: + version "3.0.2" + resolved "https://registry.yarnpkg.com/vhost/-/vhost-3.0.2.tgz#2fb1decd4c466aa88b0f9341af33dc1aff2478d5" + +vinyl@^0.5.0: + version "0.5.3" + resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-0.5.3.tgz#b0455b38fc5e0cf30d4325132e461970c2091cde" + dependencies: + clone "^1.0.0" + clone-stats "^0.0.1" + replace-ext "0.0.1" + +walker@~1.0.5: + version "1.0.7" + resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.7.tgz#2f7f9b8fd10d677262b18a884e28d19618e028fb" + dependencies: + makeerror "1.0.x" + +watch@~0.18.0: + version "0.18.0" + resolved "https://registry.yarnpkg.com/watch/-/watch-0.18.0.tgz#28095476c6df7c90c963138990c0a5423eb4b986" + dependencies: + exec-sh "^0.2.0" + minimist "^1.2.0" + +wcwidth@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/wcwidth/-/wcwidth-1.0.1.tgz#f0b0dcf915bc5ff1528afadb2c0e17b532da2fe8" + dependencies: + defaults "^1.0.3" + +whatwg-fetch@>=0.10.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-2.0.3.tgz#9c84ec2dcf68187ff00bc64e1274b442176e1c84" + +whatwg-fetch@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-1.1.1.tgz#ac3c9d39f320c6dce5339969d054ef43dd333319" + +which-module@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" + +which@1, which@^1.2.12, which@^1.2.14, which@^1.2.9, which@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/which/-/which-1.3.0.tgz#ff04bdfc010ee547d780bec38e1ac1c2777d253a" + dependencies: + isexe "^2.0.0" + +which@~1.2.11, which@~1.2.14: + version "1.2.14" + resolved "https://registry.yarnpkg.com/which/-/which-1.2.14.tgz#9a87c4378f03e827cecaf1acdf56c736c01c14e5" + dependencies: + isexe "^2.0.0" + +wide-align@^1.1.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.2.tgz#571e0f1b0604636ebc0dfc21b0339bbe31341710" + dependencies: + string-width "^1.0.2" + +widest-line@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/widest-line/-/widest-line-2.0.0.tgz#0142a4e8a243f8882c0233aa0e0281aa76152273" + dependencies: + string-width "^2.1.1" + +win-release@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/win-release/-/win-release-1.1.1.tgz#5fa55e02be7ca934edfc12665632e849b72e5209" + dependencies: + semver "^5.0.1" + +wordwrap@^1.0.0, wordwrap@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" + +wordwrap@~0.0.2: + version "0.0.3" + resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107" + +worker-farm@^1.3.1: + version "1.5.2" + resolved "https://registry.yarnpkg.com/worker-farm/-/worker-farm-1.5.2.tgz#32b312e5dc3d5d45d79ef44acc2587491cd729ae" + dependencies: + errno "^0.1.4" + xtend "^4.0.1" + +worker-farm@~1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/worker-farm/-/worker-farm-1.3.1.tgz#4333112bb49b17aa050b87895ca6b2cacf40e5ff" + dependencies: + errno ">=0.1.1 <0.2.0-0" + xtend ">=4.0.0 <4.1.0-0" + +wrap-ansi@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85" + dependencies: + string-width "^1.0.1" + strip-ansi "^3.0.1" + +wrappy@1, wrappy@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + +write-file-atomic@^1.2.0: + version "1.3.4" + resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-1.3.4.tgz#f807a4f0b1d9e913ae7a48112e6cc3af1991b45f" + dependencies: + graceful-fs "^4.1.11" + imurmurhash "^0.1.4" + slide "^1.1.5" + +write-file-atomic@^2.0.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-2.3.0.tgz#1ff61575c2e2a4e8e510d6fa4e243cce183999ab" + dependencies: + graceful-fs "^4.1.11" + imurmurhash "^0.1.4" + signal-exit "^3.0.2" + +write-file-atomic@~1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-1.1.4.tgz#b1f52dc2e8dc0e3cb04d187a25f758a38a90ca3b" + dependencies: + graceful-fs "^4.1.2" + imurmurhash "^0.1.4" + slide "^1.1.5" + +write-file-atomic@~2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-2.1.0.tgz#1769f4b551eedce419f0505deae2e26763542d37" + dependencies: + graceful-fs "^4.1.11" + imurmurhash "^0.1.4" + slide "^1.1.5" + +write@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/write/-/write-0.2.1.tgz#5fc03828e264cea3fe91455476f7a3c566cb0757" + dependencies: + mkdirp "^0.5.1" + +ws@^1.1.0: + version "1.1.5" + resolved "https://registry.yarnpkg.com/ws/-/ws-1.1.5.tgz#cbd9e6e75e09fc5d2c90015f21f0c40875e0dd51" + dependencies: + options ">=0.0.5" + ultron "1.0.x" + +ws@^2.0.3: + version "2.3.1" + resolved "https://registry.yarnpkg.com/ws/-/ws-2.3.1.tgz#6b94b3e447cb6a363f785eaf94af6359e8e81c80" + dependencies: + safe-buffer "~5.0.1" + ultron "~1.1.0" + +xcode@^0.9.1: + version "0.9.3" + resolved "https://registry.yarnpkg.com/xcode/-/xcode-0.9.3.tgz#910a89c16aee6cc0b42ca805a6d0b4cf87211cf3" + dependencies: + pegjs "^0.10.0" + simple-plist "^0.2.1" + uuid "3.0.1" + +xdg-basedir@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-3.0.0.tgz#496b2cc109eca8dbacfe2dc72b603c17c5870ad4" + +xmlbuilder@4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-4.0.0.tgz#98b8f651ca30aa624036f127d11cc66dc7b907a3" + dependencies: + lodash "^3.5.0" + +xmlbuilder@8.2.2: + version "8.2.2" + resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-8.2.2.tgz#69248673410b4ba42e1a6136551d2922335aa773" + +xmldoc@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/xmldoc/-/xmldoc-0.4.0.tgz#d257224be8393eaacbf837ef227fd8ec25b36888" + dependencies: + sax "~1.1.1" + +xmldom@0.1.x: + version "0.1.27" + resolved "https://registry.yarnpkg.com/xmldom/-/xmldom-0.1.27.tgz#d501f97b3bdb403af8ef9ecc20573187aadac0e9" + +xpipe@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/xpipe/-/xpipe-1.0.5.tgz#8dd8bf45fc3f7f55f0e054b878f43a62614dafdf" + +"xtend@>=4.0.0 <4.1.0-0", xtend@^4.0.0, xtend@^4.0.1, xtend@~4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" + +y18n@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41" + +yallist@^2.0.0, yallist@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" + +yargs-parser@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-7.0.0.tgz#8d0ac42f16ea55debd332caf4c4038b3e3f5dfd9" + dependencies: + camelcase "^4.1.0" + +yargs@^9.0.0: + version "9.0.1" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-9.0.1.tgz#52acc23feecac34042078ee78c0c007f5085db4c" + dependencies: + camelcase "^4.1.0" + cliui "^3.2.0" + decamelize "^1.1.1" + get-caller-file "^1.0.1" + os-locale "^2.0.0" + read-pkg-up "^2.0.0" + require-directory "^2.1.1" + require-main-filename "^1.0.1" + set-blocking "^2.0.0" + string-width "^2.0.0" + which-module "^2.0.0" + y18n "^3.2.1" + yargs-parser "^7.0.0" From 0e201a9a2ca833728b20526049c172e7240e4d7c Mon Sep 17 00:00:00 2001 From: zigen Date: Sat, 3 Mar 2018 15:10:01 +0900 Subject: [PATCH 0418/1148] fix module undefined bug in react-native@0.54 (#2051) --- index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/index.js b/index.js index c89dd5b92..acc1f7553 100644 --- a/index.js +++ b/index.js @@ -1,4 +1,4 @@ -import MapView from './lib/components/MapView'; +import MapView, { Animated, MAP_TYPES, ProviderPropType } from './lib/components/MapView'; import Marker from './lib/components/MapMarker.js'; import Overlay from './lib/components/MapOverlay.js'; @@ -9,9 +9,9 @@ export { default as UrlTile } from './lib/components/MapUrlTile.js'; export { default as LocalTile } from './lib/components/MapLocalTile.js'; export { default as Callout } from './lib/components/MapCallout.js'; export { default as AnimatedRegion } from './lib/components/AnimatedRegion.js'; -export { Animated, ProviderPropType, MAP_TYPES } from './lib/components/MapView.js'; export { Marker, Overlay }; +export { Animated, MAP_TYPES, ProviderPropType }; export const PROVIDER_GOOGLE = MapView.PROVIDER_GOOGLE; export const PROVIDER_DEFAULT = MapView.PROVIDER_DEFAULT; From f5cf88fd616f0cc4da07b55a70eee6ef24531c2c Mon Sep 17 00:00:00 2001 From: David Date: Sun, 4 Mar 2018 19:49:47 +0100 Subject: [PATCH 0419/1148] change onMyLocationChange to onUserLocationChange --- docs/mapview.md | 2 +- example/examples/EventListener.js | 2 +- .../java/com/airbnb/android/react/maps/AirMapManager.java | 2 +- .../main/java/com/airbnb/android/react/maps/AirMapView.java | 6 +++--- lib/components/MapView.js | 2 +- lib/ios/AirGoogleMaps/AIRGoogleMap.h | 2 +- lib/ios/AirGoogleMaps/AIRGoogleMap.m | 2 +- lib/ios/AirGoogleMaps/AIRGoogleMapManager.m | 2 +- 8 files changed, 10 insertions(+), 10 deletions(-) diff --git a/docs/mapview.md b/docs/mapview.md index eace17a51..b158d6874 100644 --- a/docs/mapview.md +++ b/docs/mapview.md @@ -48,7 +48,7 @@ To access event data, you will need to use `e.nativeEvent`. For example, `onPres | `onKmlReady` | `KmlContainer` | Callback that is called once the kml is fully loaded. | `onRegionChange` | `Region` | Callback that is called continuously when the region changes, such as when a user is dragging the map. | `onRegionChangeComplete` | `Region` | Callback that is called once when the region changes, such as when the user is done moving the map. -| `onMyLocationChange` | `{ coordinate: LatLng }` | Callback that is called when the underlying map figures our users current location. Make sure **showsUserLocation** is set to *true* and that the provider is `"google"`. +| `onUserLocationChange` | `{ coordinate: LatLng }` | Callback that is called when the underlying map figures our users current location. Make sure **showsUserLocation** is set to *true* and that the provider is `"google"`. | `onPress` | `{ coordinate: LatLng, position: Point }` | Callback that is called when user taps on the map. | `onPanDrag` | `{ coordinate: LatLng, position: Point }` | Callback that is called when user presses and drags the map. **NOTE**: for iOS `scrollEnabled` should be set to false to trigger the event | `onLongPress` | `{ coordinate: LatLng, position: Point }` | Callback that is called when user makes a "long press" somewhere on the map. diff --git a/example/examples/EventListener.js b/example/examples/EventListener.js index 858d47d2b..26b5b5216 100644 --- a/example/examples/EventListener.js +++ b/example/examples/EventListener.js @@ -85,7 +85,7 @@ class EventListener extends React.Component { let googleProviderProps = {}; if (this.props.provider === PROVIDER_GOOGLE) { googleProviderProps = { - onMyLocationChange: this.recordEvent('Map::onMyLocationChange'), + onUserLocationChange: this.recordEvent('Map::onUserLocationChange'), }; } diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java index 02f82e433..190901c71 100644 --- a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java @@ -317,7 +317,7 @@ public Map getExportedCustomDirectEventTypeConstants() { ); map.putAll(MapBuilder.of( - "onMyLocationChange", MapBuilder.of("registrationName", "onMyLocationChange"), + "onUserLocationChange", MapBuilder.of("registrationName", "onUserLocationChange"), "onMarkerDragStart", MapBuilder.of("registrationName", "onMarkerDragStart"), "onMarkerDrag", MapBuilder.of("registrationName", "onMarkerDrag"), "onMarkerDragEnd", MapBuilder.of("registrationName", "onMarkerDragEnd"), diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java index d52b0e1d7..69de99e6a 100644 --- a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java @@ -183,9 +183,9 @@ public void onMapReady(final GoogleMap map) { final AirMapView view = this; - map.setOnMyLocationChangeListener(new GoogleMap.OnMyLocationChangeListener() { + map.setOnUserLocationChangeListener(new GoogleMap.OnUserLocationChangeListener() { @Override - public void onMyLocationChange(Location location){ + public void onUserLocationChange(Location location){ WritableMap event = new WritableNativeMap(); WritableMap coordinate = new WritableNativeMap(); @@ -197,7 +197,7 @@ public void onMyLocationChange(Location location){ coordinate.putFloat("speed", location.getSpeed()); event.putMap("coordinate", coordinate); - manager.pushEvent(context, view, "onMyLocationChange", event); + manager.pushEvent(context, view, "onUserLocationChange", event); } }); diff --git a/lib/components/MapView.js b/lib/components/MapView.js index 6efe5c3c3..78437c62c 100644 --- a/lib/components/MapView.js +++ b/lib/components/MapView.js @@ -375,7 +375,7 @@ const propTypes = { /** * Callback that is called when the underlying map figures our users current location. */ - onMyLocationChange: PropTypes.func, + onUserLocationChange: PropTypes.func, /** * Callback that is called when user makes a "drag" somewhere on the map diff --git a/lib/ios/AirGoogleMaps/AIRGoogleMap.h b/lib/ios/AirGoogleMaps/AIRGoogleMap.h index eb9563b7f..1e729ad45 100644 --- a/lib/ios/AirGoogleMaps/AIRGoogleMap.h +++ b/lib/ios/AirGoogleMaps/AIRGoogleMap.h @@ -25,7 +25,7 @@ @property (nonatomic, copy) RCTBubblingEventBlock onKmlReady; @property (nonatomic, copy) RCTBubblingEventBlock onPress; @property (nonatomic, copy) RCTBubblingEventBlock onLongPress; -@property (nonatomic, copy) RCTBubblingEventBlock onMyLocationChange; +@property (nonatomic, copy) RCTBubblingEventBlock onUserLocationChange; @property (nonatomic, copy) RCTBubblingEventBlock onMarkerPress; @property (nonatomic, copy) RCTBubblingEventBlock onChange; @property (nonatomic, copy) RCTDirectEventBlock onRegionChange; diff --git a/lib/ios/AirGoogleMaps/AIRGoogleMap.m b/lib/ios/AirGoogleMaps/AIRGoogleMap.m index 0f737ed46..4cc883f99 100644 --- a/lib/ios/AirGoogleMaps/AIRGoogleMap.m +++ b/lib/ios/AirGoogleMaps/AIRGoogleMap.m @@ -441,7 +441,7 @@ - (void)observeValueForKeyPath:(NSString *)keyPath } }; - if (self.onMyLocationChange) self.onMyLocationChange(event); + if (self.onUserLocationChange) self.onUserLocationChange(event); } else { // This message is not for me; pass it on to super. [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; diff --git a/lib/ios/AirGoogleMaps/AIRGoogleMapManager.m b/lib/ios/AirGoogleMaps/AIRGoogleMapManager.m index 2ef546c70..8c9a3e808 100644 --- a/lib/ios/AirGoogleMaps/AIRGoogleMapManager.m +++ b/lib/ios/AirGoogleMaps/AIRGoogleMapManager.m @@ -66,7 +66,7 @@ - (UIView *)view RCT_EXPORT_VIEW_PROPERTY(onKmlReady, RCTBubblingEventBlock) RCT_EXPORT_VIEW_PROPERTY(onPress, RCTBubblingEventBlock) RCT_EXPORT_VIEW_PROPERTY(onLongPress, RCTBubblingEventBlock) -RCT_EXPORT_VIEW_PROPERTY(onMyLocationChange, RCTBubblingEventBlock) +RCT_EXPORT_VIEW_PROPERTY(onUserLocationChange, RCTBubblingEventBlock) RCT_EXPORT_VIEW_PROPERTY(onChange, RCTBubblingEventBlock) RCT_EXPORT_VIEW_PROPERTY(onMarkerPress, RCTDirectEventBlock) RCT_EXPORT_VIEW_PROPERTY(onRegionChange, RCTDirectEventBlock) From c198e08645d7776aa10569ca17b71d8c913618b5 Mon Sep 17 00:00:00 2001 From: David Date: Sun, 4 Mar 2018 19:58:23 +0100 Subject: [PATCH 0420/1148] from snake case to lower camel case --- .../src/main/java/com/airbnb/android/react/maps/AirMapView.java | 2 +- lib/ios/AirGoogleMaps/AIRGoogleMap.m | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java index 69de99e6a..960947e19 100644 --- a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java @@ -193,7 +193,7 @@ public void onUserLocationChange(Location location){ coordinate.putDouble("longitude", location.getLongitude()); coordinate.putDouble("altitude", location.getAltitude()); coordinate.putFloat("accuracy", location.getAccuracy()); - coordinate.putFloat("altitude_accuracy", location.getVerticalAccuracyMeters()); + coordinate.putFloat("altitudeAccuracy", location.getVerticalAccuracyMeters()); coordinate.putFloat("speed", location.getSpeed()); event.putMap("coordinate", coordinate); diff --git a/lib/ios/AirGoogleMaps/AIRGoogleMap.m b/lib/ios/AirGoogleMaps/AIRGoogleMap.m index 4cc883f99..001633ffd 100644 --- a/lib/ios/AirGoogleMaps/AIRGoogleMap.m +++ b/lib/ios/AirGoogleMaps/AIRGoogleMap.m @@ -436,7 +436,7 @@ - (void)observeValueForKeyPath:(NSString *)keyPath @"longitude": @(location.coordinate.longitude), @"altitude": @(location.altitude), @"accuracy": @(location.horizontalAccuracy), - @"altitude_accuracy": @(location.verticalAccuracy), + @"altitudeAccuracy": @(location.verticalAccuracy), @"speed": @(location.speed), } }; From bb9d85f259a9ebc597d953b98a0362ef877c4454 Mon Sep 17 00:00:00 2001 From: Dan Tamas Date: Mon, 5 Mar 2018 12:34:25 +0100 Subject: [PATCH 0421/1148] add PULL_REQUEST_TEMPLATE --- .github/PULL_REQUEST_TEMPLATE | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 .github/PULL_REQUEST_TEMPLATE diff --git a/.github/PULL_REQUEST_TEMPLATE b/.github/PULL_REQUEST_TEMPLATE new file mode 100644 index 000000000..965c7927c --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE @@ -0,0 +1,34 @@ + + + +### Is there any other PR opened that does the same ? + +If it exists please specify why you opened yours. +This could be one of the following (but not limited to) + + - the previous PR is stalled, as it's really old and the author didn't continue working on it + - there are conflicts with the `master` branch and the author didn't fix them + - the PR doesn't apply anymore + - my PR is better, please specify why + +(please answer here) + + +### What issue is this PR fixing + +(please link the issue here) + + + From 5e273e0c31ff275464f65e13f51620d9789bd4cc Mon Sep 17 00:00:00 2001 From: Dan Tamas Date: Mon, 5 Mar 2018 12:39:12 +0100 Subject: [PATCH 0422/1148] better texting --- .github/PULL_REQUEST_TEMPLATE | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/.github/PULL_REQUEST_TEMPLATE b/.github/PULL_REQUEST_TEMPLATE index 965c7927c..45a3f3596 100644 --- a/.github/PULL_REQUEST_TEMPLATE +++ b/.github/PULL_REQUEST_TEMPLATE @@ -1,7 +1,7 @@ (please answer here) From 07ac0cd0c0c1e5aa5a3fc5c62336fc654f8b3c5c Mon Sep 17 00:00:00 2001 From: Dan Tamas Date: Mon, 5 Mar 2018 12:40:39 +0100 Subject: [PATCH 0423/1148] add .md extension --- .github/{PULL_REQUEST_TEMPLATE => PULL_REQUEST_TEMPLATE.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename .github/{PULL_REQUEST_TEMPLATE => PULL_REQUEST_TEMPLATE.md} (100%) diff --git a/.github/PULL_REQUEST_TEMPLATE b/.github/PULL_REQUEST_TEMPLATE.md similarity index 100% rename from .github/PULL_REQUEST_TEMPLATE rename to .github/PULL_REQUEST_TEMPLATE.md From 69194ca92cb5f161ba1d66ba2d69751c36d6d2d2 Mon Sep 17 00:00:00 2001 From: Chris Scott Date: Mon, 5 Mar 2018 06:57:10 -0500 Subject: [PATCH 0424/1148] Check for presense of project-wide gradle configuration properties compileSdkVersion, buildToolsVersion, targetSdkVersion, androidMapsUtilsVersion. This provides a much better mechanism for aligning the module to the host project, particularly for play-services version (#2047) --- CHANGELOG.md | 2 ++ docs/installation.md | 21 ++++++++++++++++++++- lib/android/build.gradle | 21 +++++++++++++++------ 3 files changed, 37 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0398d7c6a..b1cefacd8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,6 @@ # Change Log +## Unreleased +* Android: Check for presence of Gradle configuration properties that may have been defined by the hosting `rootProject`: `compileSdkVersion`, `buildToolsVersion`, `googlePlayServicesVersion`, `androidMapsUtilsVersion`. This provides a better mechanism for aligning the requirements of the module with that of the host project. ## 0.20.1 (February 13, 2018) * Common: [hotfix PROVIDER_GOOGLE](https://github.com/react-community/react-native-maps/commit/cd868ea7b33a04c8bdd5e909cf134a133b2cb316) diff --git a/docs/installation.md b/docs/installation.md index 6392391af..fa7f81b32 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -107,7 +107,26 @@ The steps are as described in https://facebook.github.io/react-native/docs/runni } ``` - If you have a different play services than the one included in this library, use the following instead (switch 10.0.1 for the desired version): +If you've defined *[project-wide properties](https://developer.android.com/studio/build/gradle-tips.html)* (**recommended**) in your root `build.gradle`, this library will detect the presence of the following properties: + + ```groovy + buildscript {...} + allprojects {...} + + /** + + Project-wide Gradle configuration properties + */ + ext { + compileSdkVersion = 26 + targetSdkVersion = 26 + buildToolsVersion = "26.0.2" + supportLibVersion = "26.1.0" + googlePlayServicesVersion = "11.8.0" + androidMapsUtilsVersion = "0.5+" + } + ``` + + If you do **not** have *project-wide properties* defined and have a different play-services version than the one included in this library, use the following instead (switch 10.0.1 for the desired version): ```groovy ... diff --git a/lib/android/build.gradle b/lib/android/build.gradle index ab070626a..37f62d5bd 100644 --- a/lib/android/build.gradle +++ b/lib/android/build.gradle @@ -1,13 +1,19 @@ apply plugin: 'com.android.library' apply from: 'gradle-maven-push.gradle' +def DEFAULT_COMPILE_SDK_VERSION = 25 +def DEFAULT_BUILD_TOOLS_VERSION = "25.0.3" +def DEFAULT_TARGET_SDK_VERSION = 25 +def DEFAULT_GOOGLE_PLAY_SERVICES_VERSION = "10.2.4" +def DEFAULT_ANDROID_MAPS_UTILS_VERSION = "0.5+" + android { - compileSdkVersion 25 - buildToolsVersion "25.0.3" + compileSdkVersion rootProject.hasProperty('compileSdkVersion') ? rootProject.compileSdkVersion : DEFAULT_COMPILE_SDK_VERSION + buildToolsVersion rootProject.hasProperty('buildToolsVersion') ? rootProject.buildToolsVersion : DEFAULT_BUILD_TOOLS_VERSION defaultConfig { minSdkVersion 16 - targetSdkVersion 25 + targetSdkVersion rootProject.hasProperty('targetSdkVersion') ? rootProject.targetSdkVersion : DEFAULT_TARGET_SDK_VERSION } packagingOptions { @@ -34,8 +40,11 @@ android { } dependencies { + def googlePlayServicesVersion = rootProject.hasProperty('googlePlayServicesVersion') ? rootProject.googlePlayServicesVersion : DEFAULT_GOOGLE_PLAY_SERVICES_VERSION + def androidMapsUtilsVersion = rootProject.hasProperty('androidMapsUtilsVersion') ? rootProject.androidMapsUtilsVersion : DEFAULT_ANDROID_MAPS_UTILS_VERSION + provided "com.facebook.react:react-native:+" - compile "com.google.android.gms:play-services-base:10.2.4" - compile "com.google.android.gms:play-services-maps:10.2.4" - compile 'com.google.maps.android:android-maps-utils:0.5+' + compile "com.google.android.gms:play-services-base:$googlePlayServicesVersion" + compile "com.google.android.gms:play-services-maps:$googlePlayServicesVersion" + compile "com.google.maps.android:android-maps-utils:$androidMapsUtilsVersion" } \ No newline at end of file From 8f7bd9edbf2145f21664d282d73310457543a4e1 Mon Sep 17 00:00:00 2001 From: Alexander Veligurov Date: Mon, 5 Mar 2018 19:26:27 -0300 Subject: [PATCH 0425/1148] hotfix #2032 --- .../java/com/airbnb/android/react/maps/AirMapView.java | 9 ++++----- lib/ios/AirGoogleMaps/AIRGoogleMap.m | 1 + 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java index 960947e19..060656c02 100644 --- a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java @@ -183,18 +183,17 @@ public void onMapReady(final GoogleMap map) { final AirMapView view = this; - map.setOnUserLocationChangeListener(new GoogleMap.OnUserLocationChangeListener() { + map.setOnMyLocationChangeListener(new GoogleMap.OnMyLocationChangeListener() { @Override - public void onUserLocationChange(Location location){ + public void onMyLocationChange(Location location){ WritableMap event = new WritableNativeMap(); WritableMap coordinate = new WritableNativeMap(); coordinate.putDouble("latitude", location.getLatitude()); coordinate.putDouble("longitude", location.getLongitude()); coordinate.putDouble("altitude", location.getAltitude()); - coordinate.putFloat("accuracy", location.getAccuracy()); - coordinate.putFloat("altitudeAccuracy", location.getVerticalAccuracyMeters()); - coordinate.putFloat("speed", location.getSpeed()); + coordinate.putDouble("accuracy", location.getAccuracy()); + coordinate.putDouble("speed", location.getSpeed()); event.putMap("coordinate", coordinate); manager.pushEvent(context, view, "onUserLocationChange", event); diff --git a/lib/ios/AirGoogleMaps/AIRGoogleMap.m b/lib/ios/AirGoogleMaps/AIRGoogleMap.m index 001633ffd..a8b4cdecf 100644 --- a/lib/ios/AirGoogleMaps/AIRGoogleMap.m +++ b/lib/ios/AirGoogleMaps/AIRGoogleMap.m @@ -446,6 +446,7 @@ - (void)observeValueForKeyPath:(NSString *)keyPath // This message is not for me; pass it on to super. [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; } +} + (NSString *)GetIconUrl:(GMUPlacemark *) marker parser:(GMUKMLParser *) parser { if (marker.style.styleID != nil) { From 5f7bb26d2878b59ff3a66a05bb0238c8b47be177 Mon Sep 17 00:00:00 2001 From: wasedaigo Date: Thu, 8 Mar 2018 21:04:21 +0900 Subject: [PATCH 0426/1148] Fix for pointForCoordinate and coordinateForPoint (#2039) * Fix for pointForCoordinate and coordinateForPoint * reject when an invalid OS was passed --- lib/components/MapView.js | 40 +++++-------------------- lib/ios/AirMaps/AIRMap.m | 32 -------------------- lib/ios/AirMaps/AIRMapManager.m | 52 +++++++++++++++++++++++++++++++++ 3 files changed, 60 insertions(+), 64 deletions(-) diff --git a/lib/components/MapView.js b/lib/components/MapView.js index 78437c62c..093151725 100644 --- a/lib/components/MapView.js +++ b/lib/components/MapView.js @@ -658,18 +658,7 @@ class MapView extends React.Component { if (Platform.OS === 'android') { return NativeModules.AirMapModule.pointForCoordinate(this._getHandle(), coordinate); } else if (Platform.OS === 'ios') { - return new Promise((resolve, reject) => { - this._runCommand('pointForCoordinate', [ - coordinate, - (err, snapshot) => { - if (err) { - reject(err); - } else { - resolve(snapshot); - } - }, - ]); - }); + return this._runCommand('pointForCoordinate', [coordinate]); } return Promise.reject('pointForCoordinate not supported on this platform'); } @@ -683,24 +672,13 @@ class MapView extends React.Component { * * @return Promise Promise with the coordinate ({ latitude: Number, longitude: Number }) */ - coordinateFromPoint(point) { + coordinateForPoint(point) { if (Platform.OS === 'android') { - return NativeModules.AirMapModule.coordinateFromPoint(this._getHandle(), point); + return NativeModules.AirMapModule.coordinateForPoint(this._getHandle(), point); } else if (Platform.OS === 'ios') { - return new Promise((resolve, reject) => { - this._runCommand('coordinateFromPoint', [ - point, - (err, snapshot) => { - if (err) { - reject(err); - } else { - resolve(snapshot); - } - }, - ]); - }); + return this._runCommand('coordinateForPoint', [point]); } - return Promise.reject('coordinateFromPoint not supported on this platform'); + return Promise.reject('coordinateForPoint not supported on this platform'); } _uiManagerCommand(name) { @@ -718,19 +696,17 @@ class MapView extends React.Component { _runCommand(name, args) { switch (Platform.OS) { case 'android': - NativeModules.UIManager.dispatchViewManagerCommand( + return NativeModules.UIManager.dispatchViewManagerCommand( this._getHandle(), this._uiManagerCommand(name), args ); - break; case 'ios': - this._mapManagerCommand(name)(this._getHandle(), ...args); - break; + return this._mapManagerCommand(name)(this._getHandle(), ...args); default: - break; + return Promise.reject(`Invalid platform was passed: ${Platform.OS}`); } } diff --git a/lib/ios/AirMaps/AIRMap.m b/lib/ios/AirMaps/AIRMap.m index 797e5d42a..789cafa36 100644 --- a/lib/ios/AirMaps/AIRMap.m +++ b/lib/ios/AirMaps/AIRMap.m @@ -316,38 +316,6 @@ - (void)setLoadingIndicatorColor:(UIColor *)loadingIndicatorColor { self.activityIndicatorView.color = loadingIndicatorColor; } -RCT_EXPORT_METHOD(pointForCoordinate:(NSDictionary *)coordinate resolver: (RCTPromiseResolveBlock)resolve - rejecter:(RCTPromiseRejectBlock)reject) -{ - CGPoint touchPoint = [self convertCoordinate: - CLLocationCoordinate2DMake( - [coordinate[@"lat"] doubleValue], - [coordinate[@"lng"] doubleValue] - ) - toPointToView:self]; - - resolve(@{ - @"x": @(touchPoint.x), - @"y": @(touchPoint.y), - }); -} - -RCT_EXPORT_METHOD(coordinateForPoint:(NSDictionary *)point resolver: (RCTPromiseResolveBlock)resolve - rejecter:(RCTPromiseRejectBlock)reject) -{ - CLLocationCoordinate2D coordinate = [self convertPoint: - CGPointMake( - [point[@"x"] doubleValue], - [point[@"y"] doubleValue] - ) - toCoordinateFromView:self]; - - resolve(@{ - @"lat": @(coordinate.latitude), - @"lng": @(coordinate.longitude), - }); -} - // Include properties of MKMapView which are only available on iOS 9+ // and check if their selector is available before calling super method. diff --git a/lib/ios/AirMaps/AIRMapManager.m b/lib/ios/AirMaps/AIRMapManager.m index cfc3f3c46..a14dc320e 100644 --- a/lib/ios/AirMaps/AIRMapManager.m +++ b/lib/ios/AirMaps/AIRMapManager.m @@ -317,6 +317,58 @@ - (UIView *)view }]; } +RCT_EXPORT_METHOD(pointForCoordinate:(nonnull NSNumber *)reactTag + coordinate: (NSDictionary *)coordinate + resolver: (RCTPromiseResolveBlock)resolve + rejecter:(RCTPromiseRejectBlock)reject) +{ + [self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary *viewRegistry) { + id view = viewRegistry[reactTag]; + AIRMap *mapView = (AIRMap *)view; + if (![view isKindOfClass:[AIRMap class]]) { + reject(@"Invalid argument", [NSString stringWithFormat:@"Invalid view returned from registry, expecting AIRMap, got: %@", view], NULL); + } else { + CGPoint touchPoint = [mapView convertCoordinate: + CLLocationCoordinate2DMake( + [coordinate[@"lat"] doubleValue], + [coordinate[@"lng"] doubleValue] + ) + toPointToView:mapView]; + + resolve(@{ + @"x": @(touchPoint.x), + @"y": @(touchPoint.y), + }); + } + }]; +} + +RCT_EXPORT_METHOD(coordinateForPoint:(nonnull NSNumber *)reactTag + point:(NSDictionary *)point + resolver: (RCTPromiseResolveBlock)resolve + rejecter:(RCTPromiseRejectBlock)reject) +{ + [self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary *viewRegistry) { + id view = viewRegistry[reactTag]; + AIRMap *mapView = (AIRMap *)view; + if (![view isKindOfClass:[AIRMap class]]) { + reject(@"Invalid argument", [NSString stringWithFormat:@"Invalid view returned from registry, expecting AIRMap, got: %@", view], NULL); + } else { + CLLocationCoordinate2D coordinate = [mapView convertPoint: + CGPointMake( + [point[@"x"] doubleValue], + [point[@"y"] doubleValue] + ) + toCoordinateFromView:mapView]; + + resolve(@{ + @"lat": @(coordinate.latitude), + @"lng": @(coordinate.longitude), + }); + } + }]; +} + #pragma mark Take Snapshot - (void)takeMapSnapshot:(AIRMap *)mapView snapshotter:(MKMapSnapshotter *) snapshotter From f8e9253b616a26e746bda31825b2130ec3d79092 Mon Sep 17 00:00:00 2001 From: "Ho Yin (Michael) Cheng" Date: Sat, 10 Mar 2018 08:11:21 -0500 Subject: [PATCH 0427/1148] =?UTF-8?q?Stop=20marker=20event=20propagation?= =?UTF-8?q?=20in=20order=20to=20prevent=20onPress=20for=20MapView=E2=80=A6?= =?UTF-8?q?=20(#2068)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Stop marker event propagation in order to prevent onPress for MapViews from being called when a marker is clicked. This makes the behavior of Apple Maps identical to that of the behavior of Google Maps on Android. This fixes react-community/react-native-maps#1132. * Added a new Marker prop called stopPropagation. This allows the user to control whether or not onPress events from Markers propagate up and trigger MapView onPress events. This is iOS only. The default behavior is disabled (false) to prevent a breaking change from the current behavior. --- docs/marker.md | 1 + index.d.ts | 1 + lib/components/MapMarker.js | 18 +++++++++++++++++- 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/docs/marker.md b/docs/marker.md index deb53f4a1..200ea2fba 100644 --- a/docs/marker.md +++ b/docs/marker.md @@ -19,6 +19,7 @@ | `draggable` | `` | | This is a non-value based prop. Adding this allows the marker to be draggable (re-positioned). | `tracksViewChanges` | `Boolean` | true | Sets whether this marker should track view changes. It's recommended to turn it off whenever it's possible to improve custom marker performance. **Note**: iOS Google Maps only. | `tracksInfoWindowChanges` | `Boolean` | false | Sets whether this marker should track view changes in info window. Enabling it will let marker change content of info window after first render pass, but will lead to decreased performance, so it's recommended to disable it whenever you don't need it. **Note**: iOS Google Maps only. +| `stopPropagation` | `Boolean` | false | Sets whether this marker should propagate `onPress` events. Enabling it will stop the parent `MapView`'s `onPress` from being called. **Note**: iOS only. Android does not propagate `onPress` events. See [#1132](https://github.com/react-community/react-native-maps/issues/1132) for more information. ## Events diff --git a/index.d.ts b/index.d.ts index f68bd7e93..605683c89 100644 --- a/index.d.ts +++ b/index.d.ts @@ -146,6 +146,7 @@ declare module "react-native-maps" { rotation?: number; tracksViewChanges?: boolean tracksInfoWindowChanges?: boolean + stopPropagation?: boolean } export interface MapPolylineProps { diff --git a/lib/components/MapMarker.js b/lib/components/MapMarker.js index 5834d8783..73b82b1f4 100644 --- a/lib/components/MapMarker.js +++ b/lib/components/MapMarker.js @@ -185,6 +185,14 @@ const propTypes = { tracksInfoWindowChanges: PropTypes.bool, + /** + * Stops Marker onPress events from propagating to and triggering MapView onPress events. + * + * @platform ios + */ + + stopPropagation: PropTypes.bool, + /** * Callback that is called when the user presses on the marker */ @@ -227,7 +235,7 @@ const propTypes = { }; const defaultProps = { - onPress() {}, + stopPropagation: false, }; class MapMarker extends React.Component { @@ -295,6 +303,14 @@ class MapMarker extends React.Component { {...this.props} image={image} style={[styles.marker, this.props.style]} + onPress={event => { + if (this.props.stopPropagation) { + event.stopPropagation(); + } + if (this.props.onPress) { + this.props.onPress(event); + } + }} /> ); } From 624ba2acce84d710e628a6a3c0ef61fa4db86c58 Mon Sep 17 00:00:00 2001 From: JulienR2 Date: Sat, 10 Mar 2018 20:15:30 +0700 Subject: [PATCH 0428/1148] add Android support for onPoiClick (#2050) * add Android support for onPoiClick * add example of onPoiClick event handling * lint * typo * add support for GM on IOS * Update docs since onPoiClick is now available on Android and IOS. --- README.md | 8 +- docs/mapview.md | 1 + example/App.js | 2 + example/examples/OnPoiClick.js | 86 +++++++++++++++++++ index.d.ts | 1 + .../android/react/maps/AirMapManager.java | 3 +- .../airbnb/android/react/maps/AirMapView.java | 14 ++- lib/components/MapView.js | 5 ++ lib/ios/AirGoogleMaps/AIRGoogleMap.h | 2 + lib/ios/AirGoogleMaps/AIRGoogleMap.m | 36 +++++--- lib/ios/AirGoogleMaps/AIRGoogleMapManager.m | 21 +++-- 11 files changed, 159 insertions(+), 20 deletions(-) create mode 100644 example/examples/OnPoiClick.js diff --git a/README.md b/README.md index 300879830..e6e08cf7f 100644 --- a/README.md +++ b/README.md @@ -264,7 +264,7 @@ To run examples: ```bash npm i -npm start +npm start #Android npm run run:android @@ -397,6 +397,12 @@ Enable lite mode on Android with `liteMode` prop. Ideal when having multiple map ![](http://i.giphy.com/qZ2lAf18s89na.gif) +### On Poi Click (Google Maps Only) + +Poi are clickable, you can catch the event to get its information (usually to get the full detail from Google Place using the placeId). + +![](https://media.giphy.com/media/3480VsCKnHr31uCLU3/giphy.gif) + ### Animated Region The MapView can accept an `AnimatedRegion` value as its `region` prop. This allows you to utilize the Animated API to control the map's center and zoom. diff --git a/docs/mapview.md b/docs/mapview.md index b158d6874..66f0bd936 100644 --- a/docs/mapview.md +++ b/docs/mapview.md @@ -51,6 +51,7 @@ To access event data, you will need to use `e.nativeEvent`. For example, `onPres | `onUserLocationChange` | `{ coordinate: LatLng }` | Callback that is called when the underlying map figures our users current location. Make sure **showsUserLocation** is set to *true* and that the provider is `"google"`. | `onPress` | `{ coordinate: LatLng, position: Point }` | Callback that is called when user taps on the map. | `onPanDrag` | `{ coordinate: LatLng, position: Point }` | Callback that is called when user presses and drags the map. **NOTE**: for iOS `scrollEnabled` should be set to false to trigger the event +| `onPoiClick` | `{ coordinate: LatLng, position: Point, placeId: string, name: string }` | Callback that is called when user click on a POI. | `onLongPress` | `{ coordinate: LatLng, position: Point }` | Callback that is called when user makes a "long press" somewhere on the map. | `onMarkerPress` | | Callback that is called when a marker on the map is tapped by the user. | `onMarkerSelect` | | Callback that is called when a marker on the map becomes selected. This will be called when the callout for that marker is about to be shown. **Note**: iOS only. diff --git a/example/App.js b/example/App.js index b21c0f4b2..ebd4d8c80 100644 --- a/example/App.js +++ b/example/App.js @@ -40,6 +40,7 @@ import MapKml from './examples/MapKml'; import BugMarkerWontUpdate from './examples/BugMarkerWontUpdate'; import ImageOverlayWithAssets from './examples/ImageOverlayWithAssets'; import ImageOverlayWithURL from './examples/ImageOverlayWithURL'; +import OnPoiClick from './examples/OnPoiClick'; const IOS = Platform.OS === 'ios'; const ANDROID = Platform.OS === 'android'; @@ -158,6 +159,7 @@ class App extends React.Component { [BugMarkerWontUpdate, 'BUG: Marker Won\'t Update (Android)', true], [ImageOverlayWithAssets, 'Image Overlay Component with Assets', true], [ImageOverlayWithURL, 'Image Overlay Component with URL', true], + [OnPoiClick, 'On Poi Click', true], ] // Filter out examples that are not yet supported for Google Maps on iOS. .filter(example => ANDROID || (IOS && (example[2] || !this.state.useGoogleMaps))) diff --git a/example/examples/OnPoiClick.js b/example/examples/OnPoiClick.js new file mode 100644 index 000000000..ff6ec11b3 --- /dev/null +++ b/example/examples/OnPoiClick.js @@ -0,0 +1,86 @@ +import React from 'react'; +import { + StyleSheet, + View, + Text, + Dimensions, +} from 'react-native'; + +import MapView, { Callout, Marker, ProviderPropType } from 'react-native-maps'; + +const { width, height } = Dimensions.get('window'); + +const ASPECT_RATIO = width / height; +const LATITUDE = 37.78825; +const LONGITUDE = -122.4324; +const LATITUDE_DELTA = 0.0922; +const LONGITUDE_DELTA = LATITUDE_DELTA * ASPECT_RATIO; + +class OnPoiClick extends React.Component { + constructor(props) { + super(props); + + this.state = { + region: { + latitude: LATITUDE, + longitude: LONGITUDE, + latitudeDelta: LATITUDE_DELTA, + longitudeDelta: LONGITUDE_DELTA, + }, + poi: null, + }; + + this.onPoiClick = this.onPoiClick.bind(this); + } + + onPoiClick(e) { + const poi = e.nativeEvent; + + this.setState({ + poi, + }); + } + + render() { + return ( + + + {this.state.poi && ( + + + + Place Id: { this.state.poi.placeId } + Name: { this.state.poi.name } + + + + )} + + + ); + } +} + +OnPoiClick.propTypes = { + provider: ProviderPropType, +}; + +const styles = StyleSheet.create({ + container: { + ...StyleSheet.absoluteFillObject, + justifyContent: 'flex-end', + alignItems: 'center', + }, + map: { + ...StyleSheet.absoluteFillObject, + }, +}); + +export default OnPoiClick; diff --git a/index.d.ts b/index.d.ts index 605683c89..9b2984e40 100644 --- a/index.d.ts +++ b/index.d.ts @@ -89,6 +89,7 @@ declare module "react-native-maps" { onMarkerDragStart?: (value: { coordinate: LatLng, position: Point }) => void; onMarkerDrag?: (value: { coordinate: LatLng, position: Point }) => void; onMarkerDragEnd?: (value: { coordinate: LatLng, position: Point }) => void; + onPoiClick?: (value: {coordinate: LatLng, position: Point, placeId: string, name: string }) => void; minZoomLevel?: number; maxZoomLevel?: number; kmlSrc?: string; diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java index 190901c71..43651f7e2 100644 --- a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java @@ -322,7 +322,8 @@ public Map getExportedCustomDirectEventTypeConstants() { "onMarkerDrag", MapBuilder.of("registrationName", "onMarkerDrag"), "onMarkerDragEnd", MapBuilder.of("registrationName", "onMarkerDragEnd"), "onPanDrag", MapBuilder.of("registrationName", "onPanDrag"), - "onKmlReady", MapBuilder.of("registrationName", "onKmlReady") + "onKmlReady", MapBuilder.of("registrationName", "onKmlReady"), + "onPoiClick", MapBuilder.of("registrationName", "onPoiClick") )); return map; diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java index 060656c02..53f043e04 100644 --- a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java @@ -43,6 +43,7 @@ import com.google.android.gms.maps.model.LatLngBounds; import com.google.android.gms.maps.model.Marker; import com.google.android.gms.maps.model.MarkerOptions; +import com.google.android.gms.maps.model.PointOfInterest; import com.google.android.gms.maps.model.Polygon; import com.google.android.gms.maps.model.Polyline; import com.google.maps.android.data.kml.KmlContainer; @@ -64,7 +65,7 @@ import static android.support.v4.content.PermissionChecker.checkSelfPermission; public class AirMapView extends MapView implements GoogleMap.InfoWindowAdapter, - GoogleMap.OnMarkerDragListener, OnMapReadyCallback { + GoogleMap.OnMarkerDragListener, OnMapReadyCallback, GoogleMap.OnPoiClickListener { public GoogleMap map; private KmlLayer kmlLayer; private ProgressBar mapLoadingProgressBar; @@ -178,6 +179,7 @@ public void onMapReady(final GoogleMap map) { this.map = map; this.map.setInfoWindowAdapter(this); this.map.setOnMarkerDragListener(this); + this.map.setOnPoiClickListener(this); manager.pushEvent(context, this, "onMapReady", new WritableNativeMap()); @@ -806,6 +808,16 @@ public void onMarkerDragEnd(Marker marker) { manager.pushEvent(context, markerView, "onDragEnd", event); } + @Override + public void onPoiClick(PointOfInterest poi) { + WritableMap event = makeClickEventData(poi.latLng); + + event.putString("placeId", poi.placeId); + event.putString("name", poi.name); + + manager.pushEvent(context, this, "onPoiClick", event); + } + private ProgressBar getMapLoadingProgressBar() { if (this.mapLoadingProgressBar == null) { this.mapLoadingProgressBar = new ProgressBar(getContext()); diff --git a/lib/components/MapView.js b/lib/components/MapView.js index 093151725..f8011f148 100644 --- a/lib/components/MapView.js +++ b/lib/components/MapView.js @@ -382,6 +382,11 @@ const propTypes = { */ onPanDrag: PropTypes.func, + /** + * Callback that is called when user click on a POI + */ + onPoiClick: PropTypes.func, + /** * Callback that is called when a marker on the map is tapped by the user. */ diff --git a/lib/ios/AirGoogleMaps/AIRGoogleMap.h b/lib/ios/AirGoogleMaps/AIRGoogleMap.h index 1e729ad45..a9737755f 100644 --- a/lib/ios/AirGoogleMaps/AIRGoogleMap.h +++ b/lib/ios/AirGoogleMaps/AIRGoogleMap.h @@ -28,6 +28,7 @@ @property (nonatomic, copy) RCTBubblingEventBlock onUserLocationChange; @property (nonatomic, copy) RCTBubblingEventBlock onMarkerPress; @property (nonatomic, copy) RCTBubblingEventBlock onChange; +@property (nonatomic, copy) RCTBubblingEventBlock onPoiClick; @property (nonatomic, copy) RCTDirectEventBlock onRegionChange; @property (nonatomic, copy) RCTDirectEventBlock onRegionChangeComplete; @property (nonatomic, strong) NSMutableArray *markers; @@ -57,6 +58,7 @@ - (void)didLongPressAtCoordinate:(CLLocationCoordinate2D)coordinate; - (void)didChangeCameraPosition:(GMSCameraPosition *)position; - (void)idleAtCameraPosition:(GMSCameraPosition *)position; +- (void)didTapPOIWithPlaceID:(NSString *)placeID name:(NSString *) name location:(CLLocationCoordinate2D) location; + (MKCoordinateRegion)makeGMSCameraPositionFromMap:(GMSMapView *)map andGMSCameraPosition:(GMSCameraPosition *)position; + (GMSCameraPosition*)makeGMSCameraPositionFromMap:(GMSMapView *)map andMKCoordinateRegion:(MKCoordinateRegion)region; diff --git a/lib/ios/AirGoogleMaps/AIRGoogleMap.m b/lib/ios/AirGoogleMaps/AIRGoogleMap.m index a8b4cdecf..dd8b4e344 100644 --- a/lib/ios/AirGoogleMaps/AIRGoogleMap.m +++ b/lib/ios/AirGoogleMaps/AIRGoogleMap.m @@ -272,6 +272,20 @@ - (void)didChangeCameraPosition:(GMSCameraPosition *)position { if (self.onChange) self.onChange(event); } +- (void)didTapPOIWithPlaceID:(NSString *)placeID + name:(NSString *)name + location:(CLLocationCoordinate2D)location { + id event = @{@"placeId": placeID, + @"name": name, + @"coordinate": @{ + @"latitude": @(location.latitude), + @"longitude": @(location.longitude) + } + }; + + if (self.onPoiClick) self.onPoiClick(event); +} + - (void)idleAtCameraPosition:(GMSCameraPosition *)position { id event = @{@"continuous": @NO, @"region": regionAsJSON([AIRGoogleMap makeGMSCameraPositionFromMap:self andGMSCameraPosition:position]), @@ -456,7 +470,7 @@ + (NSString *)GetIconUrl:(GMUPlacemark *) marker parser:(GMUKMLParser *) parser } } } - + return marker.style.iconUrl; } @@ -465,28 +479,28 @@ - (NSString *)KmlSrc { } - (void)setKmlSrc:(NSString *)kmlUrl { - + _kmlSrc = kmlUrl; - + NSURL *url = [NSURL URLWithString:kmlUrl]; NSData *urlData = nil; - + if ([url isFileURL]) { urlData = [NSData dataWithContentsOfURL:url]; } else { urlData = [[NSFileManager defaultManager] contentsAtPath:kmlUrl]; } - + GMUKMLParser *parser = [[GMUKMLParser alloc] initWithData:urlData]; [parser parse]; - + NSUInteger index = 0; NSMutableArray *markers = [[NSMutableArray alloc]init]; for (GMUPlacemark *place in parser.placemarks) { - + CLLocationCoordinate2D location =((GMUPoint *) place.geometry).coordinate; - + AIRGoogleMapMarker *marker = (AIRGoogleMapMarker *)[[AIRGoogleMapMarkerManager alloc] view]; if (!marker.bridge) { marker.bridge = _bridge; @@ -499,9 +513,9 @@ - (void)setKmlSrc:(NSString *)kmlUrl { marker.imageSrc = [AIRGoogleMap GetIconUrl:place parser:parser]; marker.layer.backgroundColor = [UIColor clearColor].CGColor; marker.layer.position = CGPointZero; - + [self insertReactSubview:(UIView *) marker atIndex:index]; - + [markers addObject:@{@"id": marker.identifier, @"title": marker.title, @"description": marker.subtitle, @@ -513,7 +527,7 @@ - (void)setKmlSrc:(NSString *)kmlUrl { index++; } - + id event = @{@"markers": markers}; if (self.onKmlReady) self.onKmlReady(event); } diff --git a/lib/ios/AirGoogleMaps/AIRGoogleMapManager.m b/lib/ios/AirGoogleMaps/AIRGoogleMapManager.m index 8c9a3e808..37757cdb3 100644 --- a/lib/ios/AirGoogleMaps/AIRGoogleMapManager.m +++ b/lib/ios/AirGoogleMaps/AIRGoogleMapManager.m @@ -71,6 +71,7 @@ - (UIView *)view RCT_EXPORT_VIEW_PROPERTY(onMarkerPress, RCTDirectEventBlock) RCT_EXPORT_VIEW_PROPERTY(onRegionChange, RCTDirectEventBlock) RCT_EXPORT_VIEW_PROPERTY(onRegionChangeComplete, RCTDirectEventBlock) +RCT_EXPORT_VIEW_PROPERTY(onPoiClick, RCTDirectEventBlock) RCT_EXPORT_VIEW_PROPERTY(mapType, GMSMapViewType) RCT_EXPORT_VIEW_PROPERTY(minZoomLevel, CGFloat) RCT_EXPORT_VIEW_PROPERTY(maxZoomLevel, CGFloat) @@ -304,16 +305,16 @@ - (UIView *)view [coordinate[@"latitude"] doubleValue], [coordinate[@"longitude"] doubleValue] ); - + [self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary *viewRegistry) { id view = viewRegistry[reactTag]; if (![view isKindOfClass:[AIRGoogleMap class]]) { RCTLogError(@"Invalid view returned from registry, expecting AIRMap, got: %@", view); } else { AIRGoogleMap *mapView = (AIRGoogleMap *)view; - + CGPoint touchPoint = [mapView.projection pointForCoordinate:coord]; - + callback(@[[NSNull null], @{ @"x": @(touchPoint.x), @"y": @(touchPoint.y), @@ -330,16 +331,16 @@ - (UIView *)view [point[@"x"] doubleValue], [point[@"y"] doubleValue] ); - + [self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary *viewRegistry) { id view = viewRegistry[reactTag]; if (![view isKindOfClass:[AIRGoogleMap class]]) { RCTLogError(@"Invalid view returned from registry, expecting AIRMap, got: %@", view); } else { AIRGoogleMap *mapView = (AIRGoogleMap *)view; - + CLLocationCoordinate2D coordinate = [mapView.projection coordinateForPoint:pt]; - + callback(@[[NSNull null], @{ @"latitude": @(coordinate.latitude), @"longitude": @(coordinate.longitude), @@ -437,4 +438,12 @@ - (void)mapView:(GMSMapView *)mapView didDragMarker:(GMSMarker *)marker { AIRGMSMarker *aMarker = (AIRGMSMarker *)marker; [aMarker.fakeMarker didDragMarker:aMarker]; } + +- (void)mapView:(GMSMapView *)mapView + didTapPOIWithPlaceID:(NSString *)placeID + name:(NSString *)name + location:(CLLocationCoordinate2D)location { + AIRGoogleMap *googleMapView = (AIRGoogleMap *)mapView; + [googleMapView didTapPOIWithPlaceID:placeID name:name location:location]; +} @end From 637cfcdb1f5bac3bd734bcf629c4ba83e6479cfb Mon Sep 17 00:00:00 2001 From: Adrian Perhaite Date: Sun, 11 Mar 2018 11:33:22 +0200 Subject: [PATCH 0429/1148] Update installation.md (#2079) * Update installation.md * Update installation.md --- docs/installation.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/installation.md b/docs/installation.md index fa7f81b32..e16392c16 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -11,6 +11,10 @@ npm install react-native-maps --save Go to https://developers.google.com/maps/documentation/ios-sdk/get-api-key and get your key. +Make sure that Google Maps Android API and Google Maps SDK for iOS are enabled for the current project. +https://console.developers.google.com/apis/library/maps-android-backend.googleapis.com/ +https://console.developers.google.com/apis/library/maps-ios-backend.googleapis.com + Without this key the Google Maps map won't render anything. From 37c9ac69685536e71c5879ebf07310da6315b4c9 Mon Sep 17 00:00:00 2001 From: Vinicius Santana Date: Tue, 13 Mar 2018 06:36:44 -0700 Subject: [PATCH 0430/1148] removed BatchedBridge from docs/installation.md (#2065) * removed BatchedBridge from docs/installation.md * remove BatchedBridge in podfile only for RN 0.54+ --- docs/installation.md | 2 +- example/ios/Podfile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/installation.md b/docs/installation.md index e16392c16..3f4a6e550 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -46,7 +46,7 @@ target '_YOUR_PROJECT_TARGET_' do 'RCTText', 'RCTVibration', 'RCTWebSocket', - 'BatchedBridge' + 'BatchedBridge', // REMOVE THIS if you use RN 0.54+ ] pod 'react-native-maps', path: rn_maps_path diff --git a/example/ios/Podfile b/example/ios/Podfile index 8fe36b989..d74002999 100644 --- a/example/ios/Podfile +++ b/example/ios/Podfile @@ -20,7 +20,7 @@ target 'AirMapsExplorer' do 'RCTText', 'RCTVibration', 'RCTWebSocket', - 'BatchedBridge' + 'BatchedBridge', // REMOVE THIS if you use RN 0.54+ ] pod 'GoogleMaps' # Remove this line if you don't want to support GoogleMaps on iOS From 60c562be166015b02ace36dc08e5726852eaebe6 Mon Sep 17 00:00:00 2001 From: LeMinh1995 <37063291+LeMinh1995@users.noreply.github.com> Date: Tue, 13 Mar 2018 20:37:08 +0700 Subject: [PATCH 0431/1148] Fixed polygon and polyline not re-render when changing tile URL (#2057) --- lib/ios/AirMaps/AIRMapUrlTile.m | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/lib/ios/AirMaps/AIRMapUrlTile.m b/lib/ios/AirMaps/AIRMapUrlTile.m index 4d8abcea6..1488c489d 100644 --- a/lib/ios/AirMaps/AIRMapUrlTile.m +++ b/lib/ios/AirMaps/AIRMapUrlTile.m @@ -39,6 +39,13 @@ - (void) update if (_map == nil) return; [_map removeOverlay:self]; [_map addOverlay:self level:MKOverlayLevelAboveLabels]; + for (id overlay in _map.overlays) { + if ([overlay isKindOfClass:[AIRMapUrlTile class]]) { + continue; + } + [_map removeOverlay:overlay]; + [_map addOverlay:overlay]; + } } #pragma mark MKOverlay implementation From ed1ec9877bf6c3bcac5266ef47e904972ad5673b Mon Sep 17 00:00:00 2001 From: Harry Lachenmayer Date: Wed, 14 Mar 2018 15:49:56 +0000 Subject: [PATCH 0432/1148] Add testing section to pull request template & tighten up question copy. (#2097) --- .github/PULL_REQUEST_TEMPLATE.md | 42 ++++++++++++++++++++------------ 1 file changed, 27 insertions(+), 15 deletions(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 45a3f3596..040aaebf4 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,41 +1,53 @@ - -### Is there any other PR opened that does the same ? +### Does any other open PR do the same thing? (please answer here) - -### What issue is this PR fixing +### What issue is this PR fixing? (please link the issue here) +### How did you test this PR? + + + +(please answer here) From 6cc87aa5bf25f10ca1c689eed0ddb2c2e551a933 Mon Sep 17 00:00:00 2001 From: Youri Daamen Date: Wed, 14 Mar 2018 17:32:28 +0100 Subject: [PATCH 0433/1148] Tell user to get separate api key for android + forward slashes in path (#2098) --- docs/installation.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/docs/installation.md b/docs/installation.md index 3f4a6e550..f5586e606 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -9,14 +9,13 @@ npm install react-native-maps --save ## Get a Google Maps API key -Go to https://developers.google.com/maps/documentation/ios-sdk/get-api-key and get your key. +Go to https://developers.google.com/maps/documentation/ios-sdk/get-api-key and https://developers.google.com/maps/documentation/android-api/signup to get your keys for both iOS and Android. Make sure that Google Maps Android API and Google Maps SDK for iOS are enabled for the current project. https://console.developers.google.com/apis/library/maps-android-backend.googleapis.com/ https://console.developers.google.com/apis/library/maps-ios-backend.googleapis.com -Without this key the Google Maps map won't render anything. - +Without an API key the Google Maps map won't render anything. ## iOS - CocoaPods @@ -155,7 +154,7 @@ If you've defined *[project-wide properties](https://developer.android.com/studi 3. Specify your Google Maps API Key: - Add your API key to your manifest file (`android\app\src\main\AndroidManifest.xml`): + Add your API key to your manifest file (`android/app/src/main/AndroidManifest.xml`): ```xml From afa4bfae98d6ee484fbe065fa836de850b372387 Mon Sep 17 00:00:00 2001 From: Austin Hunt Date: Thu, 15 Mar 2018 13:06:54 -0400 Subject: [PATCH 0434/1148] Fixed missing self assignment to circle subview.map. (#2101) --- lib/ios/AirMaps/AIRMap.m | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/ios/AirMaps/AIRMap.m b/lib/ios/AirMaps/AIRMap.m index 789cafa36..959dede7c 100644 --- a/lib/ios/AirMaps/AIRMap.m +++ b/lib/ios/AirMaps/AIRMap.m @@ -116,6 +116,7 @@ - (void)insertReactSubview:(id)subview atIndex:(NSInteger)atIndex ((AIRMapPolygon *)subview).map = self; [self addOverlay:(id)subview]; } else if ([subview isKindOfClass:[AIRMapCircle class]]) { + ((AIRMapCircle *)subview).map = self; [self addOverlay:(id)subview]; } else if ([subview isKindOfClass:[AIRMapUrlTile class]]) { ((AIRMapUrlTile *)subview).map = self; From 80166b3e1f2f0152ec7feb33b9228d79986b7440 Mon Sep 17 00:00:00 2001 From: Harry Lachenmayer Date: Fri, 16 Mar 2018 12:22:46 +0000 Subject: [PATCH 0435/1148] Fix example project setup (#2094) * fix incorrect Podfile comment * fix syntax error in installation doc too. --- docs/installation.md | 2 +- example/ios/Podfile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/installation.md b/docs/installation.md index f5586e606..1db95928a 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -45,7 +45,7 @@ target '_YOUR_PROJECT_TARGET_' do 'RCTText', 'RCTVibration', 'RCTWebSocket', - 'BatchedBridge', // REMOVE THIS if you use RN 0.54+ + 'BatchedBridge', # REMOVE THIS if you use RN 0.54+ ] pod 'react-native-maps', path: rn_maps_path diff --git a/example/ios/Podfile b/example/ios/Podfile index d74002999..e13dc66e8 100644 --- a/example/ios/Podfile +++ b/example/ios/Podfile @@ -20,7 +20,7 @@ target 'AirMapsExplorer' do 'RCTText', 'RCTVibration', 'RCTWebSocket', - 'BatchedBridge', // REMOVE THIS if you use RN 0.54+ + 'BatchedBridge', # REMOVE THIS if you use RN 0.54+ ] pod 'GoogleMaps' # Remove this line if you don't want to support GoogleMaps on iOS From 43f46991f4a5b0dc9ddba9214ab17e0230b9321a Mon Sep 17 00:00:00 2001 From: "P.J. Swesey" Date: Tue, 20 Mar 2018 03:09:25 -0700 Subject: [PATCH 0436/1148] Fix a few typescript declarations (#2113) --- index.d.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/index.d.ts b/index.d.ts index 9b2984e40..d73a9775e 100644 --- a/index.d.ts +++ b/index.d.ts @@ -19,13 +19,15 @@ declare module "react-native-maps" { y: number } + export type Coordinate = Number[]; + export class AnimatedRegion extends Animated.AnimatedWithChildren { latitude: Animated.Value longitude: Animated.Value latitudeDelta: Animated.Value longitudeDelta: Animated.Value - constructor(LatLng); + constructor(region: Region); setValue(value: Region): void; setOffset(offset: Region): void; @@ -211,7 +213,7 @@ declare module "react-native-maps" { export interface MapOverlayProps { image?: any; - bounds: LatLng[]; + bounds: Coordinate[]; } export interface MapCalloutProps { From 35855f93ef056b5b073140a37e2d4b128ec00cfd Mon Sep 17 00:00:00 2001 From: mike castleman Date: Thu, 22 Mar 2018 08:02:51 -0400 Subject: [PATCH 0437/1148] permit android vector drawables to be used as markers (#2111) --- .../com/airbnb/android/react/maps/AirMapMarker.java | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapMarker.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapMarker.java index 1ad2c3965..ba71bee70 100644 --- a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapMarker.java +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapMarker.java @@ -5,6 +5,7 @@ import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.drawable.Animatable; +import android.graphics.drawable.Drawable; import android.net.Uri; import android.view.View; import android.widget.LinearLayout; @@ -283,7 +284,15 @@ public void setImage(String uri) { } else { iconBitmapDescriptor = getBitmapDescriptorByName(uri); if (iconBitmapDescriptor != null) { - iconBitmap = BitmapFactory.decodeResource(getResources(), getDrawableResourceByName(uri)); + int drawableId = getDrawableResourceByName(uri); + iconBitmap = BitmapFactory.decodeResource(getResources(), drawableId); + if (iconBitmap == null) { // VectorDrawable or similar + Drawable drawable = getResources().getDrawable(drawableId); + iconBitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888); + drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight()); + Canvas canvas = new Canvas(iconBitmap); + drawable.draw(canvas); + } } update(); } From 8cb158e06d9b3e4c1ed9311f78a8dcddfa933e9e Mon Sep 17 00:00:00 2001 From: Mark O'Sullivan Date: Mon, 26 Mar 2018 14:57:41 +0100 Subject: [PATCH 0438/1148] Updated gradle configuration for gradle 3.0.0+ (#2096) * Updated android install to follow the new gradle configuration * Updated to new gradle 3.0.0+ configuration --- docs/installation.md | 8 ++++---- lib/android/build.gradle | 10 +++++----- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/installation.md b/docs/installation.md index 1db95928a..b765f82e5 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -106,7 +106,7 @@ The steps are as described in https://facebook.github.io/react-native/docs/runni ... dependencies { ... - compile project(':react-native-maps') + implementation project(':react-native-maps') } ``` @@ -135,12 +135,12 @@ If you've defined *[project-wide properties](https://developer.android.com/studi ... dependencies { ... - compile(project(':react-native-maps')){ + implementation(project(':react-native-maps')){ exclude group: 'com.google.android.gms', module: 'play-services-base' exclude group: 'com.google.android.gms', module: 'play-services-maps' } - compile 'com.google.android.gms:play-services-base:10.0.1' - compile 'com.google.android.gms:play-services-maps:10.0.1' + implementation 'com.google.android.gms:play-services-base:10.0.1' + implementation 'com.google.android.gms:play-services-maps:10.0.1' } ``` diff --git a/lib/android/build.gradle b/lib/android/build.gradle index 37f62d5bd..acc7f579f 100644 --- a/lib/android/build.gradle +++ b/lib/android/build.gradle @@ -43,8 +43,8 @@ dependencies { def googlePlayServicesVersion = rootProject.hasProperty('googlePlayServicesVersion') ? rootProject.googlePlayServicesVersion : DEFAULT_GOOGLE_PLAY_SERVICES_VERSION def androidMapsUtilsVersion = rootProject.hasProperty('androidMapsUtilsVersion') ? rootProject.androidMapsUtilsVersion : DEFAULT_ANDROID_MAPS_UTILS_VERSION - provided "com.facebook.react:react-native:+" - compile "com.google.android.gms:play-services-base:$googlePlayServicesVersion" - compile "com.google.android.gms:play-services-maps:$googlePlayServicesVersion" - compile "com.google.maps.android:android-maps-utils:$androidMapsUtilsVersion" -} \ No newline at end of file + compileOnly "com.facebook.react:react-native:+" + implementation "com.google.android.gms:play-services-base:$googlePlayServicesVersion" + implementation "com.google.android.gms:play-services-maps:$googlePlayServicesVersion" + implementation "com.google.maps.android:android-maps-utils:$androidMapsUtilsVersion" +} From 15eb1211b403cdb94d9a008dca39b8b2a3a50363 Mon Sep 17 00:00:00 2001 From: Cody Pearce Date: Mon, 26 Mar 2018 07:03:51 -0700 Subject: [PATCH 0439/1148] Add mapPadding to mapView docs (#2121) * Add mapPadding to mapView docs * Map padding is only on Google Maps --- docs/mapview.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/mapview.md b/docs/mapview.md index 66f0bd936..a624fc22b 100644 --- a/docs/mapview.md +++ b/docs/mapview.md @@ -7,6 +7,7 @@ | `provider` | `string` | | The map framework to use.

Either `"google"` for GoogleMaps, otherwise `null` or `undefined` to use the native map framework (`MapKit` in iOS and `GoogleMaps` in android). | `region` | `Region` | | The region to be displayed by the map.

The region is defined by the center coordinates and the span of coordinates to display. | `initialRegion` | `Region` | | The initial region to be displayed by the map. Use this prop instead of `region` only if you don't want to control the viewport of the map besides the initial region.

Changing this prop after the component has mounted will not result in a region change.

This is similar to the `initialValue` prop of a text input. +| `mapPadding` | `EdgePadding` | | Adds custom padding to each side of the map. Useful when map elements/markers are obscured. **Note** Google Maps only. | `liteMode` | `Boolean` | `false` | Enable lite mode. **Note**: Android only. | `mapType` | `String` | `"standard"` | The map type to be displayed.

- standard: standard road map (default)
- satellite: satellite view
- hybrid: satellite view with roads and points of interest overlayed
- terrain: (Android only) topographic view
- mutedStandard: more subtle, makes markers/lines pop more (iOS 11.0+ only) | `customMapStyle` | `Array` | | Adds custom styling to the map component. See [README](https://github.com/airbnb/react-native-maps#customizing-the-map-style) for more information. From dfe180e67ab8900e5c686df90e0f4be41a585432 Mon Sep 17 00:00:00 2001 From: Chaitanya Deorukhkar Date: Tue, 27 Mar 2018 23:37:56 +0530 Subject: [PATCH 0440/1148] Add Mock Provider boolean on each location update (#2132) * Add Mock Provider boolean on each location update * Update mapview.md Update docs to specify that coordinate includes mock provider boolean --- docs/mapview.md | 2 +- .../src/main/java/com/airbnb/android/react/maps/AirMapView.java | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/mapview.md b/docs/mapview.md index a624fc22b..dab74f93e 100644 --- a/docs/mapview.md +++ b/docs/mapview.md @@ -49,7 +49,7 @@ To access event data, you will need to use `e.nativeEvent`. For example, `onPres | `onKmlReady` | `KmlContainer` | Callback that is called once the kml is fully loaded. | `onRegionChange` | `Region` | Callback that is called continuously when the region changes, such as when a user is dragging the map. | `onRegionChangeComplete` | `Region` | Callback that is called once when the region changes, such as when the user is done moving the map. -| `onUserLocationChange` | `{ coordinate: LatLng }` | Callback that is called when the underlying map figures our users current location. Make sure **showsUserLocation** is set to *true* and that the provider is `"google"`. +| `onUserLocationChange` | `{ coordinate: LatLng }` | Callback that is called when the underlying map figures our users current location (coordinate also includes isFromMockProvider value for Android). Make sure **showsUserLocation** is set to *true* and that the provider is `"google"`. | `onPress` | `{ coordinate: LatLng, position: Point }` | Callback that is called when user taps on the map. | `onPanDrag` | `{ coordinate: LatLng, position: Point }` | Callback that is called when user presses and drags the map. **NOTE**: for iOS `scrollEnabled` should be set to false to trigger the event | `onPoiClick` | `{ coordinate: LatLng, position: Point, placeId: string, name: string }` | Callback that is called when user click on a POI. diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java index 53f043e04..7d9b5ef9c 100644 --- a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java @@ -196,6 +196,8 @@ public void onMyLocationChange(Location location){ coordinate.putDouble("altitude", location.getAltitude()); coordinate.putDouble("accuracy", location.getAccuracy()); coordinate.putDouble("speed", location.getSpeed()); + coordinate.putBoolean("isFromMockProvider", location.isFromMockProvider()); + event.putMap("coordinate", coordinate); manager.pushEvent(context, view, "onUserLocationChange", event); From 39d48b15a647ef0b52a2851ada8a1d5d9dada14f Mon Sep 17 00:00:00 2001 From: Harry Lachenmayer Date: Tue, 27 Mar 2018 20:26:52 +0200 Subject: [PATCH 0441/1148] Upgrade React Native peer dependency to 0.54. (#2115) * Upgrade React Native dev dependency to 0.54.2. The Podfile is updated in line with the required React Native dependency changes. This commit also makes the following changes to how Ruby gems are installed: 1. Remove the bundler "binstubs" which were previously in `examples/ios`. Binstubs exist so that Ruby "binaries" can be executed without using `bundle exec`. See here for an explanation: https://github.com/rbenv/rbenv/wiki/Understanding-binstubs#project-specific-binstubs The only place bundles are used currently is in the `build:ios` script in `package.json`. This already uses `bundle exec`, so the binstubs were actually never used. 2. Install the Rubygem bundles locally in `example/ios/bundles`. `bundler` previously installed the dependencies in the global gems directory. If you are using the default macOS Ruby installation, this requires `sudo`. Since we already install node_modules & pods within the repo, I believe it makes sense to also install these locally. 3. Update the `Gemfile.lock`. The current `Gemfile.lock` specified an outdated version of Cocoapods. This throws a warning on the current example Podfile. Cocoapods is now updated to version 1.4.0. * Delete unused example flowconfig. * Make further changes according to https://github.com/ncuillery/rn-diff * GLog was renamed to glog in RN 0.54. https://github.com/facebook/react-native/commit/2fef1bafc8bee33432486212caf4fef5c659dd37 * Add a note in the installation docs for RN <0.54 --- .bundle/config | 2 +- .gitignore | 13 +- Gemfile.lock | 32 +- docs/installation.md | 23 +- example/.flowconfig | 65 - .../android/app/src/main/AndroidManifest.xml | 3 +- example/ios/Podfile | 17 +- example/ios/Podfile.lock | 84 +- example/ios/bundler | 17 - example/ios/fuzzy_match | 17 - example/ios/pod | 17 - examples/ios/bundler | 17 - examples/ios/fuzzy_match | 17 - examples/ios/pod | 17 - examples/ios/sandbox-pod | 17 - examples/ios/xcodeproj | 17 - package.json | 8 +- yarn.lock | 1127 +++++++++++------ 18 files changed, 827 insertions(+), 683 deletions(-) delete mode 100644 example/.flowconfig delete mode 100755 example/ios/bundler delete mode 100755 example/ios/fuzzy_match delete mode 100755 example/ios/pod delete mode 100755 examples/ios/bundler delete mode 100755 examples/ios/fuzzy_match delete mode 100755 examples/ios/pod delete mode 100755 examples/ios/sandbox-pod delete mode 100755 examples/ios/xcodeproj diff --git a/.bundle/config b/.bundle/config index 671243892..f7382bd2c 100644 --- a/.bundle/config +++ b/.bundle/config @@ -1,2 +1,2 @@ --- -BUNDLE_BIN: "./examples/ios" +BUNDLE_PATH: "./example/ios/bundles" diff --git a/.gitignore b/.gitignore index dc4d6bb16..f8943c908 100644 --- a/.gitignore +++ b/.gitignore @@ -21,6 +21,8 @@ DerivedData *.ipa *.xcuserstate project.xcworkspace +Pods/ +AirMapsExplorer.xcworkspace/ # Android/IJ # @@ -28,12 +30,15 @@ project.xcworkspace *.iml .gradle local.properties +lib/android/src/main/gen +example/android/app/src/main/gen # node.js # node_modules/ npm-debug.log -Pods/ -AirMapsExplorer.xcworkspace/ -lib/android/src/main/gen -example/android/app/src/main/gen +yarn-error.log + +# Rubygem bundles +# +bundles/ diff --git a/Gemfile.lock b/Gemfile.lock index 18a2c40a5..af24b6169 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -7,31 +7,32 @@ GEM minitest (~> 5.1) thread_safe (~> 0.3, >= 0.3.4) tzinfo (~> 1.1) + atomos (0.1.2) claide (1.0.2) - cocoapods (1.3.1) + cocoapods (1.4.0) activesupport (>= 4.0.2, < 5) claide (>= 1.0.2, < 2.0) - cocoapods-core (= 1.3.1) - cocoapods-deintegrate (>= 1.0.1, < 2.0) + cocoapods-core (= 1.4.0) + cocoapods-deintegrate (>= 1.0.2, < 2.0) cocoapods-downloader (>= 1.1.3, < 2.0) cocoapods-plugins (>= 1.0.0, < 2.0) cocoapods-search (>= 1.0.0, < 2.0) cocoapods-stats (>= 1.0.0, < 2.0) - cocoapods-trunk (>= 1.2.0, < 2.0) + cocoapods-trunk (>= 1.3.0, < 2.0) cocoapods-try (>= 1.1.0, < 2.0) colored2 (~> 3.1) escape (~> 0.0.4) fourflusher (~> 2.0.1) gh_inspector (~> 1.0) - molinillo (~> 0.5.7) + molinillo (~> 0.6.4) nap (~> 1.0) ruby-macho (~> 1.1) - xcodeproj (>= 1.5.1, < 2.0) - cocoapods-core (1.3.1) + xcodeproj (>= 1.5.4, < 2.0) + cocoapods-core (1.4.0) activesupport (>= 4.0.2, < 6) fuzzy_match (~> 2.0.4) nap (~> 1.0) - cocoapods-deintegrate (1.0.1) + cocoapods-deintegrate (1.0.2) cocoapods-downloader (1.1.3) cocoapods-plugins (1.0.0) nap @@ -46,20 +47,21 @@ GEM escape (0.0.4) fourflusher (2.0.1) fuzzy_match (2.0.4) - gh_inspector (1.0.3) - i18n (0.9.1) + gh_inspector (1.1.3) + i18n (0.9.5) concurrent-ruby (~> 1.0) - minitest (5.10.3) - molinillo (0.5.7) + minitest (5.11.3) + molinillo (0.6.4) nanaimo (0.2.3) nap (1.1.0) netrc (0.11.0) ruby-macho (1.1.0) thread_safe (0.3.6) - tzinfo (1.2.4) + tzinfo (1.2.5) thread_safe (~> 0.1) - xcodeproj (1.5.3) + xcodeproj (1.5.6) CFPropertyList (~> 2.3.3) + atomos (~> 0.1.2) claide (>= 1.0.2, < 2.0) colored2 (~> 3.1) nanaimo (~> 0.2.3) @@ -71,4 +73,4 @@ DEPENDENCIES cocoapods BUNDLED WITH - 1.15.4 + 1.16.1 diff --git a/docs/installation.md b/docs/installation.md index b765f82e5..eddda00c2 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -32,9 +32,12 @@ target '_YOUR_PROJECT_TARGET_' do rn_path = '../node_modules/react-native' rn_maps_path = '../node_modules/react-native-maps' + # See http://facebook.github.io/react-native/docs/integration-with-existing-apps.html#configuring-cocoapods-dependencies pod 'yoga', path: "#{rn_path}/ReactCommon/yoga/yoga.podspec" pod 'React', path: rn_path, subspecs: [ 'Core', + 'CxxBridge', + 'DevSupport', 'RCTActionSheet', 'RCTAnimation', 'RCTGeolocation', @@ -45,13 +48,22 @@ target '_YOUR_PROJECT_TARGET_' do 'RCTText', 'RCTVibration', 'RCTWebSocket', - 'BatchedBridge', # REMOVE THIS if you use RN 0.54+ ] - pod 'react-native-maps', path: rn_maps_path + # React Native third party dependencies podspecs + pod 'DoubleConversion', :podspec => "#{rn_path}/third-party-podspecs/DoubleConversion.podspec" + pod 'glog', :podspec => "#{rn_path}/third-party-podspecs/glog.podspec" + # If you are using React Native <0.54, you will get the following error: + # "The name of the given podspec `GLog` doesn't match the expected one `glog`" + # Use the following line instead: + #pod 'GLog', :podspec => "#{rn_path}/third-party-podspecs/GLog.podspec" + pod 'Folly', :podspec => "#{rn_path}/third-party-podspecs/Folly.podspec" - pod 'GoogleMaps' # Remove this line if you don't want to support Google Maps on iOS - pod 'react-native-google-maps', path: rn_maps_path # Remove this line if you don't want to support Google Maps on iOS + # react-native-maps dependencies + pod 'react-native-maps', path: rn_maps_path + pod 'react-native-google-maps', path: rn_maps_path # Remove this line if you don't want to support GoogleMaps on iOS + pod 'GoogleMaps' # Remove this line if you don't want to support GoogleMaps on iOS + pod 'Google-Maps-iOS-Utils' # Remove this line if you don't want to support GoogleMaps on iOS end post_install do |installer| @@ -69,7 +81,6 @@ end ~~~ - ## IMPORTANT!! **!! DO NOT USE !!** `react-native link` @@ -115,7 +126,7 @@ If you've defined *[project-wide properties](https://developer.android.com/studi ```groovy buildscript {...} allprojects {...} - + /** + Project-wide Gradle configuration properties */ diff --git a/example/.flowconfig b/example/.flowconfig deleted file mode 100644 index c3edaf946..000000000 --- a/example/.flowconfig +++ /dev/null @@ -1,65 +0,0 @@ -[ignore] - -# We fork some components by platform. -.*/*.web.js -.*/*.android.js - -# Some modules have their own node_modules with overlap -.*/node_modules/node-haste/.* - -# Ugh -.*/node_modules/babel.* -.*/node_modules/babylon.* -.*/node_modules/invariant.* - -# Ignore react and fbjs where there are overlaps, but don't ignore -# anything that react-native relies on -.*/node_modules/fbjs/lib/Map.js -.*/node_modules/fbjs/lib/Promise.js -.*/node_modules/fbjs/lib/fetch.js -.*/node_modules/fbjs/lib/ExecutionEnvironment.js -.*/node_modules/fbjs/lib/isEmpty.js -.*/node_modules/fbjs/lib/crc32.js -.*/node_modules/fbjs/lib/ErrorUtils.js - -# Flow has a built-in definition for the 'react' module which we prefer to use -# over the currently-untyped source -.*/node_modules/react/react.js -.*/node_modules/react/lib/React.js -.*/node_modules/react/lib/ReactDOM.js - -# Ignore commoner tests -.*/node_modules/commoner/test/.* - -# See https://github.com/facebook/flow/issues/442 -.*/react-tools/node_modules/commoner/lib/reader.js - -# Ignore jest -.*/node_modules/jest-cli/.* - -# Ignore Website -.*/website/.* - -[include] - -[libs] -node_modules/react-native/Libraries/react-native/react-native-interface.js - -[options] -module.system=haste - -munge_underscores=true - -module.name_mapper='^image![a-zA-Z0-9$_-]+$' -> 'GlobalImageStub' -module.name_mapper='^[./a-zA-Z0-9$_-]+\.\(bmp\|gif\|jpg\|jpeg\|png\|psd\|svg\|webp\|m4v\|mov\|mp4\|mpeg\|mpg\|webm\|aac\|aiff\|caf\|m4a\|mp3\|wav\|html\)$' -> 'RelativeImageStub' - -suppress_type=$FlowIssue -suppress_type=$FlowFixMe -suppress_type=$FixMe - -suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(>=0\\.\\(2[0-1]\\|1[0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\) -suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(>=0\\.\\(2[0-1]\\|1[0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)?:? #[0-9]+ -suppress_comment=\\(.\\|\n\\)*\\$FlowFixedInNextDeploy - -[version] -0.21.0 diff --git a/example/android/app/src/main/AndroidManifest.xml b/example/android/app/src/main/AndroidManifest.xml index 2f04e8891..af2692186 100644 --- a/example/android/app/src/main/AndroidManifest.xml +++ b/example/android/app/src/main/AndroidManifest.xml @@ -1,13 +1,12 @@ - "#{rn_path}/third-party-podspecs/DoubleConversion.podspec" + pod 'glog', :podspec => "#{rn_path}/third-party-podspecs/glog.podspec" + pod 'Folly', :podspec => "#{rn_path}/third-party-podspecs/Folly.podspec" + + # react-native-maps dependencies + pod 'react-native-maps', path: rn_maps_path + pod 'react-native-google-maps', path: rn_maps_path # Remove this line if you don't want to support GoogleMaps on iOS pod 'GoogleMaps' # Remove this line if you don't want to support GoogleMaps on iOS pod 'Google-Maps-iOS-Utils' # Remove this line if you don't want to support GoogleMaps on iOS - pod 'react-native-maps', path: '../../' - pod 'react-native-google-maps', path: '../../' # If you need GoogleMaps support on iOS end post_install do |installer| diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index d080a5442..a9a39c43d 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -1,4 +1,11 @@ PODS: + - boost-for-react-native (1.63.0) + - DoubleConversion (1.1.5) + - Folly (2016.09.26.00): + - boost-for-react-native + - DoubleConversion + - glog + - glog (0.3.4) - Google-Maps-iOS-Utils (2.1.0): - Google-Maps-iOS-Utils/Clustering (= 2.1.0) - Google-Maps-iOS-Utils/Geometry (= 2.1.0) @@ -20,57 +27,72 @@ PODS: - GoogleMaps/Base (2.5.0) - GoogleMaps/Maps (2.5.0): - GoogleMaps/Base - - React (0.51.0): - - React/Core (= 0.51.0) + - React (0.54.2): + - React/Core (= 0.54.2) - react-native-google-maps (0.20.1): - Google-Maps-iOS-Utils (= 2.1.0) - GoogleMaps (= 2.5.0) - React - react-native-maps (0.20.1): - React - - React/BatchedBridge (0.51.0): + - React/Core (0.54.2): + - yoga (= 0.54.2.React) + - React/CxxBridge (0.54.2): + - Folly (= 2016.09.26.00) - React/Core - - React/cxxreact_legacy - - React/Core (0.51.0): - - yoga (= 0.51.0.React) - - React/cxxreact_legacy (0.51.0): - - React/jschelpers_legacy - - React/fishhook (0.51.0) - - React/jschelpers_legacy (0.51.0) - - React/RCTActionSheet (0.51.0): + - React/cxxreact + - React/cxxreact (0.54.2): + - boost-for-react-native (= 1.63.0) + - Folly (= 2016.09.26.00) + - React/jschelpers + - React/jsinspector + - React/DevSupport (0.54.2): - React/Core - - React/RCTAnimation (0.51.0): + - React/RCTWebSocket + - React/fishhook (0.54.2) + - React/jschelpers (0.54.2): + - Folly (= 2016.09.26.00) + - React/PrivateDatabase + - React/jsinspector (0.54.2) + - React/PrivateDatabase (0.54.2) + - React/RCTActionSheet (0.54.2): - React/Core - - React/RCTBlob (0.51.0): + - React/RCTAnimation (0.54.2): - React/Core - - React/RCTGeolocation (0.51.0): + - React/RCTBlob (0.54.2): - React/Core - - React/RCTImage (0.51.0): + - React/RCTGeolocation (0.54.2): + - React/Core + - React/RCTImage (0.54.2): - React/Core - React/RCTNetwork - - React/RCTLinkingIOS (0.51.0): + - React/RCTLinkingIOS (0.54.2): - React/Core - - React/RCTNetwork (0.51.0): + - React/RCTNetwork (0.54.2): - React/Core - - React/RCTSettings (0.51.0): + - React/RCTSettings (0.54.2): - React/Core - - React/RCTText (0.51.0): + - React/RCTText (0.54.2): - React/Core - - React/RCTVibration (0.51.0): + - React/RCTVibration (0.54.2): - React/Core - - React/RCTWebSocket (0.51.0): + - React/RCTWebSocket (0.54.2): - React/Core - React/fishhook - React/RCTBlob - - yoga (0.51.0.React) + - yoga (0.54.2.React) DEPENDENCIES: + - DoubleConversion (from `../../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec`) + - Folly (from `../../node_modules/react-native/third-party-podspecs/Folly.podspec`) + - glog (from `../../node_modules/react-native/third-party-podspecs/glog.podspec`) - Google-Maps-iOS-Utils - GoogleMaps - react-native-google-maps (from `../../`) - react-native-maps (from `../../`) - - React/BatchedBridge (from `../../node_modules/react-native`) - React/Core (from `../../node_modules/react-native`) + - React/CxxBridge (from `../../node_modules/react-native`) + - React/DevSupport (from `../../node_modules/react-native`) - React/RCTActionSheet (from `../../node_modules/react-native`) - React/RCTAnimation (from `../../node_modules/react-native`) - React/RCTGeolocation (from `../../node_modules/react-native`) @@ -84,6 +106,12 @@ DEPENDENCIES: - yoga (from `../../node_modules/react-native/ReactCommon/yoga/yoga.podspec`) EXTERNAL SOURCES: + DoubleConversion: + :podspec: ../../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec + Folly: + :podspec: ../../node_modules/react-native/third-party-podspecs/Folly.podspec + glog: + :podspec: ../../node_modules/react-native/third-party-podspecs/glog.podspec React: :path: ../../node_modules/react-native react-native-google-maps: @@ -94,13 +122,17 @@ EXTERNAL SOURCES: :path: ../../node_modules/react-native/ReactCommon/yoga/yoga.podspec SPEC CHECKSUMS: + boost-for-react-native: 39c7adb57c4e60d6c5479dd8623128eb5b3f0f2c + DoubleConversion: ebb6747c5b66026ad4f97b789c3ceac6f18e57a6 + Folly: 211775e49d8da0ca658aebc8eab89d642935755c + glog: 1de0bb937dccdc981596d3b5825ebfb765017ded Google-Maps-iOS-Utils: c32891ff472eaaa1fca032beedafa1a013af7875 GoogleMaps: c087b8e5dfe87ca6ebf59adb9b4894a4146bec4f - React: 541ba768b9855e10cdc76f55427a5cd0653ca806 + React: c237e42de9c70e5cac6eeb52b4cfd3a0910c1f00 react-native-google-maps: 2cfe3b01f8422c7dae51d8764139fd70f888cfce react-native-maps: 066c2afcc89e18726377bcc685315f989ca22449 - yoga: 17521bbb0dd54a47c0b3ac43253e78cdac7488e0 + yoga: 55da126afc384965b96bff46652464373b330add -PODFILE CHECKSUM: de8380bda50e37e1da2c4dada3c722921bdbcbda +PODFILE CHECKSUM: 360a4a3ec45be233c554495279bfd087f4f29b0b COCOAPODS: 1.4.0 diff --git a/example/ios/bundler b/example/ios/bundler deleted file mode 100755 index 905387619..000000000 --- a/example/ios/bundler +++ /dev/null @@ -1,17 +0,0 @@ -#!/usr/bin/env ruby -# frozen_string_literal: true -# -# This file was generated by Bundler. -# -# The application 'bundler' is installed as part of a gem, and -# this file is here to facilitate running it. -# - -require "pathname" -ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../../Gemfile", - Pathname.new(__FILE__).realpath) - -require "rubygems" -require "bundler/setup" - -load Gem.bin_path("bundler", "bundler") diff --git a/example/ios/fuzzy_match b/example/ios/fuzzy_match deleted file mode 100755 index f71547393..000000000 --- a/example/ios/fuzzy_match +++ /dev/null @@ -1,17 +0,0 @@ -#!/usr/bin/env ruby -# frozen_string_literal: true -# -# This file was generated by Bundler. -# -# The application 'fuzzy_match' is installed as part of a gem, and -# this file is here to facilitate running it. -# - -require "pathname" -ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../../Gemfile", - Pathname.new(__FILE__).realpath) - -require "rubygems" -require "bundler/setup" - -load Gem.bin_path("fuzzy_match", "fuzzy_match") diff --git a/example/ios/pod b/example/ios/pod deleted file mode 100755 index 3c4a4d04c..000000000 --- a/example/ios/pod +++ /dev/null @@ -1,17 +0,0 @@ -#!/usr/bin/env ruby -# frozen_string_literal: true -# -# This file was generated by Bundler. -# -# The application 'pod' is installed as part of a gem, and -# this file is here to facilitate running it. -# - -require "pathname" -ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../../Gemfile", - Pathname.new(__FILE__).realpath) - -require "rubygems" -require "bundler/setup" - -load Gem.bin_path("cocoapods", "pod") diff --git a/examples/ios/bundler b/examples/ios/bundler deleted file mode 100755 index 905387619..000000000 --- a/examples/ios/bundler +++ /dev/null @@ -1,17 +0,0 @@ -#!/usr/bin/env ruby -# frozen_string_literal: true -# -# This file was generated by Bundler. -# -# The application 'bundler' is installed as part of a gem, and -# this file is here to facilitate running it. -# - -require "pathname" -ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../../Gemfile", - Pathname.new(__FILE__).realpath) - -require "rubygems" -require "bundler/setup" - -load Gem.bin_path("bundler", "bundler") diff --git a/examples/ios/fuzzy_match b/examples/ios/fuzzy_match deleted file mode 100755 index f71547393..000000000 --- a/examples/ios/fuzzy_match +++ /dev/null @@ -1,17 +0,0 @@ -#!/usr/bin/env ruby -# frozen_string_literal: true -# -# This file was generated by Bundler. -# -# The application 'fuzzy_match' is installed as part of a gem, and -# this file is here to facilitate running it. -# - -require "pathname" -ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../../Gemfile", - Pathname.new(__FILE__).realpath) - -require "rubygems" -require "bundler/setup" - -load Gem.bin_path("fuzzy_match", "fuzzy_match") diff --git a/examples/ios/pod b/examples/ios/pod deleted file mode 100755 index 3c4a4d04c..000000000 --- a/examples/ios/pod +++ /dev/null @@ -1,17 +0,0 @@ -#!/usr/bin/env ruby -# frozen_string_literal: true -# -# This file was generated by Bundler. -# -# The application 'pod' is installed as part of a gem, and -# this file is here to facilitate running it. -# - -require "pathname" -ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../../Gemfile", - Pathname.new(__FILE__).realpath) - -require "rubygems" -require "bundler/setup" - -load Gem.bin_path("cocoapods", "pod") diff --git a/examples/ios/sandbox-pod b/examples/ios/sandbox-pod deleted file mode 100755 index c76cfd0a5..000000000 --- a/examples/ios/sandbox-pod +++ /dev/null @@ -1,17 +0,0 @@ -#!/usr/bin/env ruby -# frozen_string_literal: true -# -# This file was generated by Bundler. -# -# The application 'sandbox-pod' is installed as part of a gem, and -# this file is here to facilitate running it. -# - -require "pathname" -ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../../Gemfile", - Pathname.new(__FILE__).realpath) - -require "rubygems" -require "bundler/setup" - -load Gem.bin_path("cocoapods", "sandbox-pod") diff --git a/examples/ios/xcodeproj b/examples/ios/xcodeproj deleted file mode 100755 index 3c3452c17..000000000 --- a/examples/ios/xcodeproj +++ /dev/null @@ -1,17 +0,0 @@ -#!/usr/bin/env ruby -# frozen_string_literal: true -# -# This file was generated by Bundler. -# -# The application 'xcodeproj' is installed as part of a gem, and -# this file is here to facilitate running it. -# - -require "pathname" -ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../../Gemfile", - Pathname.new(__FILE__).realpath) - -require "rubygems" -require "bundler/setup" - -load Gem.bin_path("xcodeproj", "xcodeproj") diff --git a/package.json b/package.json index 79e33c46e..0b8c1311a 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "lint": "eslint ./", "build": "npm run build:js && npm run build:android && npm run build:ios", "build:js": "exit 0", - "build:ios": "bundle install --binstubs ./examples/ios && bundle exec pod install --project-directory=./example/ios/", + "build:ios": "bundle install --path ./example/ios/bundles && bundle exec pod install --project-directory=./example/ios/", "build:android": "./gradlew :react-native-maps:assembleDebug", "ci": "npm run lint", "preversion": "./scripts/update-version.js" @@ -33,7 +33,7 @@ ], "peerDependencies": { "react": "^16.0", - "react-native": "^0.51", + "react-native": "^0.51 || ^0.52 || ^0.53 || ^0.54", "prop-types": "^15.0 || ^16.0" }, "devDependencies": { @@ -48,8 +48,8 @@ "gitbook-cli": "^2.3.0", "lodash": "^4.17.2", "prop-types": "^15.5.10", - "react": "16.0.0", - "react-native": "0.51.0" + "react": "^16.3.0-alpha.1", + "react-native": "^0.54" }, "rnpm": { "android": { diff --git a/yarn.lock b/yarn.lock index 601e05442..e36ad5313 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,6 +2,396 @@ # yarn lockfile v1 +"@babel/code-frame@7.0.0-beta.42": + version "7.0.0-beta.42" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.0.0-beta.42.tgz#a9c83233fa7cd06b39dc77adbb908616ff4f1962" + dependencies: + "@babel/highlight" "7.0.0-beta.42" + +"@babel/core@^7.0.0-beta": + version "7.0.0-beta.42" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.0.0-beta.42.tgz#b3a838fddbd19663369a0b4892189fd8d3f82001" + dependencies: + "@babel/code-frame" "7.0.0-beta.42" + "@babel/generator" "7.0.0-beta.42" + "@babel/helpers" "7.0.0-beta.42" + "@babel/template" "7.0.0-beta.42" + "@babel/traverse" "7.0.0-beta.42" + "@babel/types" "7.0.0-beta.42" + babylon "7.0.0-beta.42" + convert-source-map "^1.1.0" + debug "^3.1.0" + json5 "^0.5.0" + lodash "^4.2.0" + micromatch "^2.3.11" + resolve "^1.3.2" + semver "^5.4.1" + source-map "^0.5.0" + +"@babel/generator@7.0.0-beta.42", "@babel/generator@^7.0.0-beta": + version "7.0.0-beta.42" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.0.0-beta.42.tgz#777bb50f39c94a7e57f73202d833141f8159af33" + dependencies: + "@babel/types" "7.0.0-beta.42" + jsesc "^2.5.1" + lodash "^4.2.0" + source-map "^0.5.0" + trim-right "^1.0.1" + +"@babel/helper-annotate-as-pure@7.0.0-beta.42": + version "7.0.0-beta.42" + resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.0.0-beta.42.tgz#f2b0a3be684018b55fc308eb5408326f78479085" + dependencies: + "@babel/types" "7.0.0-beta.42" + +"@babel/helper-builder-react-jsx@7.0.0-beta.42": + version "7.0.0-beta.42" + resolved "https://registry.yarnpkg.com/@babel/helper-builder-react-jsx/-/helper-builder-react-jsx-7.0.0-beta.42.tgz#719510a0aa45e9b02909f2e252420e62900c406a" + dependencies: + "@babel/types" "7.0.0-beta.42" + esutils "^2.0.0" + +"@babel/helper-call-delegate@7.0.0-beta.42": + version "7.0.0-beta.42" + resolved "https://registry.yarnpkg.com/@babel/helper-call-delegate/-/helper-call-delegate-7.0.0-beta.42.tgz#53294eb8c5e6e53af3efda4293ff3c1237772d37" + dependencies: + "@babel/helper-hoist-variables" "7.0.0-beta.42" + "@babel/traverse" "7.0.0-beta.42" + "@babel/types" "7.0.0-beta.42" + +"@babel/helper-define-map@7.0.0-beta.42": + version "7.0.0-beta.42" + resolved "https://registry.yarnpkg.com/@babel/helper-define-map/-/helper-define-map-7.0.0-beta.42.tgz#e5aa10bd7eed2c23cc2873e5d15fbb4b40a30620" + dependencies: + "@babel/helper-function-name" "7.0.0-beta.42" + "@babel/types" "7.0.0-beta.42" + lodash "^4.2.0" + +"@babel/helper-function-name@7.0.0-beta.42": + version "7.0.0-beta.42" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.0.0-beta.42.tgz#b38b8f4f85168d1812c543dd700b5d549b0c4658" + dependencies: + "@babel/helper-get-function-arity" "7.0.0-beta.42" + "@babel/template" "7.0.0-beta.42" + "@babel/types" "7.0.0-beta.42" + +"@babel/helper-get-function-arity@7.0.0-beta.42": + version "7.0.0-beta.42" + resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0-beta.42.tgz#ad072e32f912c033053fc80478169aeadc22191e" + dependencies: + "@babel/types" "7.0.0-beta.42" + +"@babel/helper-hoist-variables@7.0.0-beta.42": + version "7.0.0-beta.42" + resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.0.0-beta.42.tgz#6e51d75192923d96972a24c223b81126a7fabca1" + dependencies: + "@babel/types" "7.0.0-beta.42" + +"@babel/helper-module-imports@7.0.0-beta.42": + version "7.0.0-beta.42" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.0.0-beta.42.tgz#4de334b42fa889d560f15122f66c3bfe1f30cb77" + dependencies: + "@babel/types" "7.0.0-beta.42" + lodash "^4.2.0" + +"@babel/helper-module-transforms@7.0.0-beta.42": + version "7.0.0-beta.42" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.0.0-beta.42.tgz#4d260cc786e712e8440bef58dae28040b77a6183" + dependencies: + "@babel/helper-module-imports" "7.0.0-beta.42" + "@babel/helper-simple-access" "7.0.0-beta.42" + "@babel/helper-split-export-declaration" "7.0.0-beta.42" + "@babel/template" "7.0.0-beta.42" + "@babel/types" "7.0.0-beta.42" + lodash "^4.2.0" + +"@babel/helper-optimise-call-expression@7.0.0-beta.42": + version "7.0.0-beta.42" + resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.0.0-beta.42.tgz#9ba770079001672a578fe833190cf03f973568b1" + dependencies: + "@babel/types" "7.0.0-beta.42" + +"@babel/helper-plugin-utils@7.0.0-beta.42": + version "7.0.0-beta.42" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.0.0-beta.42.tgz#9aa8b3e5dc72abea6b4f686712a7363cb29ea057" + +"@babel/helper-remap-async-to-generator@^7.0.0-beta": + version "7.0.0-beta.42" + resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.0.0-beta.42.tgz#c27dd7789f3a9973493a67a7914ac9253e879071" + dependencies: + "@babel/helper-annotate-as-pure" "7.0.0-beta.42" + "@babel/helper-wrap-function" "7.0.0-beta.42" + "@babel/template" "7.0.0-beta.42" + "@babel/traverse" "7.0.0-beta.42" + "@babel/types" "7.0.0-beta.42" + +"@babel/helper-replace-supers@7.0.0-beta.42": + version "7.0.0-beta.42" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.0.0-beta.42.tgz#fd984b6022982b71a1237d82d932ab69ff988aa4" + dependencies: + "@babel/helper-optimise-call-expression" "7.0.0-beta.42" + "@babel/template" "7.0.0-beta.42" + "@babel/traverse" "7.0.0-beta.42" + "@babel/types" "7.0.0-beta.42" + +"@babel/helper-simple-access@7.0.0-beta.42": + version "7.0.0-beta.42" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.0.0-beta.42.tgz#9d32bed186b0bc365115c600817e791c22d72c74" + dependencies: + "@babel/template" "7.0.0-beta.42" + "@babel/types" "7.0.0-beta.42" + lodash "^4.2.0" + +"@babel/helper-split-export-declaration@7.0.0-beta.42": + version "7.0.0-beta.42" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.0.0-beta.42.tgz#0d0d5254220a9cc4e7e226240306b939dc210ee7" + dependencies: + "@babel/types" "7.0.0-beta.42" + +"@babel/helper-wrap-function@7.0.0-beta.42": + version "7.0.0-beta.42" + resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.0.0-beta.42.tgz#5ffc6576902aa2a10fe6666e063bd45029c36db3" + dependencies: + "@babel/helper-function-name" "7.0.0-beta.42" + "@babel/template" "7.0.0-beta.42" + "@babel/traverse" "7.0.0-beta.42" + "@babel/types" "7.0.0-beta.42" + +"@babel/helpers@7.0.0-beta.42": + version "7.0.0-beta.42" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.0.0-beta.42.tgz#151c1c4e9da1b6ce83d54c1be5fb8c9c57aa5044" + dependencies: + "@babel/template" "7.0.0-beta.42" + "@babel/traverse" "7.0.0-beta.42" + "@babel/types" "7.0.0-beta.42" + +"@babel/highlight@7.0.0-beta.42": + version "7.0.0-beta.42" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.0.0-beta.42.tgz#a502a1c0d6f99b2b0e81d468a1b0c0e81e3f3623" + dependencies: + chalk "^2.0.0" + esutils "^2.0.2" + js-tokens "^3.0.0" + +"@babel/plugin-check-constants@^7.0.0-beta": + version "7.0.0-beta.38" + resolved "https://registry.yarnpkg.com/@babel/plugin-check-constants/-/plugin-check-constants-7.0.0-beta.38.tgz#bbda6306d45a4f097ccb416c0b52d6503f6502cf" + +"@babel/plugin-external-helpers@^7.0.0-beta": + version "7.0.0-beta.42" + resolved "https://registry.yarnpkg.com/@babel/plugin-external-helpers/-/plugin-external-helpers-7.0.0-beta.42.tgz#88b6bc650490026553aaa1733486d84bad177481" + dependencies: + "@babel/helper-plugin-utils" "7.0.0-beta.42" + +"@babel/plugin-proposal-class-properties@^7.0.0-beta": + version "7.0.0-beta.42" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.0.0-beta.42.tgz#2cd29050ab997567071b65896f92afc08a620748" + dependencies: + "@babel/helper-function-name" "7.0.0-beta.42" + "@babel/helper-plugin-utils" "7.0.0-beta.42" + "@babel/plugin-syntax-class-properties" "7.0.0-beta.42" + +"@babel/plugin-proposal-object-rest-spread@^7.0.0-beta": + version "7.0.0-beta.42" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.0.0-beta.42.tgz#56ebd55a8268165cb7cb43a5a232b60f5435a822" + dependencies: + "@babel/helper-plugin-utils" "7.0.0-beta.42" + "@babel/plugin-syntax-object-rest-spread" "7.0.0-beta.42" + +"@babel/plugin-syntax-class-properties@7.0.0-beta.42": + version "7.0.0-beta.42" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.0.0-beta.42.tgz#80ccce27907f22d0ffb49721e9d2cde311b41459" + dependencies: + "@babel/helper-plugin-utils" "7.0.0-beta.42" + +"@babel/plugin-syntax-dynamic-import@^7.0.0-beta": + version "7.0.0-beta.42" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.0.0-beta.42.tgz#90257d90098e2c9c2f49054269039eccd8bddd34" + dependencies: + "@babel/helper-plugin-utils" "7.0.0-beta.42" + +"@babel/plugin-syntax-flow@7.0.0-beta.42": + version "7.0.0-beta.42" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.0.0-beta.42.tgz#cc210adacb65c6c155578e7ccee30a53d1003a23" + dependencies: + "@babel/helper-plugin-utils" "7.0.0-beta.42" + +"@babel/plugin-syntax-jsx@7.0.0-beta.42": + version "7.0.0-beta.42" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.0.0-beta.42.tgz#92ef7807bbec0e12a49815a409822262cbaa7ddd" + dependencies: + "@babel/helper-plugin-utils" "7.0.0-beta.42" + +"@babel/plugin-syntax-object-rest-spread@7.0.0-beta.42": + version "7.0.0-beta.42" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.0.0-beta.42.tgz#aa789865abe78a4895d4a0be9de4d34b1a1d5063" + dependencies: + "@babel/helper-plugin-utils" "7.0.0-beta.42" + +"@babel/plugin-transform-arrow-functions@^7.0.0-beta": + version "7.0.0-beta.42" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.0.0-beta.42.tgz#b918eb8760c38d6503a1a9858fa073786b60ab2b" + dependencies: + "@babel/helper-plugin-utils" "7.0.0-beta.42" + +"@babel/plugin-transform-block-scoping@^7.0.0-beta": + version "7.0.0-beta.42" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.0.0-beta.42.tgz#272c5cc2b46613ebcd2e19491b19263c36d2c3f4" + dependencies: + "@babel/helper-plugin-utils" "7.0.0-beta.42" + lodash "^4.2.0" + +"@babel/plugin-transform-classes@^7.0.0-beta": + version "7.0.0-beta.42" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.0.0-beta.42.tgz#3b9fdb2e36f9f16b011a2ddc4ebb610e3dc9edfb" + dependencies: + "@babel/helper-annotate-as-pure" "7.0.0-beta.42" + "@babel/helper-define-map" "7.0.0-beta.42" + "@babel/helper-function-name" "7.0.0-beta.42" + "@babel/helper-optimise-call-expression" "7.0.0-beta.42" + "@babel/helper-plugin-utils" "7.0.0-beta.42" + "@babel/helper-replace-supers" "7.0.0-beta.42" + "@babel/helper-split-export-declaration" "7.0.0-beta.42" + globals "^11.1.0" + +"@babel/plugin-transform-computed-properties@^7.0.0-beta": + version "7.0.0-beta.42" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.0.0-beta.42.tgz#153662309475099c6948827fc86edbd7fb26f09d" + dependencies: + "@babel/helper-plugin-utils" "7.0.0-beta.42" + +"@babel/plugin-transform-destructuring@^7.0.0-beta": + version "7.0.0-beta.42" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.0.0-beta.42.tgz#1aaca42a00d9ef2b0307557c748f32e83ac44899" + dependencies: + "@babel/helper-plugin-utils" "7.0.0-beta.42" + +"@babel/plugin-transform-flow-strip-types@^7.0.0-beta": + version "7.0.0-beta.42" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.0.0-beta.42.tgz#0902538b641e1a6fe5d7dc49389560112bfd4071" + dependencies: + "@babel/helper-plugin-utils" "7.0.0-beta.42" + "@babel/plugin-syntax-flow" "7.0.0-beta.42" + +"@babel/plugin-transform-for-of@^7.0.0-beta": + version "7.0.0-beta.42" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.0.0-beta.42.tgz#acf51c5986050e1aff054c8d2a95ef3f6bec153e" + dependencies: + "@babel/helper-plugin-utils" "7.0.0-beta.42" + +"@babel/plugin-transform-function-name@^7.0.0-beta": + version "7.0.0-beta.42" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.0.0-beta.42.tgz#1eb004a9abde01010d47ec7629d46b1e4e2c6228" + dependencies: + "@babel/helper-function-name" "7.0.0-beta.42" + "@babel/helper-plugin-utils" "7.0.0-beta.42" + +"@babel/plugin-transform-literals@^7.0.0-beta": + version "7.0.0-beta.42" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.0.0-beta.42.tgz#61a34a82d757be4ddf937eda4b2d6c36b63b9c4e" + dependencies: + "@babel/helper-plugin-utils" "7.0.0-beta.42" + +"@babel/plugin-transform-modules-commonjs@^7.0.0-beta": + version "7.0.0-beta.42" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.0.0-beta.42.tgz#bdfb30e194c8841ec3ddd8a011974102d0d74afc" + dependencies: + "@babel/helper-module-transforms" "7.0.0-beta.42" + "@babel/helper-plugin-utils" "7.0.0-beta.42" + "@babel/helper-simple-access" "7.0.0-beta.42" + +"@babel/plugin-transform-object-assign@^7.0.0-beta": + version "7.0.0-beta.42" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-assign/-/plugin-transform-object-assign-7.0.0-beta.42.tgz#222eb7ff4a1c0d5e51aff7db24fc5772b1cae08d" + dependencies: + "@babel/helper-plugin-utils" "7.0.0-beta.42" + +"@babel/plugin-transform-parameters@^7.0.0-beta": + version "7.0.0-beta.42" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.0.0-beta.42.tgz#58434afb01afb0a3aa82402142807fb70eb3fb56" + dependencies: + "@babel/helper-call-delegate" "7.0.0-beta.42" + "@babel/helper-get-function-arity" "7.0.0-beta.42" + "@babel/helper-plugin-utils" "7.0.0-beta.42" + +"@babel/plugin-transform-react-display-name@^7.0.0-beta": + version "7.0.0-beta.42" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.0.0-beta.42.tgz#48766efd74d65fb9116ede6354f73299d73e66b9" + dependencies: + "@babel/helper-plugin-utils" "7.0.0-beta.42" + +"@babel/plugin-transform-react-jsx-source@^7.0.0-beta": + version "7.0.0-beta.42" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.0.0-beta.42.tgz#2c41adf060e76b9f0652591cfcdaddd192a21898" + dependencies: + "@babel/helper-plugin-utils" "7.0.0-beta.42" + "@babel/plugin-syntax-jsx" "7.0.0-beta.42" + +"@babel/plugin-transform-react-jsx@^7.0.0-beta": + version "7.0.0-beta.42" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.0.0-beta.42.tgz#a25731396ca87b07f10362a950deab4526345fac" + dependencies: + "@babel/helper-builder-react-jsx" "7.0.0-beta.42" + "@babel/helper-plugin-utils" "7.0.0-beta.42" + "@babel/plugin-syntax-jsx" "7.0.0-beta.42" + +"@babel/plugin-transform-regenerator@^7.0.0-beta": + version "7.0.0-beta.42" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.0.0-beta.42.tgz#af164751340a7e513c53e614c6f1f90279e459ef" + dependencies: + regenerator-transform "^0.12.3" + +"@babel/plugin-transform-shorthand-properties@^7.0.0-beta": + version "7.0.0-beta.42" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.0.0-beta.42.tgz#fb0b66f4afd4a5a67d9d84a85cbf6f7fef0a7b4f" + dependencies: + "@babel/helper-plugin-utils" "7.0.0-beta.42" + +"@babel/plugin-transform-spread@^7.0.0-beta": + version "7.0.0-beta.42" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.0.0-beta.42.tgz#4d7dde45c95e55d418477e1ea95dd6d9b71f15e4" + dependencies: + "@babel/helper-plugin-utils" "7.0.0-beta.42" + +"@babel/plugin-transform-template-literals@^7.0.0-beta": + version "7.0.0-beta.42" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.0.0-beta.42.tgz#7f05c5c003da8e485462cfc36f9d482b0a9a75df" + dependencies: + "@babel/helper-annotate-as-pure" "7.0.0-beta.42" + "@babel/helper-plugin-utils" "7.0.0-beta.42" + +"@babel/template@7.0.0-beta.42", "@babel/template@^7.0.0-beta": + version "7.0.0-beta.42" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.0.0-beta.42.tgz#7186d4e70d44cdec975049ba0a73bdaf5cdee052" + dependencies: + "@babel/code-frame" "7.0.0-beta.42" + "@babel/types" "7.0.0-beta.42" + babylon "7.0.0-beta.42" + lodash "^4.2.0" + +"@babel/traverse@7.0.0-beta.42", "@babel/traverse@^7.0.0-beta": + version "7.0.0-beta.42" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.0.0-beta.42.tgz#f4bf4d1e33d41baf45205e2d0463591d57326285" + dependencies: + "@babel/code-frame" "7.0.0-beta.42" + "@babel/generator" "7.0.0-beta.42" + "@babel/helper-function-name" "7.0.0-beta.42" + "@babel/helper-split-export-declaration" "7.0.0-beta.42" + "@babel/types" "7.0.0-beta.42" + babylon "7.0.0-beta.42" + debug "^3.1.0" + globals "^11.1.0" + invariant "^2.2.0" + lodash "^4.2.0" + +"@babel/types@7.0.0-beta.42", "@babel/types@^7.0.0-beta": + version "7.0.0-beta.42" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.0.0-beta.42.tgz#1e2118767684880f6963801b272fd2b3348efacc" + dependencies: + esutils "^2.0.2" + lodash "^4.2.0" + to-fast-properties "^2.0.0" + JSONStream@~1.3.1: version "1.3.2" resolved "https://registry.yarnpkg.com/JSONStream/-/JSONStream-1.3.2.tgz#c102371b6ec3a7cf3b847ca00c20bb0fce4c6dea" @@ -21,18 +411,11 @@ absolute-path@^0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/absolute-path/-/absolute-path-0.0.0.tgz#a78762fbdadfb5297be99b15d35a785b2f095bf7" -accepts@~1.2.12, accepts@~1.2.13: - version "1.2.13" - resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.2.13.tgz#e5f1f3928c6d95fd96558c36ec3d9d0de4a6ecea" - dependencies: - mime-types "~2.1.6" - negotiator "0.5.3" - -accepts@~1.3.0: - version "1.3.4" - resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.4.tgz#86246758c7dd6d21a6474ff084a4740ec05eb21f" +accepts@~1.3.3, accepts@~1.3.4: + version "1.3.5" + resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.5.tgz#eb777df6011723a3b14e8a72c0805c8e86746bd2" dependencies: - mime-types "~2.1.16" + mime-types "~2.1.18" negotiator "0.6.1" acorn-jsx@^3.0.0: @@ -312,7 +695,7 @@ babel-eslint@^6.1.2: lodash.assign "^4.0.0" lodash.pickby "^4.0.0" -babel-generator@^6.24.1, babel-generator@^6.26.0: +babel-generator@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.26.0.tgz#ac1ae20070b79f6e3ca1d3269613053774f20dc5" dependencies: @@ -446,7 +829,7 @@ babel-plugin-check-es2015-constants@^6.22.0, babel-plugin-check-es2015-constants dependencies: babel-runtime "^6.22.0" -babel-plugin-external-helpers@^6.18.0: +babel-plugin-external-helpers@^6.22.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-external-helpers/-/babel-plugin-external-helpers-6.22.0.tgz#2285f48b02bd5dede85175caf8c62e86adccefa1" dependencies: @@ -1003,6 +1386,10 @@ babel-types@^6.0.19, babel-types@^6.19.0, babel-types@^6.24.1, babel-types@^6.26 lodash "^4.17.4" to-fast-properties "^1.0.3" +babylon@7.0.0-beta.42, babylon@^7.0.0-beta: + version "7.0.0-beta.42" + resolved "https://registry.yarnpkg.com/babylon/-/babylon-7.0.0-beta.42.tgz#67cfabcd4f3ec82999d29031ccdea89d0ba99657" + babylon@^6.0.18, babylon@^6.18.0: version "6.18.0" resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3" @@ -1023,25 +1410,15 @@ base64-js@^1.1.2: version "1.2.1" resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.2.1.tgz#a91947da1f4a516ea38e5b4ec0ec3773675e0886" -base64-url@1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/base64-url/-/base64-url-1.2.1.tgz#199fd661702a0e7b7dcae6e0698bb089c52f6d78" - bash-color@0.0.4: version "0.0.4" resolved "https://registry.yarnpkg.com/bash-color/-/bash-color-0.0.4.tgz#e9be8ce33540cada4881768c59bd63865736e913" -basic-auth-connect@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/basic-auth-connect/-/basic-auth-connect-1.0.0.tgz#fdb0b43962ca7b40456a7c2bb48fe173da2d2122" - -basic-auth@~1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/basic-auth/-/basic-auth-1.0.4.tgz#030935b01de7c9b94a824b29f3fccb750d3a5290" - -batch@0.5.3: - version "0.5.3" - resolved "https://registry.yarnpkg.com/batch/-/batch-0.5.3.tgz#3f3414f380321743bfc1042f9a83ff1d5824d464" +basic-auth@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/basic-auth/-/basic-auth-2.0.0.tgz#015db3f353e02e56377755f962742e8981e7bbba" + dependencies: + safe-buffer "5.1.1" bcrypt-pbkdf@^1.0.0: version "1.0.1" @@ -1079,21 +1456,6 @@ bluebird@^3.5.0, bluebird@~3.5.0: version "3.5.1" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.1.tgz#d9551f9de98f1fcda1e683d17ee91a0602ee2eb9" -body-parser@~1.13.3: - version "1.13.3" - resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.13.3.tgz#c08cf330c3358e151016a05746f13f029c97fa97" - dependencies: - bytes "2.1.0" - content-type "~1.0.1" - debug "~2.2.0" - depd "~1.0.1" - http-errors "~1.3.1" - iconv-lite "0.4.11" - on-finished "~2.3.0" - qs "4.0.0" - raw-body "~2.1.2" - type-is "~1.6.6" - boom@2.x.x: version "2.10.1" resolved "https://registry.yarnpkg.com/boom/-/boom-2.10.1.tgz#39c8918ceff5799f83f9492a848f625add0c766f" @@ -1173,13 +1535,9 @@ builtins@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/builtins/-/builtins-1.0.3.tgz#cb94faeb61c8696451db36534e1422f94f0aee88" -bytes@2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/bytes/-/bytes-2.1.0.tgz#ac93c410e2ffc9cc7cf4b464b38289067f5e47b4" - -bytes@2.4.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/bytes/-/bytes-2.4.0.tgz#7d97196f9d5baf7f6935e25985549edd2a6c2339" +bytes@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" cacache@^10.0.0: version "10.0.2" @@ -1396,22 +1754,23 @@ commander@^2.9.0, commander@~2.13.0: version "2.13.0" resolved "https://registry.yarnpkg.com/commander/-/commander-2.13.0.tgz#6964bca67685df7c1f1430c584f07d7597885b9c" -compressible@~2.0.5: - version "2.0.12" - resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.12.tgz#c59a5c99db76767e9876500e271ef63b3493bd66" +compressible@~2.0.13: + version "2.0.13" + resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.13.tgz#0d1020ab924b2fdb4d6279875c7d6daba6baa7a9" dependencies: - mime-db ">= 1.30.0 < 2" + mime-db ">= 1.33.0 < 2" -compression@~1.5.2: - version "1.5.2" - resolved "https://registry.yarnpkg.com/compression/-/compression-1.5.2.tgz#b03b8d86e6f8ad29683cba8df91ddc6ffc77b395" +compression@^1.7.1: + version "1.7.2" + resolved "http://registry.npmjs.org/compression/-/compression-1.7.2.tgz#aaffbcd6aaf854b44ebb280353d5ad1651f59a69" dependencies: - accepts "~1.2.12" - bytes "2.1.0" - compressible "~2.0.5" - debug "~2.2.0" - on-headers "~1.0.0" - vary "~1.0.1" + accepts "~1.3.4" + bytes "3.0.0" + compressible "~2.0.13" + debug "2.6.9" + on-headers "~1.0.1" + safe-buffer "5.1.1" + vary "~1.1.2" concat-map@0.0.1: version "0.0.1" @@ -1443,50 +1802,14 @@ configstore@^3.0.0: write-file-atomic "^2.0.0" xdg-basedir "^3.0.0" -connect-timeout@~1.6.2: - version "1.6.2" - resolved "https://registry.yarnpkg.com/connect-timeout/-/connect-timeout-1.6.2.tgz#de9a5ec61e33a12b6edaab7b5f062e98c599b88e" - dependencies: - debug "~2.2.0" - http-errors "~1.3.1" - ms "0.7.1" - on-headers "~1.0.0" - -connect@^2.8.3: - version "2.30.2" - resolved "https://registry.yarnpkg.com/connect/-/connect-2.30.2.tgz#8da9bcbe8a054d3d318d74dfec903b5c39a1b609" - dependencies: - basic-auth-connect "1.0.0" - body-parser "~1.13.3" - bytes "2.1.0" - compression "~1.5.2" - connect-timeout "~1.6.2" - content-type "~1.0.1" - cookie "0.1.3" - cookie-parser "~1.3.5" - cookie-signature "1.0.6" - csurf "~1.8.3" - debug "~2.2.0" - depd "~1.0.1" - errorhandler "~1.4.2" - express-session "~1.11.3" - finalhandler "0.4.0" - fresh "0.3.0" - http-errors "~1.3.1" - method-override "~2.3.5" - morgan "~1.6.1" - multiparty "3.3.2" - on-headers "~1.0.0" - parseurl "~1.3.0" - pause "0.1.0" - qs "4.0.0" - response-time "~2.3.1" - serve-favicon "~2.3.0" - serve-index "~1.7.2" - serve-static "~1.10.0" - type-is "~1.6.6" - utils-merge "1.0.0" - vhost "~3.0.1" +connect@^3.6.5: + version "3.6.6" + resolved "https://registry.yarnpkg.com/connect/-/connect-3.6.6.tgz#09eff6c55af7236e137135a72574858b6786f524" + dependencies: + debug "2.6.9" + finalhandler "1.1.0" + parseurl "~1.3.2" + utils-merge "1.0.1" console-control-strings@^1.0.0, console-control-strings@~1.1.0: version "1.1.0" @@ -1496,29 +1819,10 @@ contains-path@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/contains-path/-/contains-path-0.1.0.tgz#fe8cf184ff6670b6baef01a9d4861a5cbec4120a" -content-type@~1.0.1: - version "1.0.4" - resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" - -convert-source-map@^1.5.0: +convert-source-map@^1.1.0, convert-source-map@^1.5.0: version "1.5.1" resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.5.1.tgz#b8278097b9bc229365de5c62cf5fcaed8b5599e5" -cookie-parser@~1.3.5: - version "1.3.5" - resolved "https://registry.yarnpkg.com/cookie-parser/-/cookie-parser-1.3.5.tgz#9d755570fb5d17890771227a02314d9be7cf8356" - dependencies: - cookie "0.1.3" - cookie-signature "1.0.6" - -cookie-signature@1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" - -cookie@0.1.3: - version "0.1.3" - resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.1.3.tgz#e734a5c1417fce472d5aef82c381cabb64d1a435" - copy-concurrently@^1.0.0: version "1.0.5" resolved "https://registry.yarnpkg.com/copy-concurrently/-/copy-concurrently-1.0.5.tgz#92297398cae34937fcafd6ec8139c18051f0b5e0" @@ -1542,19 +1846,15 @@ core-util-is@1.0.2, core-util-is@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" -crc@3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/crc/-/crc-3.3.0.tgz#fa622e1bc388bf257309082d6b65200ce67090ba" - create-error-class@^3.0.0: version "3.0.2" resolved "https://registry.yarnpkg.com/create-error-class/-/create-error-class-3.0.2.tgz#06be7abef947a3f14a30fd610671d401bca8b7b6" dependencies: capture-stack-trace "^1.0.0" -create-react-class@^15.5.2: - version "15.6.2" - resolved "https://registry.yarnpkg.com/create-react-class/-/create-react-class-15.6.2.tgz#cf1ed15f12aad7f14ef5f2dfe05e6c42f91ef02a" +create-react-class@^15.6.3: + version "15.6.3" + resolved "https://registry.yarnpkg.com/create-react-class/-/create-react-class-15.6.3.tgz#2d73237fb3f970ae6ebe011a9e66f46dbca80036" dependencies: fbjs "^0.8.9" loose-envify "^1.3.1" @@ -1584,23 +1884,6 @@ crypto-random-string@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-1.0.0.tgz#a230f64f568310e1498009940790ec99545bca7e" -csrf@~3.0.0: - version "3.0.6" - resolved "https://registry.yarnpkg.com/csrf/-/csrf-3.0.6.tgz#b61120ddceeafc91e76ed5313bb5c0b2667b710a" - dependencies: - rndm "1.2.0" - tsscmp "1.0.5" - uid-safe "2.1.4" - -csurf@~1.8.3: - version "1.8.3" - resolved "https://registry.yarnpkg.com/csurf/-/csurf-1.8.3.tgz#23f2a13bf1d8fce1d0c996588394442cba86a56a" - dependencies: - cookie "0.1.3" - cookie-signature "1.0.6" - csrf "~3.0.0" - http-errors "~1.3.1" - cyclist@~0.2.2: version "0.2.2" resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-0.2.2.tgz#1b33792e11e914a2fd6d6ed6447464444e5fa640" @@ -1637,12 +1920,6 @@ debug@^3.1.0: dependencies: ms "2.0.0" -debug@~2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.2.0.tgz#f87057e995b1a1f6ae6a4960664137bc56f039da" - dependencies: - ms "0.7.1" - debuglog@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/debuglog/-/debuglog-1.0.1.tgz#aa24ffb9ac3df9a2351837cfb2d279360cd78492" @@ -1696,11 +1973,11 @@ denodeify@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/denodeify/-/denodeify-1.2.1.tgz#3a36287f5034e699e7577901052c2e6c94251631" -depd@~1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/depd/-/depd-1.0.1.tgz#80aec64c9d6d97e65cc2a9caa93c0aa6abf73aaa" +depd@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.1.tgz#5783b4e1c459f06fa5ca27f991f3d06e7a310359" -depd@~1.1.0: +depd@~1.1.1, depd@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" @@ -1722,6 +1999,10 @@ detect-libc@^1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" +detect-newline@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-2.1.0.tgz#f41f1c10be4b00e87b5f13da680759f2c5bfd3e2" + dezalgo@^1.0.0, dezalgo@^1.0.1, dezalgo@^1.0.2, dezalgo@~1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/dezalgo/-/dezalgo-1.0.3.tgz#7f742de066fc748bc8db820569dddce49bf0d456" @@ -1792,6 +2073,10 @@ ee-first@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" +encodeurl@~1.0.1, encodeurl@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" + encoding@^0.1.11: version "0.1.12" resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.12.tgz#538b66f3ee62cd1ab51ec323829d1f9480c74beb" @@ -1818,7 +2103,7 @@ err-code@^1.0.0: version "1.1.2" resolved "https://registry.yarnpkg.com/err-code/-/err-code-1.1.2.tgz#06e0116d3028f6aef4806849eb0ea6a748ae6960" -"errno@>=0.1.1 <0.2.0-0", errno@^0.1.4: +"errno@>=0.1.1 <0.2.0-0": version "0.1.6" resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.6.tgz#c386ce8a6283f14fc09563b71560908c9bf53026" dependencies: @@ -1830,11 +2115,11 @@ error-ex@^1.2.0: dependencies: is-arrayish "^0.2.1" -errorhandler@~1.4.2: - version "1.4.3" - resolved "https://registry.yarnpkg.com/errorhandler/-/errorhandler-1.4.3.tgz#b7b70ed8f359e9db88092f2d20c0f831420ad83f" +errorhandler@^1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/errorhandler/-/errorhandler-1.5.0.tgz#eaba64ca5d542a311ac945f582defc336165d9f4" dependencies: - accepts "~1.3.0" + accepts "~1.3.3" escape-html "~1.0.3" es-abstract@^1.7.0: @@ -1917,10 +2202,6 @@ es6-weak-map@^2.0.1: es6-iterator "^2.0.1" es6-symbol "^3.1.1" -escape-html@1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.2.tgz#d77d32fa98e38c2f41ae85e9278e0e0e6ba1022c" - escape-html@~1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" @@ -2067,13 +2348,13 @@ estraverse@^4.0.0, estraverse@^4.1.0, estraverse@^4.1.1, estraverse@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.2.0.tgz#0dee3fed31fcd469618ce7342099fc1afa0bdb13" -esutils@^2.0.2: +esutils@^2.0.0, esutils@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b" -etag@~1.7.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/etag/-/etag-1.7.0.tgz#03d30b5f67dd6e632d2945d30d6652731a34d5d8" +etag@~1.8.1: + version "1.8.1" + resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" event-emitter@~0.3.5: version "0.3.5" @@ -2086,6 +2367,10 @@ event-target-shim@^1.0.5: version "1.1.1" resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-1.1.1.tgz#a86e5ee6bdaa16054475da797ccddf0c55698491" +eventemitter3@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-3.0.1.tgz#4ce66c3fc5b5a6b9f2245e359e1938f1ab10f960" + exec-sh@^0.2.0: version "0.2.1" resolved "https://registry.yarnpkg.com/exec-sh/-/exec-sh-0.2.1.tgz#163b98a6e89e6b65b47c2a28d215bc1f63989c38" @@ -2132,20 +2417,6 @@ expand-range@^1.8.1: dependencies: fill-range "^2.1.0" -express-session@~1.11.3: - version "1.11.3" - resolved "https://registry.yarnpkg.com/express-session/-/express-session-1.11.3.tgz#5cc98f3f5ff84ed835f91cbf0aabd0c7107400af" - dependencies: - cookie "0.1.3" - cookie-signature "1.0.6" - crc "3.3.0" - debug "~2.2.0" - depd "~1.0.1" - on-headers "~1.0.0" - parseurl "~1.3.0" - uid-safe "~2.0.0" - utils-merge "1.0.0" - extend@~3.0.0, extend@~3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.1.tgz#a755ea7bc1adfcc5a31ce7e762dbaadc5e636444" @@ -2257,13 +2528,16 @@ fill-range@^2.1.0: repeat-element "^1.1.2" repeat-string "^1.5.2" -finalhandler@0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-0.4.0.tgz#965a52d9e8d05d2b857548541fb89b53a2497d9b" +finalhandler@1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.0.tgz#ce0b6855b45853e791b2fcc680046d88253dd7f5" dependencies: - debug "~2.2.0" - escape-html "1.0.2" + debug "2.6.9" + encodeurl "~1.0.1" + escape-html "~1.0.3" on-finished "~2.3.0" + parseurl "~1.3.2" + statuses "~1.3.1" unpipe "~1.0.0" find-babel-config@^1.0.1: @@ -2344,9 +2618,9 @@ form-data@~2.3.1: combined-stream "^1.0.5" mime-types "^2.1.12" -fresh@0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.3.0.tgz#651f838e22424e7566de161d8358caa199f83d4f" +fresh@0.5.2: + version "0.5.2" + resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" from2@^1.3.0: version "1.3.0" @@ -2572,6 +2846,10 @@ global@^4.3.0: min-document "^2.19.0" process "~0.5.1" +globals@^11.1.0: + version "11.3.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-11.3.0.tgz#e04fdb7b9796d8adac9c8f64c14837b2313378b0" + globals@^9.14.0, globals@^9.18.0: version "9.18.0" resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a" @@ -2756,12 +3034,14 @@ http-cache-semantics@^3.8.0: version "3.8.1" resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz#39b0e16add9b605bf0a9ef3d9daaf4843b4cacd2" -http-errors@~1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.3.1.tgz#197e22cdebd4198585e8694ef6786197b91ed942" +http-errors@~1.6.2: + version "1.6.2" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.2.tgz#0a002cc85707192a7e7946ceedc11155f60ec736" dependencies: - inherits "~2.0.1" - statuses "1" + depd "1.1.1" + inherits "2.0.3" + setprototypeof "1.0.3" + statuses ">= 1.3.1 < 2" http-proxy-agent@^2.0.0: version "2.0.0" @@ -2799,14 +3079,6 @@ humanize-ms@^1.2.1: dependencies: ms "^2.0.0" -iconv-lite@0.4.11: - version "0.4.11" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.11.tgz#2ecb42fd294744922209a2e7c404dac8793d8ade" - -iconv-lite@0.4.13: - version "0.4.13" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.13.tgz#1f88aba4ab0b1508e8312acc39345f36e992e2f2" - iconv-lite@^0.4.17, iconv-lite@~0.4.13: version "0.4.19" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.19.tgz#f7468f60135f5e5dad3399c0a81be9a1603a082b" @@ -2838,7 +3110,7 @@ inflight@^1.0.4, inflight@~1.0.4, inflight@~1.0.6: once "^1.3.0" wrappy "1" -inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.0, inherits@~2.0.1, inherits@~2.0.3: +inherits@2, inherits@2.0.3, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.0, inherits@~2.0.1, inherits@~2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" @@ -2913,6 +3185,12 @@ interpret@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.1.0.tgz#7ed1b1410c6a0e0f78cf95d3b8440c63f78b8614" +invariant@^2.2.0: + version "2.2.4" + resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" + dependencies: + loose-envify "^1.0.0" + invariant@^2.2.2: version "2.2.2" resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.2.tgz#9e1f56ac0acdb6bf303306f338be3b204ae60360" @@ -3109,20 +3387,33 @@ isstream@~0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" -jest-docblock@^21, jest-docblock@^21.2.0: - version "21.2.0" - resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-21.2.0.tgz#51529c3b30d5fd159da60c27ceedc195faf8d414" +jest-docblock@22.4.0, jest-docblock@^22.4.0: + version "22.4.0" + resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-22.4.0.tgz#dbf1877e2550070cfc4d9b07a55775a0483159b8" + dependencies: + detect-newline "^2.1.0" -jest-haste-map@^21: - version "21.2.0" - resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-21.2.0.tgz#1363f0a8bb4338f24f001806571eff7a4b2ff3d8" +jest-haste-map@22.4.2: + version "22.4.2" + resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-22.4.2.tgz#a90178e66146d4378bb076345a949071f3b015b4" dependencies: fb-watchman "^2.0.0" graceful-fs "^4.1.11" - jest-docblock "^21.2.0" + jest-docblock "^22.4.0" + jest-serializer "^22.4.0" + jest-worker "^22.2.2" micromatch "^2.3.11" sane "^2.0.0" - worker-farm "^1.3.1" + +jest-serializer@^22.4.0: + version "22.4.0" + resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-22.4.0.tgz#b5d145b98c4b0d2c20ab686609adbb81fe23b566" + +jest-worker@22.2.2, jest-worker@^22.2.2: + version "22.2.2" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-22.2.2.tgz#c1f5dc39976884b81f68ec50cb8532b2cbab3390" + dependencies: + merge-stream "^1.0.1" js-tokens@^3.0.0, js-tokens@^3.0.2: version "3.0.2" @@ -3143,6 +3434,10 @@ jsesc@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b" +jsesc@^2.5.1: + version "2.5.1" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.1.tgz#e421a2a8e20d6b0819df28908f782526b96dd1fe" + jsesc@~0.5.0: version "0.5.0" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" @@ -3173,7 +3468,7 @@ json5@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/json5/-/json5-0.4.0.tgz#054352e4c4c80c86c0923877d449de176a732c8d" -json5@^0.5.1: +json5@^0.5.0, json5@^0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821" @@ -3413,6 +3708,10 @@ lodash.templatesettings@^3.0.0: lodash._reinterpolate "^3.0.0" lodash.escape "^3.0.0" +lodash.throttle@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/lodash.throttle/-/lodash.throttle-4.1.1.tgz#c23e91b710242ac70c37f1e1cda9274cc39bf2f4" + lodash.union@~4.6.0: version "4.6.0" resolved "https://registry.yarnpkg.com/lodash.union/-/lodash.union-4.6.0.tgz#48bb5088409f16f1821666641c44dd1aaae3cd88" @@ -3425,7 +3724,7 @@ lodash.without@~4.4.0: version "4.4.0" resolved "https://registry.yarnpkg.com/lodash.without/-/lodash.without-4.4.0.tgz#3cd4574a00b67bae373a94b748772640507b7aac" -lodash@4.17.4, lodash@^4.0.0, lodash@^4.14.0, lodash@^4.16.6, lodash@^4.17.2, lodash@^4.17.4, lodash@^4.3.0, lodash@^4.6.1: +lodash@4.17.4, lodash@^4.0.0, lodash@^4.14.0, lodash@^4.17.2, lodash@^4.17.4, lodash@^4.3.0, lodash@^4.6.1: version "4.17.4" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae" @@ -3433,6 +3732,10 @@ lodash@^3.5.0: version "3.10.1" resolved "https://registry.yarnpkg.com/lodash/-/lodash-3.10.1.tgz#5bf45e8e49ba4189e17d482789dfd15bd140b7b6" +lodash@^4.17.5, lodash@^4.2.0: + version "4.17.5" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.5.tgz#99a92d65c0272debe8c96b6057bc8fbfa3bed511" + loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.3.1.tgz#d1a8ad33fa9ce0e713d65fdd0ac8b748d478c848" @@ -3489,10 +3792,6 @@ makeerror@1.0.x: dependencies: tmpl "1.0.x" -media-typer@0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" - mem@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/mem/-/mem-1.1.0.tgz#5edd52b485ca1d900fe64895505399a0dfa45f76" @@ -3509,28 +3808,82 @@ merge@^1.1.3: version "1.2.0" resolved "https://registry.yarnpkg.com/merge/-/merge-1.2.0.tgz#7531e39d4949c281a66b8c5a6e0265e8b05894da" -method-override@~2.3.5: - version "2.3.10" - resolved "https://registry.yarnpkg.com/method-override/-/method-override-2.3.10.tgz#e3daf8d5dee10dd2dce7d4ae88d62bbee77476b4" +metro-babylon7@0.28.0: + version "0.28.0" + resolved "https://registry.yarnpkg.com/metro-babylon7/-/metro-babylon7-0.28.0.tgz#cf9701ffdc1992d1562b4cb667d9692164950df4" dependencies: - debug "2.6.9" - methods "~1.1.2" - parseurl "~1.3.2" - vary "~1.1.2" + babylon "^7.0.0-beta" -methods@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" +metro-cache@0.28.0: + version "0.28.0" + resolved "https://registry.yarnpkg.com/metro-cache/-/metro-cache-0.28.0.tgz#c5164a361985fc0294059fccdf4ea824e3173c1d" + dependencies: + jest-serializer "^22.4.0" + mkdirp "^0.5.1" + +metro-core@0.28.0, metro-core@^0.28.0: + version "0.28.0" + resolved "https://registry.yarnpkg.com/metro-core/-/metro-core-0.28.0.tgz#e1ced4cf07ca8fb5196a6e5ca853b5d893f06038" + dependencies: + lodash.throttle "^4.1.1" + +metro-minify-uglify@0.28.0: + version "0.28.0" + resolved "https://registry.yarnpkg.com/metro-minify-uglify/-/metro-minify-uglify-0.28.0.tgz#c9aecb8e893430d2fd58e00cf799c00b99dc0f79" + dependencies: + uglify-es "^3.1.9" -metro-bundler@^0.20.0: - version "0.20.3" - resolved "https://registry.yarnpkg.com/metro-bundler/-/metro-bundler-0.20.3.tgz#0ded01b64e8963117017b106f75b83cfc34f3656" +metro-resolver@0.28.0: + version "0.28.0" + resolved "https://registry.yarnpkg.com/metro-resolver/-/metro-resolver-0.28.0.tgz#813802d60fc762772927c81d02e01c7eec84bad8" dependencies: absolute-path "^0.0.0" + +metro-source-map@0.28.0: + version "0.28.0" + resolved "https://registry.yarnpkg.com/metro-source-map/-/metro-source-map-0.28.0.tgz#ec8c3161d8516ad3c4e7149f2c3d4802f4fd6fa2" + dependencies: + source-map "^0.5.6" + +metro@^0.28.0: + version "0.28.0" + resolved "https://registry.yarnpkg.com/metro/-/metro-0.28.0.tgz#22999c96c3129682a76acd4e1f2adc17f7d77cac" + dependencies: + "@babel/core" "^7.0.0-beta" + "@babel/generator" "^7.0.0-beta" + "@babel/helper-remap-async-to-generator" "^7.0.0-beta" + "@babel/plugin-check-constants" "^7.0.0-beta" + "@babel/plugin-external-helpers" "^7.0.0-beta" + "@babel/plugin-proposal-class-properties" "^7.0.0-beta" + "@babel/plugin-proposal-object-rest-spread" "^7.0.0-beta" + "@babel/plugin-syntax-dynamic-import" "^7.0.0-beta" + "@babel/plugin-transform-arrow-functions" "^7.0.0-beta" + "@babel/plugin-transform-block-scoping" "^7.0.0-beta" + "@babel/plugin-transform-classes" "^7.0.0-beta" + "@babel/plugin-transform-computed-properties" "^7.0.0-beta" + "@babel/plugin-transform-destructuring" "^7.0.0-beta" + "@babel/plugin-transform-flow-strip-types" "^7.0.0-beta" + "@babel/plugin-transform-for-of" "^7.0.0-beta" + "@babel/plugin-transform-function-name" "^7.0.0-beta" + "@babel/plugin-transform-literals" "^7.0.0-beta" + "@babel/plugin-transform-modules-commonjs" "^7.0.0-beta" + "@babel/plugin-transform-object-assign" "^7.0.0-beta" + "@babel/plugin-transform-parameters" "^7.0.0-beta" + "@babel/plugin-transform-react-display-name" "^7.0.0-beta" + "@babel/plugin-transform-react-jsx" "^7.0.0-beta" + "@babel/plugin-transform-react-jsx-source" "^7.0.0-beta" + "@babel/plugin-transform-regenerator" "^7.0.0-beta" + "@babel/plugin-transform-shorthand-properties" "^7.0.0-beta" + "@babel/plugin-transform-spread" "^7.0.0-beta" + "@babel/plugin-transform-template-literals" "^7.0.0-beta" + "@babel/template" "^7.0.0-beta" + "@babel/traverse" "^7.0.0-beta" + "@babel/types" "^7.0.0-beta" + absolute-path "^0.0.0" async "^2.4.0" babel-core "^6.24.1" - babel-generator "^6.24.1" - babel-plugin-external-helpers "^6.18.0" + babel-generator "^6.26.0" + babel-plugin-external-helpers "^6.22.0" babel-preset-es2015-node "^6.1.1" babel-preset-fbjs "^2.1.4" babel-preset-react-native "^4.0.0" @@ -3538,30 +3891,42 @@ metro-bundler@^0.20.0: babylon "^6.18.0" chalk "^1.1.1" concat-stream "^1.6.0" + connect "^3.6.5" core-js "^2.2.2" debug "^2.2.0" denodeify "^1.2.1" + eventemitter3 "^3.0.0" fbjs "^0.8.14" + fs-extra "^1.0.0" graceful-fs "^4.1.3" image-size "^0.6.0" - jest-docblock "^21" - jest-haste-map "^21" + jest-docblock "22.4.0" + jest-haste-map "22.4.2" + jest-worker "22.2.2" json-stable-stringify "^1.0.1" json5 "^0.4.0" left-pad "^1.1.3" - lodash "^4.16.6" + lodash.throttle "^4.1.1" merge-stream "^1.0.1" + metro-babylon7 "0.28.0" + metro-cache "0.28.0" + metro-core "0.28.0" + metro-minify-uglify "0.28.0" + metro-resolver "0.28.0" + metro-source-map "0.28.0" mime-types "2.1.11" mkdirp "^0.5.1" request "^2.79.0" rimraf "^2.5.4" + serialize-error "^2.1.0" source-map "^0.5.6" temp "0.8.3" throat "^4.1.0" - uglify-es "^3.1.8" wordwrap "^1.0.0" write-file-atomic "^1.2.0" + ws "^1.1.0" xpipe "^1.0.5" + yargs "^9.0.0" micromatch@^2.1.5, micromatch@^2.3.11: version "2.3.11" @@ -3581,9 +3946,9 @@ micromatch@^2.1.5, micromatch@^2.3.11: parse-glob "^3.0.4" regex-cache "^0.4.2" -"mime-db@>= 1.30.0 < 2": - version "1.32.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.32.0.tgz#485b3848b01a3cda5f968b4882c0771e58e09414" +"mime-db@>= 1.33.0 < 2", mime-db@~1.33.0: + version "1.33.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.33.0.tgz#a3492050a5cb9b63450541e39d9788d2272783db" mime-db@~1.23.0: version "1.23.0" @@ -3599,15 +3964,21 @@ mime-types@2.1.11: dependencies: mime-db "~1.23.0" -mime-types@^2.1.11, mime-types@^2.1.12, mime-types@~2.1.15, mime-types@~2.1.16, mime-types@~2.1.17, mime-types@~2.1.6, mime-types@~2.1.7, mime-types@~2.1.9: +mime-types@^2.1.11, mime-types@^2.1.12, mime-types@~2.1.17, mime-types@~2.1.7: version "2.1.17" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.17.tgz#09d7a393f03e995a79f8af857b70a9e0ab16557a" dependencies: mime-db "~1.30.0" -mime@1.3.4: - version "1.3.4" - resolved "https://registry.yarnpkg.com/mime/-/mime-1.3.4.tgz#115f9e3b6b3daf2959983cb38f149a2d40eb5d53" +mime-types@~2.1.18: + version "2.1.18" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.18.tgz#6f323f60a83d11146f831ff11fd66e2fe5503bb8" + dependencies: + mime-db "~1.33.0" + +mime@1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/mime/-/mime-1.4.1.tgz#121f9ebc49e3766f311a76e1fa1c8003c4b03aa6" mime@^1.3.4: version "1.6.0" @@ -3662,15 +4033,15 @@ mississippi@^1.2.0, mississippi@^1.3.0, mississippi@~1.3.0: dependencies: minimist "0.0.8" -morgan@~1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/morgan/-/morgan-1.6.1.tgz#5fd818398c6819cba28a7cd6664f292fe1c0bbf2" +morgan@^1.9.0: + version "1.9.0" + resolved "https://registry.yarnpkg.com/morgan/-/morgan-1.9.0.tgz#d01fa6c65859b76fcf31b3cb53a3821a311d8051" dependencies: - basic-auth "~1.0.3" - debug "~2.2.0" - depd "~1.0.1" + basic-auth "~2.0.0" + debug "2.6.9" + depd "~1.1.1" on-finished "~2.3.0" - on-headers "~1.0.0" + on-headers "~1.0.1" move-concurrently@^1.0.1, move-concurrently@~1.0.1: version "1.0.1" @@ -3683,14 +4054,6 @@ move-concurrently@^1.0.1, move-concurrently@~1.0.1: rimraf "^2.5.4" run-queue "^1.0.3" -ms@0.7.1: - version "0.7.1" - resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.1.tgz#9cd13c03adbff25b65effde7ce864ee952017098" - -ms@0.7.2: - version "0.7.2" - resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.2.tgz#ae25cf2512b3885a1d95d7f037868d8431124765" - ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" @@ -3699,13 +4062,6 @@ ms@^2.0.0: version "2.1.1" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" -multiparty@3.3.2: - version "3.3.2" - resolved "https://registry.yarnpkg.com/multiparty/-/multiparty-3.3.2.tgz#35de6804dc19643e5249f3d3e3bdc6c8ce301d3f" - dependencies: - readable-stream "~1.1.9" - stream-counter "~0.2.0" - multipipe@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/multipipe/-/multipipe-0.1.2.tgz#2a8f2ddf70eed564dff2d57f1e1a137d9f05078b" @@ -3728,10 +4084,6 @@ natural-compare@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" -negotiator@0.5.3: - version "0.5.3" - resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.5.3.tgz#269d5c476810ec92edbe7b6c2f28316384f9a7e8" - negotiator@0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.1.tgz#2b327184e8992101177b28563fb5e7102acd0ca9" @@ -4177,7 +4529,7 @@ on-finished@~2.3.0: dependencies: ee-first "1.1.1" -on-headers@~1.0.0, on-headers@~1.0.1: +on-headers@~1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.1.tgz#928f5d0f470d49342651ea6794b0857c100693f7" @@ -4337,7 +4689,7 @@ parse-json@^2.2.0: dependencies: error-ex "^1.2.0" -parseurl@~1.3.0, parseurl@~1.3.1, parseurl@~1.3.2: +parseurl@~1.3.2: version "1.3.2" resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.2.tgz#fc289d4ed8993119460c156253262cdc8de65bf3" @@ -4373,10 +4725,6 @@ path-type@^2.0.0: dependencies: pify "^2.0.0" -pause@0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/pause/-/pause-0.1.0.tgz#ebc8a4a8619ff0b8a81ac1513c3434ff469fdb74" - pegjs@^0.10.0: version "0.10.0" resolved "https://registry.yarnpkg.com/pegjs/-/pegjs-0.10.0.tgz#cf8bafae6eddff4b5a7efb185269eaaf4610ddbd" @@ -4551,10 +4899,6 @@ q@1.5.0: version "1.5.0" resolved "https://registry.yarnpkg.com/q/-/q-1.5.0.tgz#dd01bac9d06d30e6f219aecb8253ee9ebdc308f1" -qs@4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/qs/-/qs-4.0.0.tgz#c31d9b74ec27df75e543a86c78728ed8d4623607" - qs@~6.2.0: version "6.2.3" resolved "https://registry.yarnpkg.com/qs/-/qs-6.2.3.tgz#1cfcb25c10a9b2b483053ff39f5dfc9233908cfe" @@ -4567,10 +4911,6 @@ qs@~6.5.1: version "6.5.1" resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.1.tgz#349cdf6eef89ec45c12d7d5eb3fc0c870343a6d8" -random-bytes@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/random-bytes/-/random-bytes-1.0.0.tgz#4f68a1dc0ae58bd3fb95848c30324db75d64360b" - randomatic@^1.1.3: version "1.1.7" resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-1.1.7.tgz#c7abe9cc8b87c0baa876b19fde83fd464797e38c" @@ -4578,17 +4918,9 @@ randomatic@^1.1.3: is-number "^3.0.0" kind-of "^4.0.0" -range-parser@~1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.0.3.tgz#6872823535c692e2c2a0103826afd82c2e0ff175" - -raw-body@~2.1.2: - version "2.1.7" - resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.1.7.tgz#adfeace2e4fb3098058014d08c072dcc59758774" - dependencies: - bytes "2.4.0" - iconv-lite "0.4.13" - unpipe "1.0.0" +range-parser@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e" rc@^1.0.1, rc@^1.1.6, rc@^1.1.7: version "1.2.4" @@ -4607,16 +4939,16 @@ react-deep-force-update@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/react-deep-force-update/-/react-deep-force-update-1.1.1.tgz#bcd31478027b64b3339f108921ab520b4313dc2c" -react-devtools-core@^2.5.0: - version "2.5.2" - resolved "https://registry.yarnpkg.com/react-devtools-core/-/react-devtools-core-2.5.2.tgz#f97bec5afae5d9318d16778065e0c214c4d5714c" +react-devtools-core@3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/react-devtools-core/-/react-devtools-core-3.1.0.tgz#eec2e9e0e6edb77772e2bfc7d286a296f55a261a" dependencies: shell-quote "^1.6.1" ws "^2.0.3" -react-native@0.51.0: - version "0.51.0" - resolved "https://registry.yarnpkg.com/react-native/-/react-native-0.51.0.tgz#fe25934b3030fd323f3ca1a70f034133465955ed" +react-native@^0.54: + version "0.54.2" + resolved "https://registry.yarnpkg.com/react-native/-/react-native-0.54.2.tgz#73786e7bf3f80b0b060ca0bfe5b192f9c2f253da" dependencies: absolute-path "^0.0.0" art "^0.10.0" @@ -4632,11 +4964,13 @@ react-native@0.51.0: base64-js "^1.1.2" chalk "^1.1.1" commander "^2.9.0" - connect "^2.8.3" - create-react-class "^15.5.2" + compression "^1.7.1" + connect "^3.6.5" + create-react-class "^15.6.3" debug "^2.2.0" denodeify "^1.2.1" envinfo "^3.0.0" + errorhandler "^1.5.0" event-target-shim "^1.0.5" fbjs "^0.8.14" fbjs-scripts "^0.8.1" @@ -4644,11 +4978,13 @@ react-native@0.51.0: glob "^7.1.1" graceful-fs "^4.1.3" inquirer "^3.0.6" - lodash "^4.16.6" - metro-bundler "^0.20.0" + lodash "^4.17.5" + metro "^0.28.0" + metro-core "^0.28.0" mime "^1.3.4" minimist "^1.2.0" mkdirp "^0.5.1" + morgan "^1.9.0" node-fetch "^1.3.3" node-notifier "^5.1.2" npmlog "^2.0.4" @@ -4659,11 +4995,12 @@ react-native@0.51.0: promise "^7.1.1" prop-types "^15.5.8" react-clone-referenced-element "^1.0.1" - react-devtools-core "^2.5.0" + react-devtools-core "3.1.0" react-timer-mixin "^0.13.2" regenerator-runtime "^0.11.0" rimraf "^2.5.4" semver "^5.0.3" + serve-static "^1.13.1" shell-quote "1.6.1" stacktrace-parser "^0.1.3" whatwg-fetch "^1.0.0" @@ -4690,9 +5027,9 @@ react-transform-hmr@^1.0.4: global "^4.3.0" react-proxy "^1.1.7" -react@16.0.0: - version "16.0.0" - resolved "https://registry.yarnpkg.com/react/-/react-16.0.0.tgz#ce7df8f1941b036f02b2cca9dbd0cb1f0e855e2d" +react@^16.3.0-alpha.1: + version "16.3.0-alpha.2" + resolved "https://registry.yarnpkg.com/react/-/react-16.3.0-alpha.2.tgz#91e2b82bb985b23e7b6555f810e1fd94894afce2" dependencies: fbjs "^0.8.16" loose-envify "^1.1.0" @@ -4772,7 +5109,7 @@ read@1, read@~1.0.1, read@~1.0.7: string_decoder "~1.0.3" util-deprecate "~1.0.1" -readable-stream@~1.1.10, readable-stream@~1.1.8, readable-stream@~1.1.9: +readable-stream@~1.1.10, readable-stream@~1.1.9: version "1.1.14" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9" dependencies: @@ -4850,6 +5187,12 @@ regenerator-transform@^0.10.0: babel-types "^6.19.0" private "^0.1.6" +regenerator-transform@^0.12.3: + version "0.12.3" + resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.12.3.tgz#459adfb64f6a27164ab991b7873f45ab969eca8b" + dependencies: + private "^0.1.6" + regex-cache@^0.4.2: version "0.4.4" resolved "https://registry.yarnpkg.com/regex-cache/-/regex-cache-0.4.4.tgz#75bdc58a2a1496cec48a12835bc54c8d562336dd" @@ -5014,12 +5357,11 @@ resolve@^1.1.6, resolve@^1.2.0: dependencies: path-parse "^1.0.5" -response-time@~2.3.1: - version "2.3.2" - resolved "https://registry.yarnpkg.com/response-time/-/response-time-2.3.2.tgz#ffa71bab952d62f7c1d49b7434355fbc68dffc5a" +resolve@^1.3.2: + version "1.6.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.6.0.tgz#0fbd21278b27b4004481c395349e7aba60a9ff5c" dependencies: - depd "~1.1.0" - on-headers "~1.0.1" + path-parse "^1.0.5" restore-cursor@^1.0.1: version "1.0.1" @@ -5055,10 +5397,6 @@ rimraf@~2.5.4: dependencies: glob "^7.0.5" -rndm@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/rndm/-/rndm-1.2.0.tgz#f33fe9cfb52bbfd520aa18323bc65db110a1b76c" - run-async@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/run-async/-/run-async-0.1.0.tgz#c8ad4a5e110661e402a7d21b530e009f25f8e389" @@ -5091,7 +5429,7 @@ rx-lite@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-3.1.2.tgz#19ce502ca572665f3b647b10939f97fd1615f102" -safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@~5.1.0, safe-buffer@~5.1.1: +safe-buffer@5.1.1, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853" @@ -5139,51 +5477,36 @@ semver@~5.1.0: version "5.1.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.1.1.tgz#a3292a373e6f3e0798da0b20641b9a9c5bc47e19" -send@0.13.2: - version "0.13.2" - resolved "https://registry.yarnpkg.com/send/-/send-0.13.2.tgz#765e7607c8055452bba6f0b052595350986036de" +send@0.16.2: + version "0.16.2" + resolved "https://registry.yarnpkg.com/send/-/send-0.16.2.tgz#6ecca1e0f8c156d141597559848df64730a6bbc1" dependencies: - debug "~2.2.0" - depd "~1.1.0" + debug "2.6.9" + depd "~1.1.2" destroy "~1.0.4" + encodeurl "~1.0.2" escape-html "~1.0.3" - etag "~1.7.0" - fresh "0.3.0" - http-errors "~1.3.1" - mime "1.3.4" - ms "0.7.1" + etag "~1.8.1" + fresh "0.5.2" + http-errors "~1.6.2" + mime "1.4.1" + ms "2.0.0" on-finished "~2.3.0" - range-parser "~1.0.3" - statuses "~1.2.1" + range-parser "~1.2.0" + statuses "~1.4.0" -serve-favicon@~2.3.0: - version "2.3.2" - resolved "https://registry.yarnpkg.com/serve-favicon/-/serve-favicon-2.3.2.tgz#dd419e268de012ab72b319d337f2105013f9381f" - dependencies: - etag "~1.7.0" - fresh "0.3.0" - ms "0.7.2" - parseurl "~1.3.1" - -serve-index@~1.7.2: - version "1.7.3" - resolved "https://registry.yarnpkg.com/serve-index/-/serve-index-1.7.3.tgz#7a057fc6ee28dc63f64566e5fa57b111a86aecd2" - dependencies: - accepts "~1.2.13" - batch "0.5.3" - debug "~2.2.0" - escape-html "~1.0.3" - http-errors "~1.3.1" - mime-types "~2.1.9" - parseurl "~1.3.1" +serialize-error@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/serialize-error/-/serialize-error-2.1.0.tgz#50b679d5635cdf84667bdc8e59af4e5b81d5f60a" -serve-static@~1.10.0: - version "1.10.3" - resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.10.3.tgz#ce5a6ecd3101fed5ec09827dac22a9c29bfb0535" +serve-static@^1.13.1: + version "1.13.2" + resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.13.2.tgz#095e8472fd5b46237db50ce486a43f4b86c6cec1" dependencies: + encodeurl "~1.0.2" escape-html "~1.0.3" - parseurl "~1.3.1" - send "0.13.2" + parseurl "~1.3.2" + send "0.16.2" set-blocking@^2.0.0, set-blocking@~2.0.0: version "2.0.0" @@ -5193,6 +5516,10 @@ setimmediate@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" +setprototypeof@1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.0.3.tgz#66567e37043eeb4f04d91bd658c0cbefb55b8e04" + sha@~2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/sha/-/sha-2.0.1.tgz#6030822fbd2c9823949f8f72ed6411ee5cf25aae" @@ -5302,7 +5629,7 @@ source-map-support@^0.4.15: dependencies: source-map "^0.5.6" -source-map@^0.5.6: +source-map@^0.5.0, source-map@^0.5.6: version "0.5.7" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" @@ -5362,24 +5689,18 @@ stacktrace-parser@^0.1.3: version "0.1.4" resolved "https://registry.yarnpkg.com/stacktrace-parser/-/stacktrace-parser-0.1.4.tgz#01397922e5f62ecf30845522c95c4fe1d25e7d4e" -statuses@1: +"statuses@>= 1.3.1 < 2", statuses@~1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.4.0.tgz#bb73d446da2796106efcc1b601a253d6c46bd087" -statuses@~1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.2.1.tgz#dded45cc18256d51ed40aec142489d5c61026d28" +statuses@~1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.3.1.tgz#faf51b9eb74aaef3b3acf4ad5f61abf24cb7b93e" stream-buffers@~2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/stream-buffers/-/stream-buffers-2.2.0.tgz#91d5f5130d1cef96dcfa7f726945188741d09ee4" -stream-counter@~0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/stream-counter/-/stream-counter-0.2.0.tgz#ded266556319c8b0e222812b9cf3b26fa7d947de" - dependencies: - readable-stream "~1.1.8" - stream-each@^1.1.0: version "1.2.2" resolved "https://registry.yarnpkg.com/stream-each/-/stream-each-1.2.2.tgz#8e8c463f91da8991778765873fe4d960d8f616bd" @@ -5571,6 +5892,10 @@ to-fast-properties@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47" +to-fast-properties@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" + tough-cookie@~2.3.0, tough-cookie@~2.3.3: version "2.3.3" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.3.tgz#0b618a5565b6dea90bf3425d04d55edc475a7561" @@ -5581,10 +5906,6 @@ trim-right@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" -tsscmp@1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/tsscmp/-/tsscmp-1.0.5.tgz#7dc4a33af71581ab4337da91d85ca5427ebd9a97" - tunnel-agent@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" @@ -5605,13 +5926,6 @@ type-check@~0.3.2: dependencies: prelude-ls "~1.1.2" -type-is@~1.6.6: - version "1.6.15" - resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.15.tgz#cab10fb4909e441c82842eafe1ad646c81804410" - dependencies: - media-typer "0.3.0" - mime-types "~2.1.15" - typedarray@^0.0.6: version "0.0.6" resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" @@ -5620,9 +5934,9 @@ ua-parser-js@^0.7.9: version "0.7.17" resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.17.tgz#e9ec5f9498b9ec910e7ae3ac626a805c4d09ecac" -uglify-es@^3.1.8: - version "3.3.8" - resolved "https://registry.yarnpkg.com/uglify-es/-/uglify-es-3.3.8.tgz#f2c68e6cff0d0f9dc9577e4da207151c2e753b7e" +uglify-es@^3.1.9: + version "3.3.9" + resolved "https://registry.yarnpkg.com/uglify-es/-/uglify-es-3.3.9.tgz#0c1c4f0700bed8dbc124cdb304d2592ca203e677" dependencies: commander "~2.13.0" source-map "~0.6.1" @@ -5631,18 +5945,6 @@ uid-number@0.0.6, uid-number@^0.0.6: version "0.0.6" resolved "https://registry.yarnpkg.com/uid-number/-/uid-number-0.0.6.tgz#0ea10e8035e8eb5b8e4449f06da1c730663baa81" -uid-safe@2.1.4: - version "2.1.4" - resolved "https://registry.yarnpkg.com/uid-safe/-/uid-safe-2.1.4.tgz#3ad6f38368c6d4c8c75ec17623fb79aa1d071d81" - dependencies: - random-bytes "~1.0.0" - -uid-safe@~2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/uid-safe/-/uid-safe-2.0.0.tgz#a7f3c6ca64a1f6a5d04ec0ef3e4c3d5367317137" - dependencies: - base64-url "1.2.1" - ultron@1.0.x: version "1.0.2" resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.0.2.tgz#ace116ab557cd197386a4e88f4685378c8b2e4fa" @@ -5677,7 +5979,7 @@ universalify@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.1.tgz#fa71badd4437af4c148841e3b3b165f9e9e590b7" -unpipe@1.0.0, unpipe@~1.0.0: +unpipe@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" @@ -5718,9 +6020,9 @@ util-extend@^1.0.1: version "1.0.3" resolved "https://registry.yarnpkg.com/util-extend/-/util-extend-1.0.3.tgz#a7c216d267545169637b3b6edc6ca9119e2ff93f" -utils-merge@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.0.tgz#0294fb922bb9375153541c4f7096231f287c8af8" +utils-merge@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" uuid@3.0.1: version "3.0.1" @@ -5753,10 +6055,6 @@ validate-npm-package-name@~2.2.2: dependencies: builtins "0.0.7" -vary@~1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/vary/-/vary-1.0.1.tgz#99e4981566a286118dfb2b817357df7993376d10" - vary@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" @@ -5769,10 +6067,6 @@ verror@1.10.0: core-util-is "1.0.2" extsprintf "^1.2.0" -vhost@~3.0.1: - version "3.0.2" - resolved "https://registry.yarnpkg.com/vhost/-/vhost-3.0.2.tgz#2fb1decd4c466aa88b0f9341af33dc1aff2478d5" - vinyl@^0.5.0: version "0.5.3" resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-0.5.3.tgz#b0455b38fc5e0cf30d4325132e461970c2091cde" @@ -5850,13 +6144,6 @@ wordwrap@~0.0.2: version "0.0.3" resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107" -worker-farm@^1.3.1: - version "1.5.2" - resolved "https://registry.yarnpkg.com/worker-farm/-/worker-farm-1.5.2.tgz#32b312e5dc3d5d45d79ef44acc2587491cd729ae" - dependencies: - errno "^0.1.4" - xtend "^4.0.1" - worker-farm@~1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/worker-farm/-/worker-farm-1.3.1.tgz#4333112bb49b17aa050b87895ca6b2cacf40e5ff" @@ -5963,7 +6250,7 @@ xpipe@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/xpipe/-/xpipe-1.0.5.tgz#8dd8bf45fc3f7f55f0e054b878f43a62614dafdf" -"xtend@>=4.0.0 <4.1.0-0", xtend@^4.0.0, xtend@^4.0.1, xtend@~4.0.1: +"xtend@>=4.0.0 <4.1.0-0", xtend@^4.0.0, xtend@~4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" From d0cbac6f0971cafac0010ea724f9b66589fbafbb Mon Sep 17 00:00:00 2001 From: Harry Lachenmayer Date: Wed, 28 Mar 2018 15:00:35 +0200 Subject: [PATCH 0442/1148] Fix initialRegion when using RN 0.54 (#2131) * Fix initialRegion being zoomed out as described in https://github.com/react-community/react-native-maps/issues/2100 * Start ignoring setInitialRegion calls once the map view is in the window rather than when the map is ready --- lib/ios/AirGoogleMaps/AIRGoogleMap.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ios/AirGoogleMaps/AIRGoogleMap.m b/lib/ios/AirGoogleMaps/AIRGoogleMap.m index dd8b4e344..521143a54 100644 --- a/lib/ios/AirGoogleMaps/AIRGoogleMap.m +++ b/lib/ios/AirGoogleMaps/AIRGoogleMap.m @@ -199,7 +199,7 @@ - (void)didMoveToWindow { - (void)setInitialRegion:(MKCoordinateRegion)initialRegion { if (_initialRegionSetOnLoad) return; _initialRegion = initialRegion; - _initialRegionSetOnLoad = true; + _initialRegionSetOnLoad = _didMoveToWindow; self.camera = [AIRGoogleMap makeGMSCameraPositionFromMap:self andMKCoordinateRegion:initialRegion]; } From ede2bdce9763acd46f97588179ad3954cc5c5cbe Mon Sep 17 00:00:00 2001 From: RalfNieuwenhuizen Date: Fri, 30 Mar 2018 16:14:32 +0200 Subject: [PATCH 0443/1148] Add takeSnapshot method to MapView (#2141) According to specs at https://github.com/react-community/react-native-maps#take-snapshot-of-map --- index.d.ts | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/index.d.ts b/index.d.ts index d73a9775e..6b15f0f45 100644 --- a/index.d.ts +++ b/index.d.ts @@ -104,8 +104,9 @@ declare module "react-native-maps" { animateToViewingAngle(angle: number, duration?: number): void; fitToElements(animated: boolean): void; fitToSuppliedMarkers(markers: string[], animated: boolean): void; - fitToCoordinates(coordinates?: LatLng[], options?:{}): void; + fitToCoordinates(coordinates?: LatLng[], options?: {}): void; setMapBoundaries(northEast: LatLng, southWest: LatLng): void; + takeSnapshot(options?: SnapshotOptions): Promise; } export class MapViewAnimated extends React.Component { @@ -115,8 +116,18 @@ declare module "react-native-maps" { animateToViewingAngle(angle: number, duration?: number): void; fitToElements(animated: boolean): void; fitToSuppliedMarkers(markers: string[], animated: boolean): void; - fitToCoordinates(coordinates?: LatLng[], options?:{}): void; + fitToCoordinates(coordinates?: LatLng[], options?: {}): void; setMapBoundaries(northEast: LatLng, southWest: LatLng): void; + takeSnapshot(options?: SnapshotOptions): Promise; + } + + export interface SnapshotOptions { + width?: number; // optional, when omitted the view-width is used + height?: number; // optional, when omitted the view-height is used + region?: Region; // iOS only, optional region to render + format?: 'png' | 'jpg'; // image formats: 'png', 'jpg' (default: 'png') + quality?: number; // image quality: 0..1 (only relevant for jpg, default: 1) + result?: 'file' | 'base64'; // result types: 'file', 'base64' (default: 'file') } export type LineCapType = 'butt' | 'round' | 'square'; From c53ff0ad2632a049b6e6a25b7b304005e4f9791e Mon Sep 17 00:00:00 2001 From: Will Battel Date: Sun, 1 Apr 2018 13:06:11 -0400 Subject: [PATCH 0444/1148] v0.21.0 (#2146) * Bump version to 0.21.0 * v0.21.0 * v0.21.0 * v0.21.0 --- CHANGELOG.md | 20 ++++++++++++++++++-- example/ios/Podfile.lock | 4 ++-- lib/android/gradle.properties | 2 +- package.json | 2 +- 4 files changed, 22 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b1cefacd8..4793ed145 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,22 @@ # Change Log -## Unreleased -* Android: Check for presence of Gradle configuration properties that may have been defined by the hosting `rootProject`: `compileSdkVersion`, `buildToolsVersion`, `googlePlayServicesVersion`, `androidMapsUtilsVersion`. This provides a better mechanism for aligning the requirements of the module with that of the host project. +## 0.21.0 (March 31, 2018) +* Common: [#2030](https://github.com/react-community/react-native-maps/pull/2030) Broadened peer-dependency support +* Common: [#2035](https://github.com/react-community/react-native-maps/pull/2035), [#2113](https://github.com/react-community/react-native-maps/pull/2113), & [#2141](https://github.com/react-community/react-native-maps/pull/2141) Typescript improvements and fixes +* Common: [#2011](https://github.com/react-community/react-native-maps/pull/2011) Add suport for KML file (Only Markers) +* Common: [#2053](https://github.com/react-community/react-native-maps/pull/2053) Fix 'module undefined' for React Native >= 0.54 +* Common: [#2131](https://github.com/react-community/react-native-maps/pull/2131) Fix initialRegion for React Native >= 0.54 +* Common: [#2115](https://github.com/react-community/react-native-maps/pull/2115) Upgrade React Native peer dependency to 0.54 +* Common: [#2032](https://github.com/react-community/react-native-maps/pull/2032) Add onMyLocationChange event +* Common: [#2039](https://github.com/react-community/react-native-maps/pull/2039) Fixed problem with pointForCoordinate and coordinateForPoint methods +* Common: [#2050](https://github.com/react-community/react-native-maps/pull/2050) Add support for onPoiClick +* iOS: [#2022](https://github.com/react-community/react-native-maps/pull/2022) Add support for Map.Overlay +* iOS: [#2068](https://github.com/react-community/react-native-maps/pull/2068) Prevent marker press from calling MapView onPress +* iOS: [#2057](https://github.com/react-community/react-native-maps/pull/2057) Fixed polygon and polyline not re-rendering when changing tile URL (AirMaps) +* iOS: [#2101](https://github.com/react-community/react-native-maps/pull/2101) Fixed re-render not updating MapView.Circle component in UI when radius or center coordinates change (AirMaps) +* Android: [#2111](https://github.com/react-community/react-native-maps/pull/2111) Allow vector drawables to be used as markers +* Android: [#2132](https://github.com/react-community/react-native-maps/pull/2132) Add mock-provider boolean on each location update +* Android: [#2047](https://github.com/react-community/react-native-maps/pull/2047) Check for presence of project-wide (ext) Gradle configuration properties `compileSdkVersion`, `targetSdkVersion`, `buildToolsVersion`, `supportLibVersion`, `googlePlayServicesVersion`, and `androidMapsUtilsVersion`. This provides a better mechanism for aligning the requirements of the module with that of the host project. +* Android: [#2096](https://github.com/react-community/react-native-maps/pull/2096) Updated gradle configuration for gradle 3.0.0+ ## 0.20.1 (February 13, 2018) * Common: [hotfix PROVIDER_GOOGLE](https://github.com/react-community/react-native-maps/commit/cd868ea7b33a04c8bdd5e909cf134a133b2cb316) diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index a9a39c43d..43e7bb712 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -29,11 +29,11 @@ PODS: - GoogleMaps/Base - React (0.54.2): - React/Core (= 0.54.2) - - react-native-google-maps (0.20.1): + - react-native-google-maps (0.21.0): - Google-Maps-iOS-Utils (= 2.1.0) - GoogleMaps (= 2.5.0) - React - - react-native-maps (0.20.1): + - react-native-maps (0.21.0): - React - React/Core (0.54.2): - yoga (= 0.54.2.React) diff --git a/lib/android/gradle.properties b/lib/android/gradle.properties index ee59d1038..f9aa44da0 100644 --- a/lib/android/gradle.properties +++ b/lib/android/gradle.properties @@ -1,5 +1,5 @@ VERSION_CODE=4 -VERSION_NAME=0.20.1 +VERSION_NAME=0.21.0 GROUP=com.airbnb.android POM_DESCRIPTION=React Native Map view component for Android diff --git a/package.json b/package.json index 0b8c1311a..1f58b945e 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "description": "React Native Mapview component for iOS + Android", "main": "index.js", "author": "Leland Richardson ", - "version": "0.20.1", + "version": "0.21.0", "scripts": { "start": "node node_modules/react-native/local-cli/cli.js start", "run:packager": "./node_modules/react-native/packager/packager.sh", From 515a99c1f75690a0120f6ceb19362b42635de76c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alberto=20Mart=C3=ADnez?= Date: Thu, 5 Apr 2018 04:29:27 -0500 Subject: [PATCH 0445/1148] Typings for v0.21.0 (#2165) --- index.d.ts | 400 +++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 283 insertions(+), 117 deletions(-) diff --git a/index.d.ts b/index.d.ts index 6b15f0f45..044c05082 100644 --- a/index.d.ts +++ b/index.d.ts @@ -1,25 +1,63 @@ declare module "react-native-maps" { + import * as React from 'react'; - import { Animated } from 'react-native'; + import { + Animated, + ImageRequireSource, + ImageURISource, + NativeSyntheticEvent, + ViewProperties + } from 'react-native'; export interface Region { - latitude: number - longitude: number - latitudeDelta: number - longitudeDelta: number + latitude: number; + longitude: number; + latitudeDelta: number; + longitudeDelta: number; } export interface LatLng { - latitude: number - longitude: number + latitude: number; + longitude: number; } export interface Point { - x: number - y: number + x: number; + y: number; + } + + // helper interface + export interface MapEvent extends NativeSyntheticEvent {} + + export type LineCapType = 'butt' | 'round' | 'square'; + export type LineJoinType = 'miter' | 'round' | 'bevel'; + + // ======================================================================= + // AnimatedRegion + // ======================================================================= + + interface AnimatedRegionTimingConfig extends Animated.AnimationConfig, Partial { + easing?: (value: number) => number; + duration?: number; + delay?: number; } - export type Coordinate = Number[]; + interface AnimatedRegionSpringConfig extends Animated.AnimationConfig, Partial { + overshootClamping?: boolean; + restDisplacementThreshold?: number; + restSpeedThreshold?: number; + velocity?: number | Point; + bounciness?: number; + speed?: number; + tension?: number; + friction?: number; + stiffness?: number; + mass?: number; + damping?: number; + } export class AnimatedRegion extends Animated.AnimatedWithChildren { latitude: Animated.Value @@ -27,25 +65,100 @@ declare module "react-native-maps" { latitudeDelta: Animated.Value longitudeDelta: Animated.Value - constructor(region: Region); + constructor(region?: Region); setValue(value: Region): void; setOffset(offset: Region): void; flattenOffset(): void; - __getValue(): Region; - __attach(): void; - __detach(): void; - stopAnimation(callback?: Function): void; - addListener(callback: Function): string; + stopAnimation(callback?: (region: Region) => void): void; + addListener(callback: (region: Region) => void): string; removeListener(id: string): void; - spring(config: any): any; - timing(config: any): any; + spring(config: AnimatedRegionSpringConfig): Animated.CompositeAnimation; + timing(config: AnimatedRegionTimingConfig): Animated.CompositeAnimation; + } + + // ======================================================================= + // MapView (default export) + // ======================================================================= + + /** + * takeSnapshot options + */ + export interface SnapshotOptions { + /** optional, when omitted the view-width is used */ + width?: number; + /** optional, when omitted the view-height is used */ + height?: number; + /** __iOS only__, optional region to render */ + region?: Region; + /** image formats, defaults to 'png' */ + format?: 'png' | 'jpg'; + /** image quality: 0..1 (only relevant for jpg, default: 1) */ + quality?: number; + /** result types, defaults to 'file' */ + result?: 'file' | 'base64'; + } + + /** + * onUserLocationChange parameters + */ + export interface EventUserLocation extends NativeSyntheticEvent<{}> { + nativeEvent: { + coordinate: { + latitude: number, + longitude: number, + altitude: number, + accuracy: number, + speed: number, + isFromMockProvider: boolean, + }, + }; + } + + /** + * Map style elements. + * @see https://developers.google.com/maps/documentation/ios-sdk/styling#use_a_string_resource + * @see https://developers.google.com/maps/documentation/android-api/styling + */ + export type MapStyleElement = { + featureType?: string, + elementType?: string, + stylers: object[], + }; + + export type EdgePadding = { + top: Number, + right: Number, + bottom: Number, + left: Number, + }; + + export type EdgeInsets = { + top: Number, + right: Number, + bottom: Number, + left: Number, + }; + + export type KmlMarker = { + id: String, + title: String, + description: String, + coordinate: LatLng, + position: Point, + }; + + /** + * onKmlReady parameter + */ + export interface KmlMapEvent extends NativeSyntheticEvent<{ markers: KmlMarker[] }> { } - export interface MapViewProps { - provider?: 'google'; - style: any; - customMapStyle?: any[]; + type MapTypes = 'standard' | 'satellite' | 'hybrid' | 'terrain' | 'none' | 'mutedStandard'; + + export interface MapViewProps extends ViewProperties { + provider?: 'google' | null; + customMapStyle?: MapStyleElement[]; customMapStyleString?: string; showsUserLocation?: boolean; userLocationAnnotationTitle?: string; @@ -58,8 +171,8 @@ declare module "react-native-maps" { rotateEnabled?: boolean; cacheEnabled?: boolean; loadingEnabled?: boolean; - loadingBackgroundColor?: any; - loadingIndicatorColor?: any; + loadingBackgroundColor?: string; + loadingIndicatorColor?: string; scrollEnabled?: boolean; pitchEnabled?: boolean; toolbarEnabled?: boolean; @@ -69,29 +182,32 @@ declare module "react-native-maps" { showsTraffic?: boolean; showsIndoors?: boolean; showsIndoorLevelPicker?: boolean; - mapType?: 'standard' | 'satellite' | 'hybrid' | 'terrain' | 'none' | 'mutedStandard'; - region?: { latitude: number; longitude: number; latitudeDelta: number; longitudeDelta: number; }; - initialRegion?: { latitude: number; longitude: number; latitudeDelta: number; longitudeDelta: number; }; + mapType?: MapTypes; + region?: Region; + initialRegion?: Region; liteMode?: boolean; + mapPadding?: EdgePadding; maxDelta?: number; minDelta?: number; - legalLabelInsets?: any; - onChange?: Function; - onMapReady?: Function; + legalLabelInsets?: EdgeInsets; + + onMapReady?: () => void; + onKmlReady?: (values: KmlMapEvent) => void; onRegionChange?: (region: Region) => void; onRegionChangeComplete?: (region: Region) => void; - onPress?: (value: { coordinate: LatLng, position: Point }) => void; - onLayout?: Function; - onLongPress?: (value: { coordinate: LatLng, position: Point }) => void; - onPanDrag?: (value: {coordinate: LatLng, position: Point }) => void; - onMarkerPress?: Function; - onMarkerSelect?: Function; - onMarkerDeselect?: Function; - onCalloutPress?: Function; - onMarkerDragStart?: (value: { coordinate: LatLng, position: Point }) => void; - onMarkerDrag?: (value: { coordinate: LatLng, position: Point }) => void; - onMarkerDragEnd?: (value: { coordinate: LatLng, position: Point }) => void; - onPoiClick?: (value: {coordinate: LatLng, position: Point, placeId: string, name: string }) => void; + onPress?: (event: MapEvent) => void; + onLongPress?: (event: MapEvent) => void; + onUserLocationChange?: (event: EventUserLocation) => void; + onPanDrag?: (event: MapEvent) => void; + onPoiClick?: (event: MapEvent<{ placeId: string, name: string }>) => void; + onMarkerPress?: (event: MapEvent<{ action: 'marker-press', id: string }>) => void; + onMarkerSelect?: (event: MapEvent<{ action: 'marker-select', id: string }>) => void; + onMarkerDeselect?: (event: MapEvent<{ action: 'marker-deselect', id: string }>) => void; + onCalloutPress?: (event: MapEvent<{ action: 'callout-press' }>) => void; + onMarkerDragStart?: (event: MapEvent) => void; + onMarkerDrag?: (event: MapEvent) => void; + onMarkerDragEnd?: (event: MapEvent) => void; + minZoomLevel?: number; maxZoomLevel?: number; kmlSrc?: string; @@ -104,72 +220,91 @@ declare module "react-native-maps" { animateToViewingAngle(angle: number, duration?: number): void; fitToElements(animated: boolean): void; fitToSuppliedMarkers(markers: string[], animated: boolean): void; - fitToCoordinates(coordinates?: LatLng[], options?: {}): void; - setMapBoundaries(northEast: LatLng, southWest: LatLng): void; - takeSnapshot(options?: SnapshotOptions): Promise; - } - - export class MapViewAnimated extends React.Component { - animateToRegion(region: Region, duration?: number): void; - animateToCoordinate(latLng: LatLng, duration?: number): void; - animateToBearing(bearing: number, duration?: number): void; - animateToViewingAngle(angle: number, duration?: number): void; - fitToElements(animated: boolean): void; - fitToSuppliedMarkers(markers: string[], animated: boolean): void; - fitToCoordinates(coordinates?: LatLng[], options?: {}): void; + fitToCoordinates(coordinates?: LatLng[], options?: { edgePadding?: EdgePadding, animated?: boolean }): void; setMapBoundaries(northEast: LatLng, southWest: LatLng): void; takeSnapshot(options?: SnapshotOptions): Promise; } - export interface SnapshotOptions { - width?: number; // optional, when omitted the view-width is used - height?: number; // optional, when omitted the view-height is used - region?: Region; // iOS only, optional region to render - format?: 'png' | 'jpg'; // image formats: 'png', 'jpg' (default: 'png') - quality?: number; // image quality: 0..1 (only relevant for jpg, default: 1) - result?: 'file' | 'base64'; // result types: 'file', 'base64' (default: 'file') + export class MapViewAnimated extends MapView { } - export type LineCapType = 'butt' | 'round' | 'square'; - export type LineJoinType = 'miter' | 'round' | 'bevel'; + // ======================================================================= + // Marker + // ======================================================================= - export interface MarkerProps { + export interface MarkerProps extends ViewProperties { identifier?: string; reuseIdentifier?: string; title?: string; description?: string; - image?: any; + image?: ImageURISource | ImageRequireSource; opacity?: number; pinColor?: string; - coordinate: { latitude: number; longitude: number } | AnimatedRegion; - centerOffset?: { x: number; y: number }; - calloutOffset?: { x: number; y: number }; - anchor?: { x: number; y: number }; - calloutAnchor?: { x: number; y: number }; + coordinate: LatLng | AnimatedRegion; + centerOffset?: Point; + calloutOffset?: Point; + anchor?: Point; + calloutAnchor?: Point; flat?: boolean; draggable?: boolean; - onPress?: (value: { coordinate: LatLng, position: Point }) => void; - onSelect?: (value: { coordinate: LatLng, position: Point }) => void; - onDeselect?: (value: { coordinate: LatLng, position: Point }) => void; - onCalloutPress?: Function; - onDragStart?: (value: { coordinate: LatLng, position: Point }) => void; - onDrag?: (value: { coordinate: LatLng, position: Point }) => void; - onDragEnd?: (value: { coordinate: LatLng, position: Point }) => void; - zIndex?: number; - style?: any; - rotation?: number; tracksViewChanges?: boolean tracksInfoWindowChanges?: boolean stopPropagation?: boolean + onPress?: (event: MapEvent<{ action: 'marker-press', id: string }>) => void; + onSelect?: (event: MapEvent<{ action: 'marker-select', id: string }>) => void; + onDeselect?: (event: MapEvent<{ action: 'marker-deselect', id: string }>) => void; + onCalloutPress?: (event: MapEvent<{ action: 'callout-press' }>) => void; + onDragStart?: (event: MapEvent) => void; + onDrag?: (event: MapEvent) => void; + onDragEnd?: (event: MapEvent) => void; + + rotation?: number; + zIndex?: number; + } + + export class Marker extends React.Component { + /** + * Shows the callout for this marker + */ + showCallout(): void; + /** + * Hides the callout for this marker + */ + hideCallout(): void; + /** + * Animates marker movement. + * __Android only__ + */ + animateMarkerToCoordinate(coordinate: LatLng, duration?: number): void; + } + + export class MarkerAnimated extends Marker { + } + + // ======================================================================= + // Callout + // ======================================================================= + + export interface MapCalloutProps extends ViewProperties { + tooltip?: boolean; + onPress?: (event: MapEvent<{ action: 'callout-press' }>) => void; + } + + export class Callout extends React.Component { } - export interface MapPolylineProps { - coordinates: { latitude: number; longitude: number; }[]; - onPress?: Function; + // ======================================================================= + // Polyline + // ======================================================================= + + export interface MapPolylineProps extends ViewProperties { + coordinates: LatLng[]; + onPress?: (event: MapEvent) => void; tappable?: boolean; fillColor?: string; strokeWidth?: number; strokeColor?: string; + strokeColors?: string[]; zIndex?: number; lineCap?: LineCapType; lineJoin?: LineJoinType; @@ -179,10 +314,17 @@ declare module "react-native-maps" { lineDashPattern?: number[]; } - export interface MapPolygonProps { - coordinates: { latitude: number; longitude: number; }[]; - holes?: { latitude: number; longitude: number; }[][]; - onPress?: Function; + export class Polyline extends React.Component { + } + + // ======================================================================= + // Polygon + // ======================================================================= + + export interface MapPolygonProps extends ViewProperties { + coordinates: LatLng[]; + holes?: LatLng[][]; + onPress?: (event: MapEvent) => void; tappable?: boolean; strokeWidth?: number; strokeColor?: string; @@ -196,10 +338,17 @@ declare module "react-native-maps" { lineDashPattern?: number[]; } - export interface MapCircleProps { - center: { latitude: number; longitude: number }; + export class Polygon extends React.Component { + } + + // ======================================================================= + // Circle + // ======================================================================= + + export interface MapCircleProps extends ViewProperties { + center: LatLng; radius: number; - onPress?: Function; + onPress?: (event: MapEvent) => void; strokeWidth?: number; strokeColor?: string; fillColor?: string; @@ -211,45 +360,62 @@ declare module "react-native-maps" { lineDashPattern?: number[]; } - export interface MapUrlTileProps { + export class Circle extends React.Component { + } + + // ======================================================================= + // UrlTile & LocalTile + // ======================================================================= + + export interface MapUrlTileProps extends ViewProperties { urlTemplate: string; + maximumZ?: number; zIndex?: number; } - export interface MapLocalTileProps { + export class UrlTile extends React.Component { + } + + export interface MapLocalTileProps extends ViewProperties { pathTemplate: string; - tileSize: number; + tileSize?: number; zIndex?: number; } - export interface MapOverlayProps { - image?: any; - bounds: Coordinate[]; + export class LocalTile extends React.Component { } - export interface MapCalloutProps { - tooltip?: boolean; - onPress?: Function; - style?: any; + // ======================================================================= + // Overlay + // ======================================================================= + + type Coordinate = [number, number] + + export interface MapOverlayProps extends ViewProperties { + image?: ImageURISource | ImageRequireSource; + bounds: [Coordinate, Coordinate]; } - export class Marker extends React.Component { - showCallout(): void; - hideCallout(): void; - animateMarkerToCoordinate(coordinate: LatLng, duration: number): void; + export class Overlay extends React.Component { } - export class Polyline extends React.Component { } - export class Polygon extends React.Component { } - export class Circle extends React.Component { } - export class UrlTile extends React.Component { } - export class LocalTile extends React.Component { } - export class Overlay extends React.Component { } - export class Callout extends React.Component { } - export class MarkerAnimated extends React.Component { - showCallout(): void; - hideCallout(): void; - animateMarkerToCoordinate(coordinate: LatLng, duration: number): void; + export class OverlayAnimated extends Overlay { } - export class OverlayAnimated extends React.Component { } + + // ======================================================================= + // Constants + // ======================================================================= + + export const MAP_TYPES: { + STANDARD: MapTypes, + SATELLITE: MapTypes, + HYBRID: MapTypes, + TERRAIN: MapTypes, + NONE: MapTypes, + MUTEDSTANDARD: MapTypes, + } + + export const PROVIDER_DEFAULT: null; + export const PROVIDER_GOOGLE: 'google'; + } From aafa4e668bb72f8b2281f858bd29e80814d60575 Mon Sep 17 00:00:00 2001 From: Ahmet Date: Mon, 9 Apr 2018 10:39:10 +0100 Subject: [PATCH 0446/1148] Update mapview.md (#2171) Add 'none' option to docs for mapType --- docs/mapview.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/mapview.md b/docs/mapview.md index dab74f93e..f6f424ab6 100644 --- a/docs/mapview.md +++ b/docs/mapview.md @@ -9,7 +9,7 @@ | `initialRegion` | `Region` | | The initial region to be displayed by the map. Use this prop instead of `region` only if you don't want to control the viewport of the map besides the initial region.

Changing this prop after the component has mounted will not result in a region change.

This is similar to the `initialValue` prop of a text input. | `mapPadding` | `EdgePadding` | | Adds custom padding to each side of the map. Useful when map elements/markers are obscured. **Note** Google Maps only. | `liteMode` | `Boolean` | `false` | Enable lite mode. **Note**: Android only. -| `mapType` | `String` | `"standard"` | The map type to be displayed.

- standard: standard road map (default)
- satellite: satellite view
- hybrid: satellite view with roads and points of interest overlayed
- terrain: (Android only) topographic view
- mutedStandard: more subtle, makes markers/lines pop more (iOS 11.0+ only) +| `mapType` | `String` | `"standard"` | The map type to be displayed.

- standard: standard road map (default)
- none: no map
- satellite: satellite view
- hybrid: satellite view with roads and points of interest overlayed
- terrain: (Android only) topographic view
- mutedStandard: more subtle, makes markers/lines pop more (iOS 11.0+ only) | `customMapStyle` | `Array` | | Adds custom styling to the map component. See [README](https://github.com/airbnb/react-native-maps#customizing-the-map-style) for more information. | `showsUserLocation` | `Boolean` | `false` | If `true` the app will ask for the user's location. **NOTE**: You need to add `NSLocationWhenInUseUsageDescription` key in Info.plist to enable geolocation, otherwise it is going to *fail silently*! | `userLocationAnnotationTitle` | `String` | | The title of the annotation for current user location. This only works if `showsUserLocation` is true. There is a default value `My Location` set by MapView. **Note**: iOS only. From 7f3d559735957518b18b6afcbd9cf86dd4af2ba4 Mon Sep 17 00:00:00 2001 From: Chaitanya Deorukhkar Date: Mon, 9 Apr 2018 16:54:54 +0530 Subject: [PATCH 0447/1148] Fixed crash for Android API level below 18 on isFromMockProvider (#2172) * Add Mock Provider boolean on each location update * Update mapview.md Update docs to specify that coordinate includes mock provider boolean * Check API is 18 or above for isFromMockProvider * Update docs to mention API --- docs/mapview.md | 2 +- .../main/java/com/airbnb/android/react/maps/AirMapView.java | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/mapview.md b/docs/mapview.md index f6f424ab6..1f4007e4c 100644 --- a/docs/mapview.md +++ b/docs/mapview.md @@ -49,7 +49,7 @@ To access event data, you will need to use `e.nativeEvent`. For example, `onPres | `onKmlReady` | `KmlContainer` | Callback that is called once the kml is fully loaded. | `onRegionChange` | `Region` | Callback that is called continuously when the region changes, such as when a user is dragging the map. | `onRegionChangeComplete` | `Region` | Callback that is called once when the region changes, such as when the user is done moving the map. -| `onUserLocationChange` | `{ coordinate: LatLng }` | Callback that is called when the underlying map figures our users current location (coordinate also includes isFromMockProvider value for Android). Make sure **showsUserLocation** is set to *true* and that the provider is `"google"`. +| `onUserLocationChange` | `{ coordinate: LatLng }` | Callback that is called when the underlying map figures our users current location (coordinate also includes isFromMockProvider value for Android API 18 and above). Make sure **showsUserLocation** is set to *true* and that the provider is `"google"`. | `onPress` | `{ coordinate: LatLng, position: Point }` | Callback that is called when user taps on the map. | `onPanDrag` | `{ coordinate: LatLng, position: Point }` | Callback that is called when user presses and drags the map. **NOTE**: for iOS `scrollEnabled` should be set to false to trigger the event | `onPoiClick` | `{ coordinate: LatLng, position: Point, placeId: string, name: string }` | Callback that is called when user click on a POI. diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java index 7d9b5ef9c..f270374c8 100644 --- a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java @@ -196,8 +196,10 @@ public void onMyLocationChange(Location location){ coordinate.putDouble("altitude", location.getAltitude()); coordinate.putDouble("accuracy", location.getAccuracy()); coordinate.putDouble("speed", location.getSpeed()); + if(android.os.Build.VERSION.SDK_INT >= 18){ coordinate.putBoolean("isFromMockProvider", location.isFromMockProvider()); - + } + event.putMap("coordinate", coordinate); manager.pushEvent(context, view, "onUserLocationChange", event); From bacb33b37213188fc945217542fa5f07ab1fbab7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1vid=20Cs=C3=A1kv=C3=A1ri?= Date: Mon, 9 Apr 2018 20:57:53 +0200 Subject: [PATCH 0448/1148] Add opacity to API docs. (#2174) --- docs/marker.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/marker.md b/docs/marker.md index 200ea2fba..10490349c 100644 --- a/docs/marker.md +++ b/docs/marker.md @@ -20,6 +20,7 @@ | `tracksViewChanges` | `Boolean` | true | Sets whether this marker should track view changes. It's recommended to turn it off whenever it's possible to improve custom marker performance. **Note**: iOS Google Maps only. | `tracksInfoWindowChanges` | `Boolean` | false | Sets whether this marker should track view changes in info window. Enabling it will let marker change content of info window after first render pass, but will lead to decreased performance, so it's recommended to disable it whenever you don't need it. **Note**: iOS Google Maps only. | `stopPropagation` | `Boolean` | false | Sets whether this marker should propagate `onPress` events. Enabling it will stop the parent `MapView`'s `onPress` from being called. **Note**: iOS only. Android does not propagate `onPress` events. See [#1132](https://github.com/react-community/react-native-maps/issues/1132) for more information. +| `opacity` | `Float` | 1.0 | The marker's opacity between 0.0 and 1.0. ## Events From 67d63ef8905b3d4b78f3efe1aa006fd340ea537a Mon Sep 17 00:00:00 2001 From: Adam Date: Mon, 9 Apr 2018 16:07:03 -0300 Subject: [PATCH 0449/1148] Modifications/Enhancements to MapView.UrlTile (#2136) * 1. Allow canReplaceMapContent to be set on the JS side (via prop shouldReplaceMapContent) for iOS, MapKit only 2. Allow GoogleMaps on iOS to obey maximumZ 3. Added prop minimumZ for MapKit and GoogleMaps on iOS and Android * Removed debug NSLogs * MaximumZ was not being obeyed correctly for google maps (convert to long to compare). Get rid of compiler warnings (accidentally wrote NSUInteger instead of NSInteger) * Typings for v0.21.0 (#2165) * Update mapview.md (#2171) Add 'none' option to docs for mapType * Fixed crash for Android API level below 18 on isFromMockProvider (#2172) * Add Mock Provider boolean on each location update * Update mapview.md Update docs to specify that coordinate includes mock provider boolean * Check API is 18 or above for isFromMockProvider * Update docs to mention API * 1. Allow canReplaceMapContent to be set on the JS side (via prop shouldReplaceMapContent) for iOS, MapKit only 2. Allow GoogleMaps on iOS to obey maximumZ 3. Added prop minimumZ for MapKit and GoogleMaps on iOS and Android * Removed debug NSLogs * MaximumZ was not being obeyed correctly for google maps (convert to long to compare). Get rid of compiler warnings (accidentally wrote NSUInteger instead of NSInteger) --- .../android/react/maps/AirMapUrlTile.java | 25 ++++++++++++++ .../react/maps/AirMapUrlTileManager.java | 10 ++++++ lib/components/MapUrlTile.js | 17 ++++++++-- .../AIRGoogleMapURLTileManager.m | 2 ++ lib/ios/AirGoogleMaps/AIRGoogleMapUrlTile.h | 2 ++ lib/ios/AirGoogleMaps/AIRGoogleMapUrlTile.m | 16 +++++++-- lib/ios/AirMaps/AIRMapUrlTile.h | 3 +- lib/ios/AirMaps/AIRMapUrlTile.m | 33 ++++++++++++++++++- lib/ios/AirMaps/AIRMapUrlTileManager.m | 2 ++ 9 files changed, 103 insertions(+), 7 deletions(-) diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapUrlTile.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapUrlTile.java index ae51a63b4..061a58591 100644 --- a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapUrlTile.java +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapUrlTile.java @@ -28,6 +28,15 @@ public synchronized URL getTileUrl(int x, int y, int zoom) { .replace("{y}", Integer.toString(y)) .replace("{z}", Integer.toString(zoom)); URL url = null; + + if(this.maximumZ && zoom > maximumZ) { + return url; + } + + if(this.minimumZ && zoom < minimumZ) { + return url; + } + try { url = new URL(s); } catch (MalformedURLException e) { @@ -47,6 +56,8 @@ public void setUrlTemplate(String urlTemplate) { private String urlTemplate; private float zIndex; + private float maximumZ; + private float minimumZ; public AirMapUrlTile(Context context) { super(context); @@ -69,6 +80,20 @@ public void setZIndex(float zIndex) { } } + public void setMaximumZ(float maximumZ) { + this.maximumZ = maximumZ; + if (tileOverlay != null) { + tileOverlay.clearTileCache(); + } + } + + public void setMinimumZ(float minimumZ) { + this.minimumZ = minimumZ; + if (tileOverlay != null) { + tileOverlay.clearTileCache(); + } + } + public TileOverlayOptions getTileOverlayOptions() { if (tileOverlayOptions == null) { tileOverlayOptions = createTileOverlayOptions(); diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapUrlTileManager.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapUrlTileManager.java index 68bf07342..e583a9412 100644 --- a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapUrlTileManager.java +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapUrlTileManager.java @@ -45,4 +45,14 @@ public void setZIndex(AirMapUrlTile view, float zIndex) { view.setZIndex(zIndex); } + @ReactProp(name = "minimumZ", defaultFloat = 0.0f) + public void setMinimumZ(AirMapUrlTile view, float minimumZ) { + view.setMinimumZ(minimumZ) + } + + @ReactProp(name = "maximumZ", defaultFloat = 100.0f) + public void setMaximumZ(AirMapUrlTile view, float maximumZ) { + view.setMaximumZ(maximumZ); + } + } diff --git a/lib/components/MapUrlTile.js b/lib/components/MapUrlTile.js index 0566ec2ea..babe6555c 100644 --- a/lib/components/MapUrlTile.js +++ b/lib/components/MapUrlTile.js @@ -32,12 +32,23 @@ const propTypes = { */ zIndex: PropTypes.number, /** - * The maximum zoom level for this tile overlay. Corresponds to the maximumZ setting in - * MKTileOverlay. iOS only. + * The maximum zoom level for this tile overlay. * - * @platform ios */ maximumZ: PropTypes.number, + + /** + * The minimum zoom level for this tile overlay. + * + */ + minimumZ: PropTypes.number, + + /** + * Corresponds to MKTileOverlay canReplaceMapContent. + * + * @platform ios + */ + shouldReplaceMapContent: PropTypes.bool, }; class MapUrlTile extends React.Component { diff --git a/lib/ios/AirGoogleMaps/AIRGoogleMapURLTileManager.m b/lib/ios/AirGoogleMaps/AIRGoogleMapURLTileManager.m index 79c82fe25..398d75eff 100644 --- a/lib/ios/AirGoogleMaps/AIRGoogleMapURLTileManager.m +++ b/lib/ios/AirGoogleMaps/AIRGoogleMapURLTileManager.m @@ -22,5 +22,7 @@ - (UIView *)view RCT_EXPORT_VIEW_PROPERTY(urlTemplate, NSString) RCT_EXPORT_VIEW_PROPERTY(zIndex, int) +RCT_EXPORT_VIEW_PROPERTY(maximumZ, NSInteger) +RCT_EXPORT_VIEW_PROPERTY(minimumZ, NSInteger) @end diff --git a/lib/ios/AirGoogleMaps/AIRGoogleMapUrlTile.h b/lib/ios/AirGoogleMaps/AIRGoogleMapUrlTile.h index f76a9dc88..bcc6c67fc 100644 --- a/lib/ios/AirGoogleMaps/AIRGoogleMapUrlTile.h +++ b/lib/ios/AirGoogleMaps/AIRGoogleMapUrlTile.h @@ -11,5 +11,7 @@ @property (nonatomic, strong) GMSURLTileLayer *tileLayer; @property (nonatomic, assign) NSString *urlTemplate; @property (nonatomic, assign) int zIndex; +@property NSInteger *maximumZ; +@property NSInteger *minimumZ; @end diff --git a/lib/ios/AirGoogleMaps/AIRGoogleMapUrlTile.m b/lib/ios/AirGoogleMaps/AIRGoogleMapUrlTile.m index ae6333cff..39a53fc05 100644 --- a/lib/ios/AirGoogleMaps/AIRGoogleMapUrlTile.m +++ b/lib/ios/AirGoogleMaps/AIRGoogleMapUrlTile.m @@ -22,13 +22,25 @@ - (void)setUrlTemplate:(NSString *)urlTemplate - (GMSTileURLConstructor)_getTileURLConstructor { NSString *urlTemplate = self.urlTemplate; - GMSTileURLConstructor urls = ^(NSUInteger x, NSUInteger y, NSUInteger zoom) { + NSInteger *maximumZ = self.maximumZ; + NSInteger *minimumZ = self.minimumZ; + GMSTileURLConstructor urls = ^NSURL* _Nullable (NSUInteger x, NSUInteger y, NSUInteger zoom) { NSString *url = urlTemplate; url = [url stringByReplacingOccurrencesOfString:@"{x}" withString:[NSString stringWithFormat: @"%ld", (long)x]]; url = [url stringByReplacingOccurrencesOfString:@"{y}" withString:[NSString stringWithFormat: @"%ld", (long)y]]; url = [url stringByReplacingOccurrencesOfString:@"{z}" withString:[NSString stringWithFormat: @"%ld", (long)zoom]]; + + if(maximumZ && (long)zoom > (long)maximumZ) { + return nil; + } + + if(minimumZ && (long)zoom < (long)minimumZ) { + return nil; + } + return [NSURL URLWithString:url]; }; return urls; } -@end + +@end \ No newline at end of file diff --git a/lib/ios/AirMaps/AIRMapUrlTile.h b/lib/ios/AirMaps/AIRMapUrlTile.h index 697e8deae..06eda10dd 100644 --- a/lib/ios/AirMaps/AIRMapUrlTile.h +++ b/lib/ios/AirMaps/AIRMapUrlTile.h @@ -22,9 +22,10 @@ @property (nonatomic, strong) MKTileOverlay *tileOverlay; @property (nonatomic, strong) MKTileOverlayRenderer *renderer; - @property (nonatomic, copy) NSString *urlTemplate; @property NSInteger maximumZ; +@property NSInteger minimumZ; +@property BOOL shouldReplaceMapContent; #pragma mark MKOverlay protocol diff --git a/lib/ios/AirMaps/AIRMapUrlTile.m b/lib/ios/AirMaps/AIRMapUrlTile.m index 1488c489d..62e82adc2 100644 --- a/lib/ios/AirMaps/AIRMapUrlTile.m +++ b/lib/ios/AirMaps/AIRMapUrlTile.m @@ -13,6 +13,32 @@ @implementation AIRMapUrlTile { BOOL _urlTemplateSet; } +- (void)setShouldReplaceMapContent:(BOOL)shouldReplaceMapContent +{ + _shouldReplaceMapContent = shouldReplaceMapContent; + if(self.tileOverlay) { + self.tileOverlay.canReplaceMapContent = _shouldReplaceMapContent; + } + [self update]; +} + +- (void)setMaximumZ:(NSUInteger)maximumZ +{ + _maximumZ = maximumZ; + if(self.tileOverlay) { + self.tileOverlay.maximumZ = _maximumZ; + } + [self update]; +} + +- (void)setMinimumZ:(NSUInteger)minimumZ +{ + _minimumZ = minimumZ; + if(self.tileOverlay) { + self.tileOverlay.minimumZ = _minimumZ; + } + [self update]; +} - (void)setUrlTemplate:(NSString *)urlTemplate{ _urlTemplate = urlTemplate; @@ -25,7 +51,12 @@ - (void) createTileOverlayAndRendererIfPossible { if (!_urlTemplateSet) return; self.tileOverlay = [[MKTileOverlay alloc] initWithURLTemplate:self.urlTemplate]; - self.tileOverlay.canReplaceMapContent = YES; + + self.tileOverlay.canReplaceMapContent = self.shouldReplaceMapContent; + + if(self.minimumZ) { + self.tileOverlay.minimumZ = self.minimumZ; + } if (self.maximumZ) { self.tileOverlay.maximumZ = self.maximumZ; } diff --git a/lib/ios/AirMaps/AIRMapUrlTileManager.m b/lib/ios/AirMaps/AIRMapUrlTileManager.m index 816b9f6ab..64bc617fd 100644 --- a/lib/ios/AirMaps/AIRMapUrlTileManager.m +++ b/lib/ios/AirMaps/AIRMapUrlTileManager.m @@ -34,5 +34,7 @@ - (UIView *)view RCT_EXPORT_VIEW_PROPERTY(urlTemplate, NSString) RCT_EXPORT_VIEW_PROPERTY(maximumZ, NSInteger) +RCT_EXPORT_VIEW_PROPERTY(minimumZ, NSInteger) +RCT_EXPORT_VIEW_PROPERTY(shouldReplaceMapContent, BOOL) @end From 09a52924c7511383e1bf2960f59f7be34480c857 Mon Sep 17 00:00:00 2001 From: sfyfe31 Date: Wed, 11 Apr 2018 13:54:27 +0100 Subject: [PATCH 0450/1148] Add note about NSLocationWhenInUseUsageDescription (#2181) Apple are now rejecting app submissions without an explanation of why you need to user's location. --- docs/mapview.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/mapview.md b/docs/mapview.md index 1f4007e4c..144beb3fa 100644 --- a/docs/mapview.md +++ b/docs/mapview.md @@ -11,7 +11,7 @@ | `liteMode` | `Boolean` | `false` | Enable lite mode. **Note**: Android only. | `mapType` | `String` | `"standard"` | The map type to be displayed.

- standard: standard road map (default)
- none: no map
- satellite: satellite view
- hybrid: satellite view with roads and points of interest overlayed
- terrain: (Android only) topographic view
- mutedStandard: more subtle, makes markers/lines pop more (iOS 11.0+ only) | `customMapStyle` | `Array` | | Adds custom styling to the map component. See [README](https://github.com/airbnb/react-native-maps#customizing-the-map-style) for more information. -| `showsUserLocation` | `Boolean` | `false` | If `true` the app will ask for the user's location. **NOTE**: You need to add `NSLocationWhenInUseUsageDescription` key in Info.plist to enable geolocation, otherwise it is going to *fail silently*! +| `showsUserLocation` | `Boolean` | `false` | If `true` the app will ask for the user's location. **NOTE**: You need to add `NSLocationWhenInUseUsageDescription` key in Info.plist to enable geolocation, otherwise it is going to *fail silently*! You will also need to add an explanation for why you need the users location against `NSLocationWhenInUseUsageDescription` in Info.plist. Otherwise Apple may reject your app submission. | `userLocationAnnotationTitle` | `String` | | The title of the annotation for current user location. This only works if `showsUserLocation` is true. There is a default value `My Location` set by MapView. **Note**: iOS only. | `followsUserLocation` | `Boolean` | `false` | If `true` the map will focus on the user's location. This only works if `showsUserLocation` is true and the user has shared their location. **Note**: iOS only. | `showsMyLocationButton` | `Boolean` | `true` | If `false` hide the button to move map to the current user's location. From c7c8bf511f171ae5f16131b4da3b16c492bd354e Mon Sep 17 00:00:00 2001 From: Ben Roth Date: Wed, 11 Apr 2018 16:05:21 -0700 Subject: [PATCH 0451/1148] Fix warnings for format, pointer type, unused var We noticed these warnings when using this library inside Expo. Changed NULL to 0 for the NSStringCompareOptions flag; cast the NSIntegers to long when using as a string format argument; removed unused variable zoomLevel. --- lib/ios/AirMaps/AIRMapLocalTileOverlay.m | 6 +++--- lib/ios/AirMaps/AIRMapManager.m | 1 - 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/lib/ios/AirMaps/AIRMapLocalTileOverlay.m b/lib/ios/AirMaps/AIRMapLocalTileOverlay.m index 26262e083..27b02fac7 100644 --- a/lib/ios/AirMaps/AIRMapLocalTileOverlay.m +++ b/lib/ios/AirMaps/AIRMapLocalTileOverlay.m @@ -16,9 +16,9 @@ @implementation AIRMapLocalTileOverlay -(void)loadTileAtPath:(MKTileOverlayPath)path result:(void (^)(NSData *, NSError *))result { NSMutableString *tileFilePath = [self.URLTemplate mutableCopy]; - [tileFilePath replaceOccurrencesOfString: @"{x}" withString:[NSString stringWithFormat:@"%i", path.x] options:NULL range:NSMakeRange(0, tileFilePath.length)]; - [tileFilePath replaceOccurrencesOfString:@"{y}" withString:[NSString stringWithFormat:@"%i", path.y] options:NULL range:NSMakeRange(0, tileFilePath.length)]; - [tileFilePath replaceOccurrencesOfString:@"{z}" withString:[NSString stringWithFormat:@"%i", path.z] options:NULL range:NSMakeRange(0, tileFilePath.length)]; + [tileFilePath replaceOccurrencesOfString: @"{x}" withString:[NSString stringWithFormat:@"%li", (long)path.x] options:0 range:NSMakeRange(0, tileFilePath.length)]; + [tileFilePath replaceOccurrencesOfString:@"{y}" withString:[NSString stringWithFormat:@"%li", (long)path.y] options:0 range:NSMakeRange(0, tileFilePath.length)]; + [tileFilePath replaceOccurrencesOfString:@"{z}" withString:[NSString stringWithFormat:@"%li", (long)path.z] options:0 range:NSMakeRange(0, tileFilePath.length)]; if ([[NSFileManager defaultManager] fileExistsAtPath:tileFilePath]) { NSData* tile = [NSData dataWithContentsOfFile:tileFilePath]; result(tile,nil); diff --git a/lib/ios/AirMaps/AIRMapManager.m b/lib/ios/AirMaps/AIRMapManager.m index a14dc320e..b7fe67c0c 100644 --- a/lib/ios/AirMaps/AIRMapManager.m +++ b/lib/ios/AirMaps/AIRMapManager.m @@ -810,7 +810,6 @@ - (void)_regionChanged:(AIRMap *)mapView BOOL needZoom = NO; CGFloat newLongitudeDelta = 0.0f; MKCoordinateRegion region = mapView.region; - CGFloat zoomLevel = [self zoomLevel:mapView]; // On iOS 7, it's possible that we observe invalid locations during initialization of the map. // Filter those out. if (!CLLocationCoordinate2DIsValid(region.center)) { From a4b1137c06b3892cff993edf419a0668e5e744a6 Mon Sep 17 00:00:00 2001 From: Stanimir Marinov Date: Wed, 18 Apr 2018 11:40:51 +0300 Subject: [PATCH 0452/1148] Fix https://github.com/react-community/react-native-maps/issues/2203 --- .../main/java/com/airbnb/android/react/maps/AirMapView.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java index f270374c8..6da24f6ab 100644 --- a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java @@ -194,11 +194,12 @@ public void onMyLocationChange(Location location){ coordinate.putDouble("latitude", location.getLatitude()); coordinate.putDouble("longitude", location.getLongitude()); coordinate.putDouble("altitude", location.getAltitude()); + coordinate.putDouble("timestamp", location.getTime()); coordinate.putDouble("accuracy", location.getAccuracy()); coordinate.putDouble("speed", location.getSpeed()); if(android.os.Build.VERSION.SDK_INT >= 18){ coordinate.putBoolean("isFromMockProvider", location.isFromMockProvider()); - } + } event.putMap("coordinate", coordinate); From 521e5fed0736bc8ccc08b7800a725fb874b52c29 Mon Sep 17 00:00:00 2001 From: Christoph Jerolimov Date: Wed, 18 Apr 2018 15:53:38 +0200 Subject: [PATCH 0453/1148] Fix compile issues in Android variant. (#2184) --- .../java/com/airbnb/android/react/maps/AirMapUrlTile.java | 6 +++--- .../com/airbnb/android/react/maps/AirMapUrlTileManager.java | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapUrlTile.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapUrlTile.java index 061a58591..03e7e7e78 100644 --- a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapUrlTile.java +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapUrlTile.java @@ -29,11 +29,11 @@ public synchronized URL getTileUrl(int x, int y, int zoom) { .replace("{z}", Integer.toString(zoom)); URL url = null; - if(this.maximumZ && zoom > maximumZ) { + if(AirMapUrlTile.this.maximumZ > 0 && zoom > maximumZ) { return url; } - if(this.minimumZ && zoom < minimumZ) { + if(AirMapUrlTile.this.minimumZ > 0 && zoom < minimumZ) { return url; } @@ -92,7 +92,7 @@ public void setMinimumZ(float minimumZ) { if (tileOverlay != null) { tileOverlay.clearTileCache(); } - } + } public TileOverlayOptions getTileOverlayOptions() { if (tileOverlayOptions == null) { diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapUrlTileManager.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapUrlTileManager.java index e583a9412..1fc5672c4 100644 --- a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapUrlTileManager.java +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapUrlTileManager.java @@ -47,7 +47,7 @@ public void setZIndex(AirMapUrlTile view, float zIndex) { @ReactProp(name = "minimumZ", defaultFloat = 0.0f) public void setMinimumZ(AirMapUrlTile view, float minimumZ) { - view.setMinimumZ(minimumZ) + view.setMinimumZ(minimumZ); } @ReactProp(name = "maximumZ", defaultFloat = 100.0f) From d30ef1e2c808e79942c9e813b8e1200054cebafc Mon Sep 17 00:00:00 2001 From: Stanimir Marinov Date: Wed, 18 Apr 2018 17:05:18 +0300 Subject: [PATCH 0454/1148] update js interface for onUserLocationChange results --- index.d.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/index.d.ts b/index.d.ts index 044c05082..ab350f158 100644 --- a/index.d.ts +++ b/index.d.ts @@ -108,6 +108,7 @@ declare module "react-native-maps" { latitude: number, longitude: number, altitude: number, + timestamp: number, accuracy: number, speed: number, isFromMockProvider: boolean, From 062a505112ac1b0fafbdc02bc206c517214c5cfc Mon Sep 17 00:00:00 2001 From: Stanimir Marinov Date: Fri, 20 Apr 2018 15:31:49 +0300 Subject: [PATCH 0455/1148] for iOS add timestamp to onUserLocationChange results --- lib/ios/AirGoogleMaps/AIRGoogleMap.m | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/ios/AirGoogleMaps/AIRGoogleMap.m b/lib/ios/AirGoogleMaps/AIRGoogleMap.m index 521143a54..d40fdc295 100644 --- a/lib/ios/AirGoogleMaps/AIRGoogleMap.m +++ b/lib/ios/AirGoogleMaps/AIRGoogleMap.m @@ -449,6 +449,7 @@ - (void)observeValueForKeyPath:(NSString *)keyPath @"latitude": @(location.coordinate.latitude), @"longitude": @(location.coordinate.longitude), @"altitude": @(location.altitude), + @"timestamp": @(location.timestamp), @"accuracy": @(location.horizontalAccuracy), @"altitudeAccuracy": @(location.verticalAccuracy), @"speed": @(location.speed), From bf915b3ae7124f76bb04fd4316fcb79375930df3 Mon Sep 17 00:00:00 2001 From: Pedro Belo Date: Wed, 25 Apr 2018 18:59:42 -0700 Subject: [PATCH 0456/1148] Fix color prop types use react-native's ColorPropType to validate the input --- lib/components/MapCircle.js | 5 +++-- lib/components/MapMarker.js | 3 ++- lib/components/MapPolygon.js | 5 +++-- lib/components/MapPolyline.js | 7 ++++--- 4 files changed, 12 insertions(+), 8 deletions(-) diff --git a/lib/components/MapCircle.js b/lib/components/MapCircle.js index 7163128ea..556f54d4f 100644 --- a/lib/components/MapCircle.js +++ b/lib/components/MapCircle.js @@ -1,6 +1,7 @@ import PropTypes from 'prop-types'; import React from 'react'; import { + ColorPropType, ViewPropTypes, View, } from 'react-native'; @@ -44,12 +45,12 @@ const propTypes = { /** * The stroke color to use for the path. */ - strokeColor: PropTypes.string, + strokeColor: ColorPropType, /** * The fill color to use for the path. */ - fillColor: PropTypes.string, + fillColor: ColorPropType, /** * The order in which this tile overlay is drawn with respect to other overlays. An overlay diff --git a/lib/components/MapMarker.js b/lib/components/MapMarker.js index 73b82b1f4..ef0d103ff 100644 --- a/lib/components/MapMarker.js +++ b/lib/components/MapMarker.js @@ -1,6 +1,7 @@ import PropTypes from 'prop-types'; import React from 'react'; import { + ColorPropType, StyleSheet, Platform, NativeModules, @@ -62,7 +63,7 @@ const propTypes = { * If no custom marker view or custom image is provided, the platform default pin will be used, * which can be customized by this color. Ignored if a custom marker is being used. */ - pinColor: PropTypes.string, + pinColor: ColorPropType, /** * The coordinate for the marker. diff --git a/lib/components/MapPolygon.js b/lib/components/MapPolygon.js index a57e62b2b..369cf2c44 100644 --- a/lib/components/MapPolygon.js +++ b/lib/components/MapPolygon.js @@ -1,6 +1,7 @@ import PropTypes from 'prop-types'; import React from 'react'; import { + ColorPropType, ViewPropTypes, View, } from 'react-native'; @@ -56,12 +57,12 @@ const propTypes = { /** * The stroke color to use for the path. */ - strokeColor: PropTypes.string, + strokeColor: ColorPropType, /** * The fill color to use for the path. */ - fillColor: PropTypes.string, + fillColor: ColorPropType, /** * The order in which this tile overlay is drawn with respect to other overlays. An overlay diff --git a/lib/components/MapPolyline.js b/lib/components/MapPolyline.js index 4351aa8c5..14289a3e3 100644 --- a/lib/components/MapPolyline.js +++ b/lib/components/MapPolyline.js @@ -1,6 +1,7 @@ import PropTypes from 'prop-types'; import React from 'react'; import { + ColorPropType, ViewPropTypes, View, } from 'react-native'; @@ -39,7 +40,7 @@ const propTypes = { /** * The fill color to use for the path. */ - fillColor: PropTypes.string, + fillColor: ColorPropType, /** * The stroke width to use for the path. @@ -49,12 +50,12 @@ const propTypes = { /** * The stroke color to use for the path. */ - strokeColor: PropTypes.string, + strokeColor: ColorPropType, /** * The stroke colors to use for the path. */ - strokeColors: PropTypes.arrayOf(PropTypes.string), + strokeColors: PropTypes.arrayOf(ColorPropType), /** * The order in which this tile overlay is drawn with respect to other overlays. An overlay From 1900f585b6391d8b1918a550521b3b1e8b65fadc Mon Sep 17 00:00:00 2001 From: Roman Kot Date: Sat, 28 Apr 2018 12:33:35 +0200 Subject: [PATCH 0457/1148] respect `tappable` prop on android --- .../com/airbnb/android/react/maps/AirMapPolygon.java | 10 +++++++++- .../android/react/maps/AirMapPolygonManager.java | 5 +++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapPolygon.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapPolygon.java index 5f2729378..6ed5df360 100644 --- a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapPolygon.java +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapPolygon.java @@ -23,6 +23,7 @@ public class AirMapPolygon extends AirMapFeature { private int fillColor; private float strokeWidth; private boolean geodesic; + private boolean tappable; private float zIndex; public AirMapPolygon(Context context) { @@ -95,6 +96,13 @@ public void setStrokeWidth(float width) { } } + public void setTappable(boolean tapabble) { + this.tappable = tapabble; + if (polygon != null) { + polygon.setClickable(tappable); + } + } + public void setGeodesic(boolean geodesic) { this.geodesic = geodesic; if (polygon != null) { @@ -142,7 +150,7 @@ public Object getFeature() { @Override public void addToMap(GoogleMap map) { polygon = map.addPolygon(getPolygonOptions()); - polygon.setClickable(true); + polygon.setClickable(this.tappable); } @Override diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapPolygonManager.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapPolygonManager.java index 0f0378026..3013214d5 100644 --- a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapPolygonManager.java +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapPolygonManager.java @@ -68,6 +68,11 @@ public void setStrokeColor(AirMapPolygon view, int color) { view.setStrokeColor(color); } + @ReactProp(name = "tappable", defaultBoolean = false) + public void setTappable(AirMapPolygon view, boolean tapabble) { + view.setTappable(tapabble); + } + @ReactProp(name = "geodesic", defaultBoolean = false) public void setGeodesic(AirMapPolygon view, boolean geodesic) { view.setGeodesic(geodesic); From c4298be7fd11d6b4e38e85a6045a5a6bf2dc8f57 Mon Sep 17 00:00:00 2001 From: Eric Samelson Date: Mon, 30 Apr 2018 15:28:13 -0700 Subject: [PATCH 0458/1148] use global imports for new Pods dependencies in AIRGoogleMap (#2229) --- lib/ios/AirGoogleMaps/AIRGoogleMap.m | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/ios/AirGoogleMaps/AIRGoogleMap.m b/lib/ios/AirGoogleMaps/AIRGoogleMap.m index d40fdc295..fd43467cb 100644 --- a/lib/ios/AirGoogleMaps/AIRGoogleMap.m +++ b/lib/ios/AirGoogleMaps/AIRGoogleMap.m @@ -14,10 +14,10 @@ #import "AIRGoogleMapUrlTile.h" #import "AIRGoogleMapOverlay.h" #import -#import "GMUKMLParser.h" -#import "GMUPlacemark.h" -#import "GMUPoint.h" -#import "GMUGeometryRenderer.h" +#import +#import +#import +#import #import #import #import From 294ccea7fc6edc4c3b25779c36c234ec80f05f50 Mon Sep 17 00:00:00 2001 From: KUBO Date: Tue, 1 May 2018 19:36:26 +0900 Subject: [PATCH 0459/1148] Add comment about NSLocationWhenInUseUsageDescription (#2219) --- lib/components/MapView.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/components/MapView.js b/lib/components/MapView.js index f8011f148..9d90fd84d 100644 --- a/lib/components/MapView.js +++ b/lib/components/MapView.js @@ -90,7 +90,9 @@ const propTypes = { * * **NOTE**: You need to add NSLocationWhenInUseUsageDescription key in * Info.plist to enable geolocation, otherwise it is going - * to *fail silently*! + * to *fail silently*! You will also need to add an explanation for why + * you need the users location against `NSLocationWhenInUseUsageDescription` in Info.plist. + * Otherwise Apple may reject your app submission. */ showsUserLocation: PropTypes.bool, From 25776e789b79e676ede13251b4ca72a9f8926b52 Mon Sep 17 00:00:00 2001 From: Dmitry Kabak Date: Tue, 1 May 2018 13:38:40 +0300 Subject: [PATCH 0460/1148] Fix overlay removal bug (#2197) --- .../main/java/com/airbnb/android/react/maps/AirMapOverlay.java | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapOverlay.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapOverlay.java index 0c110d4b5..7d2134ada 100644 --- a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapOverlay.java +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapOverlay.java @@ -100,6 +100,7 @@ public void addToMap(GoogleMap map) { @Override public void removeFromMap(GoogleMap map) { + this.map = null; if (this.groundOverlay != null) { this.groundOverlay.remove(); this.groundOverlay = null; From 5f2de47932ecbe0b6338e57014ac4132c7e26963 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Tue, 1 May 2018 13:39:31 +0300 Subject: [PATCH 0461/1148] Fixed `pointForCoordinate`/`coordinateForPoint` Promises in iOS (#2039, #2061) (#2150) --- lib/ios/AirGoogleMaps/AIRGoogleMapManager.m | 22 +++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/lib/ios/AirGoogleMaps/AIRGoogleMapManager.m b/lib/ios/AirGoogleMaps/AIRGoogleMapManager.m index 37757cdb3..bbe206fb5 100644 --- a/lib/ios/AirGoogleMaps/AIRGoogleMapManager.m +++ b/lib/ios/AirGoogleMaps/AIRGoogleMapManager.m @@ -298,7 +298,8 @@ - (UIView *)view RCT_EXPORT_METHOD(pointForCoordinate:(nonnull NSNumber *)reactTag coordinate:(NSDictionary *)coordinate - withCallback:(RCTResponseSenderBlock)callback) + resolver: (RCTPromiseResolveBlock)resolve + rejecter:(RCTPromiseRejectBlock)reject) { CLLocationCoordinate2D coord = CLLocationCoordinate2DMake( @@ -314,18 +315,19 @@ - (UIView *)view AIRGoogleMap *mapView = (AIRGoogleMap *)view; CGPoint touchPoint = [mapView.projection pointForCoordinate:coord]; - - callback(@[[NSNull null], @{ - @"x": @(touchPoint.x), - @"y": @(touchPoint.y), - }]); + + resolve(@{ + @"x": @(touchPoint.x), + @"y": @(touchPoint.y), + }); } }]; } RCT_EXPORT_METHOD(coordinateForPoint:(nonnull NSNumber *)reactTag point:(NSDictionary *)point - withCallback:(RCTResponseSenderBlock)callback) + resolver: (RCTPromiseResolveBlock)resolve + rejecter:(RCTPromiseRejectBlock)reject) { CGPoint pt = CGPointMake( [point[@"x"] doubleValue], @@ -340,11 +342,11 @@ - (UIView *)view AIRGoogleMap *mapView = (AIRGoogleMap *)view; CLLocationCoordinate2D coordinate = [mapView.projection coordinateForPoint:pt]; - - callback(@[[NSNull null], @{ + + resolve(@{ @"latitude": @(coordinate.latitude), @"longitude": @(coordinate.longitude), - }]); + }); } }]; } From bdf6407b7e3459b83abb0891d50177e1e16fb702 Mon Sep 17 00:00:00 2001 From: Ben Roth Date: Tue, 1 May 2018 11:14:06 -0700 Subject: [PATCH 0462/1148] [iOS] Prefix DummyView class (#2231) --- .../AirGoogleMaps/{DummyView.h => AIRDummyView.h} | 4 ++-- .../AirGoogleMaps/{DummyView.m => AIRDummyView.m} | 6 +++--- lib/ios/AirGoogleMaps/AIRGoogleMapMarker.m | 6 +++--- lib/ios/AirMaps.xcodeproj/project.pbxproj | 12 ++++++------ 4 files changed, 14 insertions(+), 14 deletions(-) rename lib/ios/AirGoogleMaps/{DummyView.h => AIRDummyView.h} (78%) rename lib/ios/AirGoogleMaps/{DummyView.m => AIRDummyView.m} (75%) diff --git a/lib/ios/AirGoogleMaps/DummyView.h b/lib/ios/AirGoogleMaps/AIRDummyView.h similarity index 78% rename from lib/ios/AirGoogleMaps/DummyView.h rename to lib/ios/AirGoogleMaps/AIRDummyView.h index ba4be2834..624c0cb43 100644 --- a/lib/ios/AirGoogleMaps/DummyView.h +++ b/lib/ios/AirGoogleMaps/AIRDummyView.h @@ -1,5 +1,5 @@ // -// DummyView.h +// AIRDummyView.h // AirMapsExplorer // // Created by Gil Birman on 10/4/16. @@ -8,7 +8,7 @@ #import -@interface DummyView : UIView +@interface AIRDummyView : UIView @property (nonatomic, weak) UIView *view; - (instancetype)initWithView:(UIView*)view; @end diff --git a/lib/ios/AirGoogleMaps/DummyView.m b/lib/ios/AirGoogleMaps/AIRDummyView.m similarity index 75% rename from lib/ios/AirGoogleMaps/DummyView.m rename to lib/ios/AirGoogleMaps/AIRDummyView.m index 9e8439707..3775394dc 100644 --- a/lib/ios/AirGoogleMaps/DummyView.m +++ b/lib/ios/AirGoogleMaps/AIRDummyView.m @@ -1,14 +1,14 @@ // -// DummyView.m +// AIRDummyView.m // AirMapsExplorer // // Created by Gil Birman on 10/4/16. // #import -#import "DummyView.h" +#import "AIRDummyView.h" -@implementation DummyView +@implementation AIRDummyView - (instancetype)initWithView:(UIView*)view { if ((self = [super init])) { diff --git a/lib/ios/AirGoogleMaps/AIRGoogleMapMarker.m b/lib/ios/AirGoogleMaps/AIRGoogleMapMarker.m index 5c513854c..12d556099 100644 --- a/lib/ios/AirGoogleMaps/AIRGoogleMapMarker.m +++ b/lib/ios/AirGoogleMaps/AIRGoogleMapMarker.m @@ -11,7 +11,7 @@ #import #import "AIRGMSMarker.h" #import "AIRGoogleMapCallout.h" -#import "DummyView.h" +#import "AIRDummyView.h" CGRect unionRect(CGRect a, CGRect b) { return CGRectMake( @@ -90,12 +90,12 @@ - (void)insertReactSubview:(id)subview atIndex:(NSInteger)atIndex } else { // a child view of the marker [self iconViewInsertSubview:(UIView*)subview atIndex:atIndex+1]; } - DummyView *dummySubview = [[DummyView alloc] initWithView:(UIView *)subview]; + AIRDummyView *dummySubview = [[AIRDummyView alloc] initWithView:(UIView *)subview]; [super insertReactSubview:(UIView*)dummySubview atIndex:atIndex]; } - (void)removeReactSubview:(id)dummySubview { - UIView* subview = ((DummyView*)dummySubview).view; + UIView* subview = ((AIRDummyView*)dummySubview).view; if ([subview isKindOfClass:[AIRGoogleMapCallout class]]) { self.calloutView = nil; diff --git a/lib/ios/AirMaps.xcodeproj/project.pbxproj b/lib/ios/AirMaps.xcodeproj/project.pbxproj index 4bb684b04..7e2468f62 100644 --- a/lib/ios/AirMaps.xcodeproj/project.pbxproj +++ b/lib/ios/AirMaps.xcodeproj/project.pbxproj @@ -43,11 +43,11 @@ 9B9498D52017EFB800158761 /* AIRGoogleMapPolyline.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B9498BB2017EFB600158761 /* AIRGoogleMapPolyline.m */; }; 9B9498D62017EFB800158761 /* AIRGoogleMapCircleManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B9498BC2017EFB600158761 /* AIRGoogleMapCircleManager.m */; }; 9B9498D72017EFB800158761 /* AIRGoogleMapManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B9498BD2017EFB600158761 /* AIRGoogleMapManager.m */; }; - 9B9498D82017EFB800158761 /* DummyView.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B9498BF2017EFB600158761 /* DummyView.m */; }; 9B9498D92017EFB800158761 /* AIRGoogleMapCalloutManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B9498C42017EFB700158761 /* AIRGoogleMapCalloutManager.m */; }; 9B9498DA2017EFB800158761 /* AIRGoogleMapPolygon.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B9498C62017EFB800158761 /* AIRGoogleMapPolygon.m */; }; 9B9498DB2017EFB800158761 /* AIRGoogleMapMarker.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B9498C72017EFB800158761 /* AIRGoogleMapMarker.m */; }; 9B9498DC2017EFB800158761 /* AIRGoogleMapPolygonManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B9498C92017EFB800158761 /* AIRGoogleMapPolygonManager.m */; }; + B5EA3BA92098E22B000E7AFD /* AIRDummyView.m in Sources */ = {isa = PBXBuildFile; fileRef = B5EA3BA72098E22B000E7AFD /* AIRDummyView.m */; }; DA6C26381C9E2AFE0035349F /* AIRMapUrlTile.m in Sources */ = {isa = PBXBuildFile; fileRef = DA6C26371C9E2AFE0035349F /* AIRMapUrlTile.m */; }; DA6C263E1C9E324A0035349F /* AIRMapUrlTileManager.m in Sources */ = {isa = PBXBuildFile; fileRef = DA6C263D1C9E324A0035349F /* AIRMapUrlTileManager.m */; }; /* End PBXBuildFile section */ @@ -123,7 +123,6 @@ 9B9498AF2017EFB500158761 /* AIRGMSPolyline.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AIRGMSPolyline.m; path = AirGoogleMaps/AIRGMSPolyline.m; sourceTree = ""; }; 9B9498B02017EFB500158761 /* AIRGoogleMapCircleManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AIRGoogleMapCircleManager.h; path = AirGoogleMaps/AIRGoogleMapCircleManager.h; sourceTree = ""; }; 9B9498B12017EFB500158761 /* AIRGoogleMapPolylineManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AIRGoogleMapPolylineManager.m; path = AirGoogleMaps/AIRGoogleMapPolylineManager.m; sourceTree = ""; }; - 9B9498B22017EFB500158761 /* DummyView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DummyView.h; path = AirGoogleMaps/DummyView.h; sourceTree = ""; }; 9B9498B32017EFB500158761 /* AIRGoogleMapCircle.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AIRGoogleMapCircle.m; path = AirGoogleMaps/AIRGoogleMapCircle.m; sourceTree = ""; }; 9B9498B42017EFB500158761 /* AIRGMSPolyline.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AIRGMSPolyline.h; path = AirGoogleMaps/AIRGMSPolyline.h; sourceTree = ""; }; 9B9498B52017EFB500158761 /* AIRGoogleMapMarkerManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AIRGoogleMapMarkerManager.m; path = AirGoogleMaps/AIRGoogleMapMarkerManager.m; sourceTree = ""; }; @@ -136,7 +135,6 @@ 9B9498BC2017EFB600158761 /* AIRGoogleMapCircleManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AIRGoogleMapCircleManager.m; path = AirGoogleMaps/AIRGoogleMapCircleManager.m; sourceTree = ""; }; 9B9498BD2017EFB600158761 /* AIRGoogleMapManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AIRGoogleMapManager.m; path = AirGoogleMaps/AIRGoogleMapManager.m; sourceTree = ""; }; 9B9498BE2017EFB600158761 /* AIRGoogleMapManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AIRGoogleMapManager.h; path = AirGoogleMaps/AIRGoogleMapManager.h; sourceTree = ""; }; - 9B9498BF2017EFB600158761 /* DummyView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = DummyView.m; path = AirGoogleMaps/DummyView.m; sourceTree = ""; }; 9B9498C02017EFB700158761 /* AIRGoogleMapMarker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AIRGoogleMapMarker.h; path = AirGoogleMaps/AIRGoogleMapMarker.h; sourceTree = ""; }; 9B9498C12017EFB700158761 /* AIRGMSMarker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AIRGMSMarker.h; path = AirGoogleMaps/AIRGMSMarker.h; sourceTree = ""; }; 9B9498C22017EFB700158761 /* AIRGoogleMapCircle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AIRGoogleMapCircle.h; path = AirGoogleMaps/AIRGoogleMapCircle.h; sourceTree = ""; }; @@ -147,6 +145,8 @@ 9B9498C72017EFB800158761 /* AIRGoogleMapMarker.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AIRGoogleMapMarker.m; path = AirGoogleMaps/AIRGoogleMapMarker.m; sourceTree = ""; }; 9B9498C82017EFB800158761 /* AIRGoogleMapUrlTile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AIRGoogleMapUrlTile.h; path = AirGoogleMaps/AIRGoogleMapUrlTile.h; sourceTree = ""; }; 9B9498C92017EFB800158761 /* AIRGoogleMapPolygonManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AIRGoogleMapPolygonManager.m; path = AirGoogleMaps/AIRGoogleMapPolygonManager.m; sourceTree = ""; }; + B5EA3BA72098E22B000E7AFD /* AIRDummyView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AIRDummyView.m; path = AirGoogleMaps/AIRDummyView.m; sourceTree = ""; }; + B5EA3BA82098E22B000E7AFD /* AIRDummyView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AIRDummyView.h; path = AirGoogleMaps/AIRDummyView.h; sourceTree = ""; }; DA6C26361C9E2AFE0035349F /* AIRMapUrlTile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRMapUrlTile.h; sourceTree = ""; }; DA6C26371C9E2AFE0035349F /* AIRMapUrlTile.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRMapUrlTile.m; sourceTree = ""; }; DA6C263C1C9E324A0035349F /* AIRMapUrlTileManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRMapUrlTileManager.h; sourceTree = ""; }; @@ -238,6 +238,8 @@ 9B9498A32017EF9D00158761 /* AirGoogleMaps */ = { isa = PBXGroup; children = ( + B5EA3BA82098E22B000E7AFD /* AIRDummyView.h */, + B5EA3BA72098E22B000E7AFD /* AIRDummyView.m */, 9B9498C12017EFB700158761 /* AIRGMSMarker.h */, 9B9498AE2017EFB500158761 /* AIRGMSMarker.m */, 9B9498BA2017EFB600158761 /* AIRGMSPolygon.h */, @@ -272,8 +274,6 @@ 9B9498A62017EFB400158761 /* AIRGoogleMapUrlTile.m */, 9B9498AD2017EFB400158761 /* AIRGoogleMapUrlTileManager.h */, 9B9498A72017EFB400158761 /* AIRGoogleMapURLTileManager.m */, - 9B9498B22017EFB500158761 /* DummyView.h */, - 9B9498BF2017EFB600158761 /* DummyView.m */, 9B9498A92017EFB400158761 /* RCTConvert+GMSMapViewType.h */, 9B9498B92017EFB600158761 /* RCTConvert+GMSMapViewType.m */, ); @@ -352,7 +352,6 @@ 9B9498D72017EFB800158761 /* AIRGoogleMapManager.m in Sources */, 19DABC7F1E7C9D3C00F41150 /* RCTConvert+AirMap.m in Sources */, 1125B2E51C4AD3DA007D0023 /* AIRMapPolyline.m in Sources */, - 9B9498D82017EFB800158761 /* DummyView.m in Sources */, 9B9498D52017EFB800158761 /* AIRGoogleMapPolyline.m in Sources */, 9B9498CF2017EFB800158761 /* AIRGMSPolyline.m in Sources */, 9B9498D42017EFB800158761 /* RCTConvert+GMSMapViewType.m in Sources */, @@ -371,6 +370,7 @@ 9B9498D02017EFB800158761 /* AIRGoogleMapPolylineManager.m in Sources */, 1125B2E11C4AD3DA007D0023 /* AIRMapMarker.m in Sources */, 9B9498CA2017EFB800158761 /* AIRGoogleMapUrlTile.m in Sources */, + B5EA3BA92098E22B000E7AFD /* AIRDummyView.m in Sources */, 9B9498CD2017EFB800158761 /* AIRGoogleMapCallout.m in Sources */, 1125B2E21C4AD3DA007D0023 /* AIRMapMarkerManager.m in Sources */, DA6C26381C9E2AFE0035349F /* AIRMapUrlTile.m in Sources */, From b6bf65b0c2d70f86327de48e20c1a2ca76329a48 Mon Sep 17 00:00:00 2001 From: Janic Duplessis Date: Sat, 5 May 2018 12:29:50 -0400 Subject: [PATCH 0463/1148] Support the asset scheme for images --- .../main/java/com/airbnb/android/react/maps/AirMapMarker.java | 2 +- .../main/java/com/airbnb/android/react/maps/ImageReader.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapMarker.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapMarker.java index ba71bee70..4663b7109 100644 --- a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapMarker.java +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapMarker.java @@ -268,7 +268,7 @@ public void setImage(String uri) { iconBitmapDescriptor = null; update(); } else if (uri.startsWith("http://") || uri.startsWith("https://") || - uri.startsWith("file://")) { + uri.startsWith("file://") || uri.startsWith("asset://")) { ImageRequest imageRequest = ImageRequestBuilder .newBuilderWithSource(Uri.parse(uri)) .build(); diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/ImageReader.java b/lib/android/src/main/java/com/airbnb/android/react/maps/ImageReader.java index 09be61976..c01866d80 100644 --- a/lib/android/src/main/java/com/airbnb/android/react/maps/ImageReader.java +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/ImageReader.java @@ -89,7 +89,7 @@ public void setImage(String uri) { imp.setIconBitmapDescriptor(null); imp.update(); } else if (uri.startsWith("http://") || uri.startsWith("https://") || - uri.startsWith("file://")) { + uri.startsWith("file://") || uri.startsWith("asset://")) { ImageRequest imageRequest = ImageRequestBuilder .newBuilderWithSource(Uri.parse(uri)) .build(); From 6b06ac943f48c01730fe27edd05b29a96a13705e Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Wed, 9 May 2018 19:14:40 +0300 Subject: [PATCH 0464/1148] Added `paddingAdjustmentBehavior` for Google Maps on iOS (#2149) --- docs/mapview.md | 1 + lib/components/MapView.js | 9 ++++++ lib/ios/AirGoogleMaps/AIRGoogleMap.h | 1 + lib/ios/AirGoogleMaps/AIRGoogleMap.m | 32 +++++++++++++++++++++ lib/ios/AirGoogleMaps/AIRGoogleMapManager.m | 1 + 5 files changed, 44 insertions(+) diff --git a/docs/mapview.md b/docs/mapview.md index 144beb3fa..0a57bc2f2 100644 --- a/docs/mapview.md +++ b/docs/mapview.md @@ -8,6 +8,7 @@ | `region` | `Region` | | The region to be displayed by the map.

The region is defined by the center coordinates and the span of coordinates to display. | `initialRegion` | `Region` | | The initial region to be displayed by the map. Use this prop instead of `region` only if you don't want to control the viewport of the map besides the initial region.

Changing this prop after the component has mounted will not result in a region change.

This is similar to the `initialValue` prop of a text input. | `mapPadding` | `EdgePadding` | | Adds custom padding to each side of the map. Useful when map elements/markers are obscured. **Note** Google Maps only. +| `paddingAdjustmentBehavior` | 'always'|'automatic'|'never' | Indicates how/when to affect padding with safe area insets (`GoogleMaps` in iOS only) | `liteMode` | `Boolean` | `false` | Enable lite mode. **Note**: Android only. | `mapType` | `String` | `"standard"` | The map type to be displayed.

- standard: standard road map (default)
- none: no map
- satellite: satellite view
- hybrid: satellite view with roads and points of interest overlayed
- terrain: (Android only) topographic view
- mutedStandard: more subtle, makes markers/lines pop more (iOS 11.0+ only) | `customMapStyle` | `Array` | | Adds custom styling to the map component. See [README](https://github.com/airbnb/react-native-maps#customizing-the-map-style) for more information. diff --git a/lib/components/MapView.js b/lib/components/MapView.js index 9d90fd84d..b848beb4e 100644 --- a/lib/components/MapView.js +++ b/lib/components/MapView.js @@ -324,6 +324,15 @@ const propTypes = { */ mapPadding: EdgeInsetsPropType, + /** + * (Google Maps only, iOS) + * + * Whether the safe area padding is added to the Google Map View padding. + * This affects where markers, compass, Google logo etc. are placed on the view. + * + */ + paddingAdjustmentBehavior: PropTypes.oneOf(['always', 'automatic', 'never']), + /** * Maximum size of area that can be displayed. * diff --git a/lib/ios/AirGoogleMaps/AIRGoogleMap.h b/lib/ios/AirGoogleMaps/AIRGoogleMap.h index a9737755f..af362c27e 100644 --- a/lib/ios/AirGoogleMaps/AIRGoogleMap.h +++ b/lib/ios/AirGoogleMaps/AIRGoogleMap.h @@ -21,6 +21,7 @@ @property (nonatomic, assign) MKCoordinateRegion region; @property (nonatomic, assign) NSString *customMapStyleString; @property (nonatomic, assign) UIEdgeInsets mapPadding; +@property (nonatomic, assign) NSString *paddingAdjustmentBehaviorString; @property (nonatomic, copy) RCTBubblingEventBlock onMapReady; @property (nonatomic, copy) RCTBubblingEventBlock onKmlReady; @property (nonatomic, copy) RCTBubblingEventBlock onPress; diff --git a/lib/ios/AirGoogleMaps/AIRGoogleMap.m b/lib/ios/AirGoogleMaps/AIRGoogleMap.m index fd43467cb..171692a66 100644 --- a/lib/ios/AirGoogleMaps/AIRGoogleMap.m +++ b/lib/ios/AirGoogleMaps/AIRGoogleMap.m @@ -301,6 +301,38 @@ - (UIEdgeInsets)mapPadding { return self.padding; } +- (void)setPaddingAdjustmentBehaviorString:(NSString *)str +{ + if ([str isEqualToString:@"never"]) + { + self.paddingAdjustmentBehavior = kGMSMapViewPaddingAdjustmentBehaviorNever; + } + else if ([str isEqualToString:@"automatic"]) + { + self.paddingAdjustmentBehavior = kGMSMapViewPaddingAdjustmentBehaviorAutomatic; + } + else //if ([str isEqualToString:@"always"]) <-- default + { + self.paddingAdjustmentBehavior = kGMSMapViewPaddingAdjustmentBehaviorAlways; + } +} + +- (NSString *)paddingAdjustmentBehaviorString +{ + switch (self.paddingAdjustmentBehavior) + { + case kGMSMapViewPaddingAdjustmentBehaviorNever: + return @"never"; + case kGMSMapViewPaddingAdjustmentBehaviorAutomatic: + return @"automatic"; + case kGMSMapViewPaddingAdjustmentBehaviorAlways: + return @"always"; + + default: + return @"unknown"; + } +} + - (void)setScrollEnabled:(BOOL)scrollEnabled { self.settings.scrollGestures = scrollEnabled; } diff --git a/lib/ios/AirGoogleMaps/AIRGoogleMapManager.m b/lib/ios/AirGoogleMaps/AIRGoogleMapManager.m index bbe206fb5..2f768f976 100644 --- a/lib/ios/AirGoogleMaps/AIRGoogleMapManager.m +++ b/lib/ios/AirGoogleMaps/AIRGoogleMapManager.m @@ -62,6 +62,7 @@ - (UIView *)view RCT_EXPORT_VIEW_PROPERTY(showsIndoorLevelPicker, BOOL) RCT_EXPORT_VIEW_PROPERTY(customMapStyleString, NSString) RCT_EXPORT_VIEW_PROPERTY(mapPadding, UIEdgeInsets) +RCT_REMAP_VIEW_PROPERTY(paddingAdjustmentBehavior, paddingAdjustmentBehaviorString, NSString) RCT_EXPORT_VIEW_PROPERTY(onMapReady, RCTBubblingEventBlock) RCT_EXPORT_VIEW_PROPERTY(onKmlReady, RCTBubblingEventBlock) RCT_EXPORT_VIEW_PROPERTY(onPress, RCTBubblingEventBlock) From 607c9edf35f6d618885b524cd2841c0a0037772d Mon Sep 17 00:00:00 2001 From: satori-ytolstoguzov <31261230+satori-ytolstoguzov@users.noreply.github.com> Date: Thu, 10 May 2018 03:57:20 -0700 Subject: [PATCH 0465/1148] Added support of lineDashPattern polyline prop to iOS Google Maps (#2243) --- lib/ios/AirGoogleMaps/AIRGoogleMapPolyline.h | 1 + lib/ios/AirGoogleMaps/AIRGoogleMapPolyline.m | 29 ++++++++++++++++++- .../AIRGoogleMapPolylineManager.m | 1 + 3 files changed, 30 insertions(+), 1 deletion(-) diff --git a/lib/ios/AirGoogleMaps/AIRGoogleMapPolyline.h b/lib/ios/AirGoogleMaps/AIRGoogleMapPolyline.h index adebc40d6..45f69eb35 100644 --- a/lib/ios/AirGoogleMaps/AIRGoogleMapPolyline.h +++ b/lib/ios/AirGoogleMaps/AIRGoogleMapPolyline.h @@ -21,6 +21,7 @@ @property (nonatomic, strong) UIColor *strokeColor; @property (nonatomic, assign) double strokeWidth; @property (nonatomic, assign) UIColor *fillColor; +@property (nonatomic, strong) NSArray *lineDashPattern; @property (nonatomic, assign) BOOL geodesic; @property (nonatomic, assign) NSString *title; @property (nonatomic, assign) int zIndex; diff --git a/lib/ios/AirGoogleMaps/AIRGoogleMapPolyline.m b/lib/ios/AirGoogleMaps/AIRGoogleMapPolyline.m index 881f17be6..250b92aa5 100644 --- a/lib/ios/AirGoogleMaps/AIRGoogleMapPolyline.m +++ b/lib/ios/AirGoogleMaps/AIRGoogleMapPolyline.m @@ -32,13 +32,16 @@ -(void)setCoordinates:(NSArray *)coordinates [path addCoordinate:coordinates[i].coordinate]; } - _polyline.path = path; + _polyline.path = path; + + [self configureStyleSpansIfNeeded]; } -(void)setStrokeColor:(UIColor *)strokeColor { _strokeColor = strokeColor; _polyline.strokeColor = strokeColor; + [self configureStyleSpansIfNeeded]; } -(void)setStrokeWidth:(double)strokeWidth @@ -53,6 +56,11 @@ -(void)setFillColor:(UIColor *)fillColor _polyline.spans = @[[GMSStyleSpan spanWithColor:fillColor]]; } +- (void)setLineDashPattern:(NSArray *)lineDashPattern { + _lineDashPattern = lineDashPattern; + [self configureStyleSpansIfNeeded]; +} + -(void)setGeodesic:(BOOL)geodesic { _geodesic = geodesic; @@ -81,4 +89,23 @@ - (void)setOnPress:(RCTBubblingEventBlock)onPress { _polyline.onPress = onPress; } +- (void)configureStyleSpansIfNeeded { + if (!_strokeColor || !_lineDashPattern || !_polyline.path) { + return; + } + + BOOL isLine = YES; + NSMutableArray *styles = [[NSMutableArray alloc] init]; + for (NSInteger i = 0; i < _lineDashPattern.count; i++) { + if (isLine) { + [styles addObject:[GMSStrokeStyle solidColor:_strokeColor]]; + } else { + [styles addObject:[GMSStrokeStyle solidColor:[UIColor clearColor]]]; + } + isLine = !isLine; + } + + _polyline.spans = GMSStyleSpans(_polyline.path, styles, _lineDashPattern, kGMSLengthRhumb); +} + @end diff --git a/lib/ios/AirGoogleMaps/AIRGoogleMapPolylineManager.m b/lib/ios/AirGoogleMaps/AIRGoogleMapPolylineManager.m index a7515c207..e4c49187f 100644 --- a/lib/ios/AirGoogleMaps/AIRGoogleMapPolylineManager.m +++ b/lib/ios/AirGoogleMaps/AIRGoogleMapPolylineManager.m @@ -34,6 +34,7 @@ - (UIView *)view RCT_EXPORT_VIEW_PROPERTY(fillColor, UIColor) RCT_EXPORT_VIEW_PROPERTY(strokeColor, UIColor) RCT_EXPORT_VIEW_PROPERTY(strokeWidth, double) +RCT_EXPORT_VIEW_PROPERTY(lineDashPattern, NSArray) RCT_EXPORT_VIEW_PROPERTY(geodesic, BOOL) RCT_EXPORT_VIEW_PROPERTY(zIndex, int) RCT_EXPORT_VIEW_PROPERTY(tappable, BOOL) From 29fb4a9228b6a7d33881c0d74e403f68b60e4bef Mon Sep 17 00:00:00 2001 From: funkyfourier Date: Sun, 13 May 2018 13:07:04 +0200 Subject: [PATCH 0466/1148] =?UTF-8?q?Make=20tiles=20display=20at=20the=20s?= =?UTF-8?q?ame=20physical=20size=20regardless=20of=20pixel=20dens=E2=80=A6?= =?UTF-8?q?=20(#2248)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Make tiles display at the same physical size regardless of pixel density on iOS devices * Fix for timestamp issue * Removed plus sign --- lib/ios/AirGoogleMaps/AIRGoogleMap.m | 2 +- lib/ios/AirGoogleMaps/AIRGoogleMapUrlTile.m | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/ios/AirGoogleMaps/AIRGoogleMap.m b/lib/ios/AirGoogleMaps/AIRGoogleMap.m index 171692a66..4205bd458 100644 --- a/lib/ios/AirGoogleMaps/AIRGoogleMap.m +++ b/lib/ios/AirGoogleMaps/AIRGoogleMap.m @@ -481,7 +481,7 @@ - (void)observeValueForKeyPath:(NSString *)keyPath @"latitude": @(location.coordinate.latitude), @"longitude": @(location.coordinate.longitude), @"altitude": @(location.altitude), - @"timestamp": @(location.timestamp), + @"timestamp": @(location.timestamp.timeIntervalSinceReferenceDate * 1000), @"accuracy": @(location.horizontalAccuracy), @"altitudeAccuracy": @(location.verticalAccuracy), @"speed": @(location.speed), diff --git a/lib/ios/AirGoogleMaps/AIRGoogleMapUrlTile.m b/lib/ios/AirGoogleMaps/AIRGoogleMapUrlTile.m index 39a53fc05..29eedb461 100644 --- a/lib/ios/AirGoogleMaps/AIRGoogleMapUrlTile.m +++ b/lib/ios/AirGoogleMaps/AIRGoogleMapUrlTile.m @@ -17,6 +17,7 @@ - (void)setUrlTemplate:(NSString *)urlTemplate { _urlTemplate = urlTemplate; _tileLayer = [GMSURLTileLayer tileLayerWithURLConstructor:[self _getTileURLConstructor]]; + _tileLayer.tileSize = [[UIScreen mainScreen] scale] * 256; } - (GMSTileURLConstructor)_getTileURLConstructor From 9ddd7a0d75a16b21c8561461fbee4d5e55040ebd Mon Sep 17 00:00:00 2001 From: Colin Basnett Date: Fri, 18 May 2018 04:08:22 -0700 Subject: [PATCH 0467/1148] Fix for compile error (#2215). (#2232) * Fix for compile error (#2215). * Addendum to previous commit, making `timestamp` return milliseconds instead of seconds to match with the Android implementation. * Update mapview.md Updated the documentation to reflect the arguments passed to `onUserLocationChange`. The documentation was missing parts of the data (`altitude`, `accuracy` etc.). I also made clear that the timestamp unit is in milliseconds since the Unix epoch time. --- docs/mapview.md | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/docs/mapview.md b/docs/mapview.md index 0a57bc2f2..471e8d981 100644 --- a/docs/mapview.md +++ b/docs/mapview.md @@ -50,7 +50,7 @@ To access event data, you will need to use `e.nativeEvent`. For example, `onPres | `onKmlReady` | `KmlContainer` | Callback that is called once the kml is fully loaded. | `onRegionChange` | `Region` | Callback that is called continuously when the region changes, such as when a user is dragging the map. | `onRegionChangeComplete` | `Region` | Callback that is called once when the region changes, such as when the user is done moving the map. -| `onUserLocationChange` | `{ coordinate: LatLng }` | Callback that is called when the underlying map figures our users current location (coordinate also includes isFromMockProvider value for Android API 18 and above). Make sure **showsUserLocation** is set to *true* and that the provider is `"google"`. +| `onUserLocationChange` | `{ coordinate: Location }` | Callback that is called when the underlying map figures our users current location (coordinate also includes isFromMockProvider value for Android API 18 and above). Make sure **showsUserLocation** is set to *true* and that the provider is `"google"`. | `onPress` | `{ coordinate: LatLng, position: Point }` | Callback that is called when user taps on the map. | `onPanDrag` | `{ coordinate: LatLng, position: Point }` | Callback that is called when user presses and drags the map. **NOTE**: for iOS `scrollEnabled` should be set to false to trigger the event | `onPoiClick` | `{ coordinate: LatLng, position: Point, placeId: string, name: string }` | Callback that is called when user click on a POI. @@ -100,6 +100,18 @@ type LatLng { } ``` +``` +type Location { + latitude: Number, + longitude: Number, + altitude: Number, + timestamp: Number, //Milliseconds since Unix epoch + accuracy: Number, + altitudeAccuracy: Number, + speed: Number, +} +``` + ``` type Point { x: Number, From 71b31911a060092ba3eb16a3a9b73fb6bcdfe62a Mon Sep 17 00:00:00 2001 From: Dan Federman Date: Wed, 6 Jun 2018 13:08:06 -0700 Subject: [PATCH 0468/1148] Fix CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF warnings (#2154) --- lib/ios/AirMaps/AIRMap.m | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/lib/ios/AirMaps/AIRMap.m b/lib/ios/AirMaps/AIRMap.m index 959dede7c..1e3e76193 100644 --- a/lib/ios/AirMaps/AIRMap.m +++ b/lib/ios/AirMaps/AIRMap.m @@ -424,18 +424,18 @@ - (void)cacheViewIfNeeded { - (void)updateLegalLabelInsets { if (_legalLabel) { dispatch_async(dispatch_get_main_queue(), ^{ - CGRect frame = _legalLabel.frame; - if (_legalLabelInsets.left) { - frame.origin.x = _legalLabelInsets.left; - } else if (_legalLabelInsets.right) { - frame.origin.x = self.frame.size.width - _legalLabelInsets.right - frame.size.width; + CGRect frame = self->_legalLabel.frame; + if (self->_legalLabelInsets.left) { + frame.origin.x = self->_legalLabelInsets.left; + } else if (self->_legalLabelInsets.right) { + frame.origin.x = self.frame.size.width - self->_legalLabelInsets.right - frame.size.width; } - if (_legalLabelInsets.top) { - frame.origin.y = _legalLabelInsets.top; - } else if (_legalLabelInsets.bottom) { - frame.origin.y = self.frame.size.height - _legalLabelInsets.bottom - frame.size.height; + if (self->_legalLabelInsets.top) { + frame.origin.y = self->_legalLabelInsets.top; + } else if (self->_legalLabelInsets.bottom) { + frame.origin.y = self.frame.size.height - self->_legalLabelInsets.bottom - frame.size.height; } - _legalLabel.frame = frame; + self->_legalLabel.frame = frame; }); } } From e9618d489c44a760a1a5912c59ebf4955b3362ce Mon Sep 17 00:00:00 2001 From: Ben Roth Date: Wed, 6 Jun 2018 13:11:53 -0700 Subject: [PATCH 0469/1148] [iOS] Prefix or eliminate globals in AIRMapMarker (#2306) --- lib/ios/AirMaps/AIRMapMarker.m | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/ios/AirMaps/AIRMapMarker.m b/lib/ios/AirMaps/AIRMapMarker.m index 9fc6c96f9..3795910b1 100644 --- a/lib/ios/AirMaps/AIRMapMarker.m +++ b/lib/ios/AirMaps/AIRMapMarker.m @@ -14,17 +14,18 @@ #import #import #import -NSInteger const CALLOUT_OPEN_ZINDEX_BASELINE = 999; + +NSInteger const AIR_CALLOUT_OPEN_ZINDEX_BASELINE = 999; @implementation AIREmptyCalloutBackgroundView -bool _calloutIsOpen = NO; -NSInteger _zIndexBeforeOpen = 0; @end @implementation AIRMapMarker { BOOL _hasSetCalloutOffset; RCTImageLoaderCancellationBlock _reloadImageCancellationBlock; MKPinAnnotationView *_pinView; + BOOL _calloutIsOpen; + NSInteger _zIndexBeforeOpen; } - (void)reactSetFrame:(CGRect)frame @@ -307,7 +308,7 @@ - (void)setPinColor:(UIColor *)pinColor - (void)setZIndex:(NSInteger)zIndex { _zIndexBeforeOpen = zIndex; - _zIndex = _calloutIsOpen ? zIndex + CALLOUT_OPEN_ZINDEX_BASELINE : zIndex; + _zIndex = _calloutIsOpen ? zIndex + AIR_CALLOUT_OPEN_ZINDEX_BASELINE : zIndex; self.layer.zPosition = zIndex; } From c8b5ac1bdc4df0051c3ac0c6a7f7a5f38597f7c0 Mon Sep 17 00:00:00 2001 From: Filipe Borges Date: Mon, 11 Jun 2018 17:32:32 -0300 Subject: [PATCH 0470/1148] Fix custom marker updates on android #1611 #2048 --- .../java/com/airbnb/android/react/maps/AirMapMarker.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapMarker.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapMarker.java index 4663b7109..1a1af3663 100644 --- a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapMarker.java +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapMarker.java @@ -300,8 +300,10 @@ public void setImage(String uri) { public MarkerOptions getMarkerOptions() { if (markerOptions == null) { - markerOptions = createMarkerOptions(); + markerOptions = new MarkerOptions(); } + + fillMarkerOptions(markerOptions); return markerOptions; } @@ -355,8 +357,8 @@ private BitmapDescriptor getIcon() { } } - private MarkerOptions createMarkerOptions() { - MarkerOptions options = new MarkerOptions().position(position); + private MarkerOptions fillMarkerOptions(MarkerOptions options) { + options.position(position); if (anchorIsSet) options.anchor(anchorX, anchorY); if (calloutAnchorIsSet) options.infoWindowAnchor(calloutAnchorX, calloutAnchorY); options.title(title); From d6d7a2708c55c120575ca68ca86a0b9f21763518 Mon Sep 17 00:00:00 2001 From: Mike Morris Date: Mon, 18 Jun 2018 13:53:55 -0400 Subject: [PATCH 0471/1148] Add react-native@^0.55 to peerDependencies (#2332) --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1f58b945e..6a83e0bc4 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,7 @@ ], "peerDependencies": { "react": "^16.0", - "react-native": "^0.51 || ^0.52 || ^0.53 || ^0.54", + "react-native": "^0.51 || ^0.52 || ^0.53 || ^0.54 || ^0.55", "prop-types": "^15.0 || ^16.0" }, "devDependencies": { From 72b0f77e31d18959e91acb036d5f91ab46e11ef2 Mon Sep 17 00:00:00 2001 From: Guilherme Eduardo Gulinoski Teixeira Date: Tue, 26 Jun 2018 06:42:08 -0300 Subject: [PATCH 0472/1148] Added animateToNavigation method to MapView (#2049) * added animateToNavigation method to MapView * Added AnimatedNavigation example * Updated Fork * Deleted IDE files and Unnecessary .class files --- docs/mapview.md | 1 + example/App.js | 2 + example/android/app/.project | 23 +++ .../maps/example/ExampleApplication.class | Bin 0 -> 2567 bytes .../react/maps/example/MainActivity.class | Bin 0 -> 1152 bytes example/examples/AnimatedNavigation.js | 137 ++++++++++++++++++ example/examples/assets/car.png | Bin 0 -> 2825 bytes index.d.ts | 1 + lib/android/.project | 23 +++ .../main/java/com/airbnb/android/react/maps | 0 .../android/react/maps/AirMapManager.java | 32 +++- .../airbnb/android/react/maps/AirMapView.java | 10 ++ lib/components/MapView.js | 4 + lib/ios/AirGoogleMaps/AIRGoogleMapManager.m | 23 +++ lib/ios/AirMaps/AIRMapManager.m | 24 +++ 15 files changed, 278 insertions(+), 2 deletions(-) create mode 100644 example/android/app/.project create mode 100644 example/android/app/bin/src/main/java/com/airbnb/android/react/maps/example/ExampleApplication.class create mode 100644 example/android/app/bin/src/main/java/com/airbnb/android/react/maps/example/MainActivity.class create mode 100644 example/examples/AnimatedNavigation.js create mode 100644 example/examples/assets/car.png create mode 100644 lib/android/.project create mode 100644 lib/android/bin/src/main/java/com/airbnb/android/react/maps diff --git a/docs/mapview.md b/docs/mapview.md index 471e8d981..80a8425e1 100644 --- a/docs/mapview.md +++ b/docs/mapview.md @@ -69,6 +69,7 @@ To access event data, you will need to use `e.nativeEvent`. For example, `onPres | Method Name | Arguments | Notes |---|---|---| +| `animateToNavigation` | `location: LatLng`, `bearing: Number`, `angle: Number`, `duration: Number` | | `animateToRegion` | `region: Region`, `duration: Number` | | `animateToCoordinate` | `coordinate: LatLng`, `duration: Number` | | `animateToBearing` | `bearing: Number`, `duration: Number` | diff --git a/example/App.js b/example/App.js index ebd4d8c80..7b6231e61 100644 --- a/example/App.js +++ b/example/App.js @@ -40,6 +40,7 @@ import MapKml from './examples/MapKml'; import BugMarkerWontUpdate from './examples/BugMarkerWontUpdate'; import ImageOverlayWithAssets from './examples/ImageOverlayWithAssets'; import ImageOverlayWithURL from './examples/ImageOverlayWithURL'; +import AnimatedNavigation from './examples/AnimatedNavigation'; import OnPoiClick from './examples/OnPoiClick'; const IOS = Platform.OS === 'ios'; @@ -159,6 +160,7 @@ class App extends React.Component { [BugMarkerWontUpdate, 'BUG: Marker Won\'t Update (Android)', true], [ImageOverlayWithAssets, 'Image Overlay Component with Assets', true], [ImageOverlayWithURL, 'Image Overlay Component with URL', true], + [AnimatedNavigation, 'Animated Map Navigation', true], [OnPoiClick, 'On Poi Click', true], ] // Filter out examples that are not yet supported for Google Maps on iOS. diff --git a/example/android/app/.project b/example/android/app/.project new file mode 100644 index 000000000..ca3856c62 --- /dev/null +++ b/example/android/app/.project @@ -0,0 +1,23 @@ + + + example-android + Project example-android created by Buildship. + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.buildship.core.gradleprojectbuilder + + + + + + org.eclipse.jdt.core.javanature + org.eclipse.buildship.core.gradleprojectnature + + diff --git a/example/android/app/bin/src/main/java/com/airbnb/android/react/maps/example/ExampleApplication.class b/example/android/app/bin/src/main/java/com/airbnb/android/react/maps/example/ExampleApplication.class new file mode 100644 index 0000000000000000000000000000000000000000..3ed43fa991ade2004952ac83f41a36fac1799b7e GIT binary patch literal 2567 zcmds3T~FIE6ussvZRp0=Hny=3!!}l4nwLF|X%a&qkOEB5A??vgOlwH&$Z;$97yA?Y z4U;x$d*6?mc9XVhDFMR7(;gbf?(xaF*T>iX{pb5n0C)pc3q}ZRCfau*CZu!B+RX7) z>3zlxt(7jp9Wow$lA0$f zZ1aGk-dKd01R87Qg*-~$QoCGlavE?yWEw#+^G{fV(g-(bY12wKTd~H@YPn zD4tNM42_uao75l|KaDY-K`zW2P7|`0N~{%Q?&uOxthAv$1uTxK&t&>NkJDac=b(M| zBFH1=b5E(0{|%cZx@AOoU0_!O2V9#&M2(`1nzNYO<;~cZU1EYn!oUfCsf?Tdh%%#c(vi`BVWiM`w!3A2=nw=#% ze0F&Uw`R6}#h7-m02D(O40Nc-YR^)MAPpw5@)>S?W54%?D4vv|oNC<4Xw{zy;!7 zXUxKWOBxaJZP^xyK#^-{$<0m<)MUH8q^_3WF@diI&Y0eeoUHx(+73l?H8+8hlIxl? z!%Og#z?a)oeLLpC#2%=Y_W7nrT`_<0;*cGm=&Wt&E16(*;L>afu9^0mXBI3Gm>iH| z!ArbmWH~xFx{Mwi${c~pjz|)$Ty-qw2`mC$FYw}nrh##oz_(F+x1fa2a&{p~`vCS2 zus_dMzQNsJ*c*Wvd`@Klq%#339Td#LJ?x=!cz~$+F6tq+7ug==ur21YEufz3*q-FD bE$6U}!ZTDe0?&bB3-B6$C5(CzUcjrrpsXkm literal 0 HcmV?d00001 diff --git a/example/android/app/bin/src/main/java/com/airbnb/android/react/maps/example/MainActivity.class b/example/android/app/bin/src/main/java/com/airbnb/android/react/maps/example/MainActivity.class new file mode 100644 index 0000000000000000000000000000000000000000..41f9343a16ddd63938a5e1b8c20d858cada4dd1e GIT binary patch literal 1152 zcmbtTT~8B16ur|H+AhUHEq>w0z*BkIeeuZ}BNB}y1rn$vzL?C;UfY4)na%99fnR2# ziN5=zjCZ$ffY4wQALcXXo;h>wy}$o_{|NvuVXF!y25&PfgG4ADoQbgrq)7syY^cLP z=*Sus1r~*L1WB_1FGP~Y7#t9OS2{IT?y?FM25UudEc75a3eQkF2FtINR_+aha%bn1 zL1oWGScN)+<`wq6wZ_(9g|RQ6w8hNCV~jXyNL4JHGMcB>gfS-BEAG|%L*x<4SXct3 zLY|8O@@+!<6UF{iv0o_mbH)Bt@ivbPW?UP`6XE2LJL1BNl$2iQA}=URX+M|fFUCC4 zrIOTGmrM7*3W=dH=UfV%KNupPea)*M=Vs2Vn}guaaKYVWieCL_jMl0M{{cI3R_Vdr zAP;J=+JGgv$6%w=yUM^MxSMCF*;5)1M@fjbFUWKTt)7u0J{4Bw=jmm|4OPbAUGIMj zr^}!{K$q9j9%bBU)b3Cu^lrPeb6X;V&Et`FD#3j{R+%D2yScwbosb}}H}k7ogGUVX z0u?ojxZAw?A`X*)6Em_BKd9Wg_3JHCloJ`hucgtM${hXlqe3gJ98&*0W3YOoE~@b2 zMoUfJXV5rMSw^|;Q+Z^t1=L&A$p9tVEx|I))uOY@v;**dK<#tO`v#3)1*S=JjsY5L xG&d$FScev!DsUg##I!L*J)reA+rv3*D|6V&@R;ID@B}t#1>iK6>HHL){{=LjOq&1z literal 0 HcmV?d00001 diff --git a/example/examples/AnimatedNavigation.js b/example/examples/AnimatedNavigation.js new file mode 100644 index 000000000..ce7b85f99 --- /dev/null +++ b/example/examples/AnimatedNavigation.js @@ -0,0 +1,137 @@ +import React, { Component } from 'react'; + +import { + View, + StyleSheet, + TouchableOpacity, + Text, +} from 'react-native'; + +import MapView from 'react-native-maps'; +import carImage from './assets/car.png'; + +export default class NavigationMap extends Component { + + constructor(props) { + super(props); + this.state = { + prevPos: null, + curPos: { latitude: 37.420814, longitude: -122.081949 }, + curAng: 45, + latitudeDelta: 0.0922, + longitudeDelta: 0.0421, + }; + this.changePosition = this.changePosition.bind(this); + this.getRotation = this.getRotation.bind(this); + this.updateMap = this.updateMap.bind(this); + } + + changePosition(latOffset, lonOffset) { + const latitude = this.state.curPos.latitude + latOffset; + const longitude = this.state.curPos.longitude + lonOffset; + this.setState({ prevPos: this.state.curPos, curPos: { latitude, longitude } }); + this.updateMap(); + } + + getRotation(prevPos, curPos) { + if (!prevPos) return 0; + const xDiff = curPos.latitude - prevPos.latitude; + const yDiff = curPos.longitude - prevPos.longitude; + return (Math.atan2(yDiff, xDiff) * 180.0) / Math.PI; + } + + updateMap() { + const { curPos, prevPos, curAng } = this.state; + const curRot = this.getRotation(prevPos, curPos); + this.map.animateToNavigation(curPos, curRot, curAng); + } + + render() { + return ( + + (this.map = el)} + style={styles.flex} + minZoomLevel={15} + initialRegion={{ + ...this.state.curPos, + latitudeDelta: this.state.latitudeDelta, + longitudeDelta: this.state.longitudeDelta, + }} + > + + + + this.changePosition(0.0001, 0)} + > + + Lat + + this.changePosition(-0.0001, 0)} + > + - Lat + + + + this.changePosition(0, -0.0001)} + > + - Lon + + this.changePosition(0, 0.0001)} + > + + Lon + + + + ); + } +} + +const styles = StyleSheet.create({ + flex: { + flex: 1, + width: '100%', + }, + buttonContainerUpDown: { + ...StyleSheet.absoluteFillObject, + flexDirection: 'row', + justifyContent: 'center', + }, + buttonContainerLeftRight: { + ...StyleSheet.absoluteFillObject, + flexDirection: 'column', + justifyContent: 'center', + }, + button: { + backgroundColor: 'rgba(100,100,100,0.2)', + position: 'absolute', + alignItems: 'center', + justifyContent: 'center', + borderRadius: 20, + height: 50, + width: 50, + }, + up: { + alignSelf: 'flex-start', + }, + down: { + alignSelf: 'flex-end', + }, + left: { + alignSelf: 'flex-start', + }, + right: { + alignSelf: 'flex-end', + }, +}); diff --git a/example/examples/assets/car.png b/example/examples/assets/car.png new file mode 100644 index 0000000000000000000000000000000000000000..ebe9aa16324ac187e48742ee0787913361421cea GIT binary patch literal 2825 zcmXw5c{J4B8~>WbOvqLldlL#XL}%V2Ym;pZ(!7>rrW#DyMk1n;vCY_vP?m%&p&6Op z?80jqB4N_lm*h7ISu;fZzWwo@XS?T~bI)_nb3dQwxpDS(mSP9w4gdfkhP5)ogVFGh zL4`nnc4s&M3^0Eymp}jzk^W->KvoVM+&t=Tg|`KOyJ`SHjRJtJJuuDzK#&dqe7^=B zeF^|FH&d^+TL8d;hgh?74k058*+fqT?qT*Ge~sZpnbE-dYGv(inMAJl z!kfc}PKrg~U(P(4D*oCMVVc!&IMx2LweDZ&L#wG6f87{7CQ8|wQ-GcljuKp6 zGidFBYZlN-K`Jg)@Z;KNiodGVxyCE>e_);Czyo0FDAgD+fIRvTzj^g65!wPnm;-wd z|2W-Xn(oF8_N{jgA`c;(DpZHRUo(Y=jpo}N%5k!W@NaV&eLFGvwg!9qppZp3sX z%-6l-&cCL}`}p`=A`;sN2BcQE42z44{pSYM2sQo!If1~V!{((oPGzoO^8I(O=LbL= zBxPY8j*8T<@1HcX1N}r0e&z4hdJU=y)Pws@r*wHtB(i6!|ItCnzphZlo)pyf<@5QY z%=wAnA^YbKe$7cdJ@L5f!mnSyf|q)O-V!nAU7a_@dG)p}d3boMs1mT(ZLnXgObh0-s(x=O~G`FTH;htM0( zL+8XZluc5srt;}ZBlzYz=FIXmZQs9Di(zT_>!YU$+(xz6kh~(VFPyG7@+U>aAVaekTZk6$=Xsb3GE`=2oCPc{f)kg)B?@CToW)b@2YodIcf6 zxMX5WI45M?51E=}kTdK`C@vX|I(^~GEyDTg?`8b#L8y~mbZn)ONF?Yp$m6$N2_T3UqHP?d^1!{hOu6j>KRh}>|n%7jwxyrmwGn2?YVRz<-f zmLv8F%Zc;Dln1>J7kjypNCG$@2>(69bwMNcYD5PWv9{QVOX$r~HNg?J56ZwCb-p4q7!NjT>?C=cOpY`Afm#7^GY zR8Ff-V%3iyKbkb-3*NJA9372J3=Fm{itt;8p|KV(COr~=e`38NP4Z_xWcE$B()&Mu zrfqG7!f65=G%4%2X8QZRaiXldm8z7dkI#8mSNXFB1}SzW{TxnIOUpTrH!g)7uZHyj zT*&rfwY;`yv!9pOmgS8byqk*bt>Lk;vG78=3m_9|HbJ2^N}F-e5*T}iQ^m*CLqMm; zDHF8ljLe|-TgebZ`R22Cjmr3vxa(Rj%=kn49T7Z$(ao_9Q#*-;looRu&Fv7OqgvFsM%AGD& zPF|{N(8Ru3Pts^G-f_@L?$hI?;OShRR~_?&hCAxP$xCpm8{8rh#73hqbvjfjfjy(; zAO`s)maem8kBEl$>boa;rBX&EfsomBXaA{Y0YXEF`uXaTJJ zWm|4l?3D#9?`|*6WZuYa>Fk8k==92ad_Rvj!}1x9AeKAW>|6iq$*fSQX=+jyH`!TE zdLe?)F)&EL!(|56>{coVYxrmIA}!l z(fOj-cT4Vmeg{eC7J{+)_CxEM#p>3Xx=zK+`Ci=)&6;`>(ygMl=+<Q_5DG9)o5jFoxD>;Z&Fk_5gWEko8_&Dv{tt$|gbPR3Z( z614BpNIP=R7lS{a8S*Q+gu=X^4fr`bOGXayhQHmgNdQ}=%)PsJr?!o?uf9u+5*GiL zg*tQ~reg(Uiy|EUNUYV~chqTndwVb@W`9zklGs4M_vvhgt*z}a3pJW)Q@lG(SFSTM zGJ0_5&Y6jOOGX~2WIeNJxF_1A$#-F30ca#DzOE{h)COOxtE)SzrKJ_;acb)xq7BX? z)Eb-K{Dq9%uTWOjd!;^DY;A4L^X5(Z(zXN!efmRW&0!j8nOGmJ4`M3WE6WEQ5X#{@ zx7IAL!xa?T2Fsl#lPvypIJe4J2hIK1)N3wB6xb1EWy@j8xx5y%tzL4JgXYgCgM))% zoA&0u-SKJeT-_jQ`Tb zT0q9T$sCBma?lqw)9q15_R6D}dwPlZ5xol$ zgO>_#2;bXX`+1jG!JYpUM8rZ7FoZfH`l2=V(&G$rt)7WV_-7XC(PH@OkkG_`a&~n| Z0N{8eXBHWc8H3+g0Bde%#>8BU{6A&!KLY>& literal 0 HcmV?d00001 diff --git a/index.d.ts b/index.d.ts index ab350f158..83d4f2fa3 100644 --- a/index.d.ts +++ b/index.d.ts @@ -215,6 +215,7 @@ declare module "react-native-maps" { } export default class MapView extends React.Component { + animateToNavigation(location: LatLng, bearing: number, angle: number, duration?: number): void; animateToRegion(region: Region, duration?: number): void; animateToCoordinate(latLng: LatLng, duration?: number): void; animateToBearing(bearing: number, duration?: number): void; diff --git a/lib/android/.project b/lib/android/.project new file mode 100644 index 000000000..2a84911fc --- /dev/null +++ b/lib/android/.project @@ -0,0 +1,23 @@ + + + react-native-maps-lib + Project react-native-maps-lib created by Buildship. + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.buildship.core.gradleprojectbuilder + + + + + + org.eclipse.jdt.core.javanature + org.eclipse.buildship.core.gradleprojectnature + + diff --git a/lib/android/bin/src/main/java/com/airbnb/android/react/maps b/lib/android/bin/src/main/java/com/airbnb/android/react/maps new file mode 100644 index 000000000..e69de29bb diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java index 43651f7e2..ee80725c1 100644 --- a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java @@ -22,6 +22,7 @@ import com.google.maps.android.data.kml.KmlLayer; import java.util.Map; +import java.util.HashMap; import javax.annotation.Nullable; @@ -36,6 +37,7 @@ public class AirMapManager extends ViewGroupManager { private static final int FIT_TO_SUPPLIED_MARKERS = 6; private static final int FIT_TO_COORDINATES = 7; private static final int SET_MAP_BOUNDARIES = 8; + private static final int ANIMATE_TO_NAVIGATION = 9; private final Map MAP_TYPES = MapBuilder.of( @@ -251,6 +253,17 @@ public void receiveCommand(AirMapView view, int commandId, @Nullable ReadableArr ReadableMap region; switch (commandId) { + case ANIMATE_TO_NAVIGATION: + region = args.getMap(0); + lng = region.getDouble("longitude"); + lat = region.getDouble("latitude"); + LatLng location = new LatLng(lat, lng); + bearing = (float)args.getDouble(1); + angle = (float)args.getDouble(2); + duration = args.getInt(3); + view.animateToNavigation(location, bearing, angle, duration); + break; + case ANIMATE_TO_REGION: region = args.getMap(0); duration = args.getInt(1); @@ -332,14 +345,15 @@ public Map getExportedCustomDirectEventTypeConstants() { @Nullable @Override public Map getCommandsMap() { - Map map = MapBuilder.of( + Map map = this.CreateMap( "animateToRegion", ANIMATE_TO_REGION, "animateToCoordinate", ANIMATE_TO_COORDINATE, "animateToViewingAngle", ANIMATE_TO_VIEWING_ANGLE, "animateToBearing", ANIMATE_TO_BEARING, "fitToElements", FIT_TO_ELEMENTS, "fitToSuppliedMarkers", FIT_TO_SUPPLIED_MARKERS, - "fitToCoordinates", FIT_TO_COORDINATES + "fitToCoordinates", FIT_TO_COORDINATES, + "animateToNavigation", ANIMATE_TO_NAVIGATION ); map.putAll(MapBuilder.of( @@ -349,6 +363,20 @@ public Map getCommandsMap() { return map; } + public static Map CreateMap( + K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6, K k7, V v7, K k8, V v8) { + Map map = new HashMap(); + map.put(k1, v1); + map.put(k2, v2); + map.put(k3, v3); + map.put(k4, v4); + map.put(k5, v5); + map.put(k6, v6); + map.put(k7, v7); + map.put(k8, v8); + return map; + } + @Override public LayoutShadowNode createShadowNodeInstance() { // A custom shadow node is needed in order to pass back the width/height of the map to the diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java index 6da24f6ab..e1adff97f 100644 --- a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java @@ -612,6 +612,16 @@ public void updateExtraData(Object extraData) { } } + public void animateToNavigation(LatLng location, float bearing, float angle, int duration) { + if (map == null) return; + CameraPosition cameraPosition = new CameraPosition.Builder(map.getCameraPosition()) + .bearing(bearing) + .tilt(angle) + .target(location) + .build(); + map.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition), duration, null); + } + public void animateToRegion(LatLngBounds bounds, int duration) { if (map == null) return; map.animateCamera(CameraUpdateFactory.newLatLngBounds(bounds, 0), duration, null); diff --git a/lib/components/MapView.js b/lib/components/MapView.js index b848beb4e..50c4d2657 100644 --- a/lib/components/MapView.js +++ b/lib/components/MapView.js @@ -549,6 +549,10 @@ class MapView extends React.Component { } } + animateToNavigation(location, bearing, angle, duration) { + this._runCommand('animateToNavigation', [location, bearing, angle, duration || 500]); + } + animateToRegion(region, duration) { this._runCommand('animateToRegion', [region, duration || 500]); } diff --git a/lib/ios/AirGoogleMaps/AIRGoogleMapManager.m b/lib/ios/AirGoogleMaps/AIRGoogleMapManager.m index 2f768f976..4ae089c1f 100644 --- a/lib/ios/AirGoogleMaps/AIRGoogleMapManager.m +++ b/lib/ios/AirGoogleMaps/AIRGoogleMapManager.m @@ -78,6 +78,29 @@ - (UIView *)view RCT_EXPORT_VIEW_PROPERTY(maxZoomLevel, CGFloat) RCT_EXPORT_VIEW_PROPERTY(kmlSrc, NSString) +RCT_EXPORT_METHOD(animateToNavigation:(nonnull NSNumber *)reactTag + withRegion:(MKCoordinateRegion)region + withBearing:(CGFloat)bearing + withAngle:(double)angle + withDuration:(CGFloat)duration) +{ + [self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary *viewRegistry) { + id view = viewRegistry[reactTag]; + if (![view isKindOfClass:[AIRGoogleMap class]]) { + RCTLogError(@"Invalid view returned from registry, expecting AIRGoogleMap, got: %@", view); + } else { + [CATransaction begin]; + [CATransaction setAnimationDuration:duration/1000]; + AIRGoogleMap *mapView = (AIRGoogleMap *)view; + GMSCameraPosition *camera = [AIRGoogleMap makeGMSCameraPositionFromMap:mapView andMKCoordinateRegion:region]; + [mapView animateToCameraPosition:camera]; + [mapView animateToViewingAngle:angle]; + [mapView animateToBearing:bearing]; + [CATransaction commit]; + } + }]; +} + RCT_EXPORT_METHOD(animateToRegion:(nonnull NSNumber *)reactTag withRegion:(MKCoordinateRegion)region withDuration:(CGFloat)duration) diff --git a/lib/ios/AirMaps/AIRMapManager.m b/lib/ios/AirMaps/AIRMapManager.m index b7fe67c0c..da1efc08e 100644 --- a/lib/ios/AirMaps/AIRMapManager.m +++ b/lib/ios/AirMaps/AIRMapManager.m @@ -129,6 +129,30 @@ - (UIView *)view #pragma mark exported MapView methods +RCT_EXPORT_METHOD(animateToNavigation:(nonnull NSNumber *)reactTag + withRegion:(MKCoordinateRegion)region + withBearing:(CGFloat)bearing + withAngle:(double)angle + withDuration:(CGFloat)duration) +{ + [self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary *viewRegistry) { + id view = viewRegistry[reactTag]; + if (![view isKindOfClass:[AIRMap class]]) { + RCTLogError(@"Invalid view returned from registry, expecting AIRMap, got: %@", view); + } else { + AIRMap *mapView = (AIRMap *)view; + MKMapCamera *mapCamera = [[mapView camera] copy]; + [mapCamera setPitch:angle]; + [mapCamera setHeading:bearing]; + + [AIRMap animateWithDuration:duration/1000 animations:^{ + [(AIRMap *)view setRegion:region animated:YES]; + [mapView setCamera:mapCamera animated:YES]; + }]; + } + }]; +} + RCT_EXPORT_METHOD(animateToRegion:(nonnull NSNumber *)reactTag withRegion:(MKCoordinateRegion)region withDuration:(CGFloat)duration) From ceed47f2297630c4616359f41d96a56eae76f1fd Mon Sep 17 00:00:00 2001 From: Ross Date: Thu, 28 Jun 2018 03:37:35 -0500 Subject: [PATCH 0473/1148] add support for calloutAnchor with GoogleMaps on iOS; fixes #1852 (#2351) * add support for calloutAnchor with GoogleMaps on iOS * update docs to specify platform specifics for calloutAnchor and calloutOffset --- docs/marker.md | 4 ++-- lib/ios/AirGoogleMaps/AIRGoogleMapMarker.h | 1 + lib/ios/AirGoogleMaps/AIRGoogleMapMarker.m | 5 +++++ lib/ios/AirGoogleMaps/AIRGoogleMapMarkerManager.m | 1 + 4 files changed, 9 insertions(+), 2 deletions(-) diff --git a/docs/marker.md b/docs/marker.md index 10490349c..53fdbedc3 100644 --- a/docs/marker.md +++ b/docs/marker.md @@ -10,9 +10,9 @@ | `pinColor` | `Color` | | If no custom marker view or custom image is provided, the platform default pin will be used, which can be customized by this color. Ignored if a custom marker is being used. | `coordinate` | `LatLng` | | The coordinate for the marker. | `centerOffset` | `Point` | (0, 0) | The offset (in points) at which to display the view.

By default, the center point of an annotation view is placed at the coordinate point of the associated annotation. You can use this property to reposition the annotation view as needed. This x and y offset values are measured in points. Positive offset values move the annotation view down and to the right, while negative values move it up and to the left.

For Google Maps, see the `anchor` prop. -| `calloutOffset` | `Point` | (0, 0) | The offset (in points) at which to place the callout bubble.

This property determines the additional distance by which to move the callout bubble. When this property is set to (0, 0), the anchor point of the callout bubble is placed on the top-center point of the marker view’s frame. Specifying positive offset values moves the callout bubble down and to the right, while specifying negative values moves it up and to the left.

For android, see the `calloutAnchor` prop. +| `calloutOffset` | `Point` | (0, 0) | The offset (in points) at which to place the callout bubble.

This property determines the additional distance by which to move the callout bubble. When this property is set to (0, 0), the anchor point of the callout bubble is placed on the top-center point of the marker view’s frame. Specifying positive offset values moves the callout bubble down and to the right, while specifying negative values moves it up and to the left.

For Google Maps, see the `calloutAnchor` prop. | `anchor` | `Point` | (0.5, 1) | Sets the anchor point for the marker.

The anchor specifies the point in the icon image that is anchored to the marker's position on the Earth's surface.

The anchor point is specified in the continuous space [0.0, 1.0] x [0.0, 1.0], where (0, 0) is the top-left corner of the image, and (1, 1) is the bottom-right corner. The anchoring point in a W x H image is the nearest discrete grid point in a (W + 1) x (H + 1) grid, obtained by scaling the then rounding. For example, in a 4 x 2 image, the anchor point (0.7, 0.6) resolves to the grid point at (3, 1).

For MapKit on iOS, see the `centerOffset` prop. -| `calloutAnchor` | `Point` | (0.5, 0) | Specifies the point in the marker image at which to anchor the callout when it is displayed. This is specified in the same coordinate system as the anchor. See the `anchor` prop for more details.

The default is the top middle of the image.

For ios, see the `calloutOffset` prop. +| `calloutAnchor` | `Point` | (0.5, 0) | Specifies the point in the marker image at which to anchor the callout when it is displayed. This is specified in the same coordinate system as the anchor. See the `anchor` prop for more details.

The default is the top middle of the image.

For MapKit on iOS, see the `calloutOffset` prop. | `flat` | `Boolean` | false | Sets whether this marker should be flat against the map true or a billboard facing the camera. | `identifier` | `String` | | An identifier used to reference this marker at a later date. | `rotation` | `Float` | 0 | A float number indicating marker's rotation angle, in degrees. diff --git a/lib/ios/AirGoogleMaps/AIRGoogleMapMarker.h b/lib/ios/AirGoogleMaps/AIRGoogleMapMarker.h index cc536d52b..ed4581aec 100644 --- a/lib/ios/AirGoogleMaps/AIRGoogleMapMarker.h +++ b/lib/ios/AirGoogleMaps/AIRGoogleMapMarker.h @@ -28,6 +28,7 @@ @property (nonatomic, copy) NSString *subtitle; @property (nonatomic, strong) UIColor *pinColor; @property (nonatomic, assign) CGPoint anchor; +@property (nonatomic, assign) CGPoint calloutAnchor; @property (nonatomic, assign) NSInteger zIndex; @property (nonatomic, assign) double opacity; @property (nonatomic, assign) BOOL draggable; diff --git a/lib/ios/AirGoogleMaps/AIRGoogleMapMarker.m b/lib/ios/AirGoogleMaps/AIRGoogleMapMarker.m index 12d556099..7f5a8803c 100644 --- a/lib/ios/AirGoogleMaps/AIRGoogleMapMarker.m +++ b/lib/ios/AirGoogleMaps/AIRGoogleMapMarker.m @@ -282,6 +282,11 @@ - (void)setAnchor:(CGPoint)anchor { _realMarker.groundAnchor = anchor; } +- (void)setCalloutAnchor:(CGPoint)calloutAnchor { + _calloutAnchor = calloutAnchor; + _realMarker.infoWindowAnchor = calloutAnchor; +} + - (void)setZIndex:(NSInteger)zIndex { diff --git a/lib/ios/AirGoogleMaps/AIRGoogleMapMarkerManager.m b/lib/ios/AirGoogleMaps/AIRGoogleMapMarkerManager.m index ff9b1afa7..a3d931d60 100644 --- a/lib/ios/AirGoogleMaps/AIRGoogleMapMarkerManager.m +++ b/lib/ios/AirGoogleMaps/AIRGoogleMapMarkerManager.m @@ -35,6 +35,7 @@ - (UIView *)view RCT_REMAP_VIEW_PROPERTY(description, subtitle, NSString) RCT_EXPORT_VIEW_PROPERTY(pinColor, UIColor) RCT_EXPORT_VIEW_PROPERTY(anchor, CGPoint) +RCT_EXPORT_VIEW_PROPERTY(calloutAnchor, CGPoint) RCT_EXPORT_VIEW_PROPERTY(zIndex, NSInteger) RCT_EXPORT_VIEW_PROPERTY(draggable, BOOL) RCT_EXPORT_VIEW_PROPERTY(tracksViewChanges, BOOL) From ecec7f37e2f9e8660c14423ae03fdb3e90d2f249 Mon Sep 17 00:00:00 2001 From: Billy Mathews Date: Tue, 3 Jul 2018 10:14:25 +0100 Subject: [PATCH 0474/1148] Fix readme formatting (#2358) --- docs/mapview.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/mapview.md b/docs/mapview.md index 80a8425e1..edbe23a85 100644 --- a/docs/mapview.md +++ b/docs/mapview.md @@ -8,7 +8,7 @@ | `region` | `Region` | | The region to be displayed by the map.

The region is defined by the center coordinates and the span of coordinates to display. | `initialRegion` | `Region` | | The initial region to be displayed by the map. Use this prop instead of `region` only if you don't want to control the viewport of the map besides the initial region.

Changing this prop after the component has mounted will not result in a region change.

This is similar to the `initialValue` prop of a text input. | `mapPadding` | `EdgePadding` | | Adds custom padding to each side of the map. Useful when map elements/markers are obscured. **Note** Google Maps only. -| `paddingAdjustmentBehavior` | 'always'|'automatic'|'never' | Indicates how/when to affect padding with safe area insets (`GoogleMaps` in iOS only) +| `paddingAdjustmentBehavior` | 'always'\|'automatic'\|'never' | 'never' | Indicates how/when to affect padding with safe area insets (`GoogleMaps` in iOS only) | `liteMode` | `Boolean` | `false` | Enable lite mode. **Note**: Android only. | `mapType` | `String` | `"standard"` | The map type to be displayed.

- standard: standard road map (default)
- none: no map
- satellite: satellite view
- hybrid: satellite view with roads and points of interest overlayed
- terrain: (Android only) topographic view
- mutedStandard: more subtle, makes markers/lines pop more (iOS 11.0+ only) | `customMapStyle` | `Array` | | Adds custom styling to the map component. See [README](https://github.com/airbnb/react-native-maps#customizing-the-map-style) for more information. From 080678b24f886c3b8104206f2f80452ee723243a Mon Sep 17 00:00:00 2001 From: Farid Date: Tue, 3 Jul 2018 17:05:44 +0300 Subject: [PATCH 0475/1148] zIndex doesn't work when the map moves in iOS 11 (#2359) --- lib/ios/AirMaps/AIRMapMarker.m | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/lib/ios/AirMaps/AIRMapMarker.m b/lib/ios/AirMaps/AIRMapMarker.m index 3795910b1..e5598f183 100644 --- a/lib/ios/AirMaps/AIRMapMarker.m +++ b/lib/ios/AirMaps/AIRMapMarker.m @@ -28,6 +28,14 @@ @implementation AIRMapMarker { NSInteger _zIndexBeforeOpen; } +- (instancetype)initWithFrame:(CGRect)frame { + self = [super initWithFrame:frame]; + if (self) { + [self.layer addObserver:self forKeyPath:@"zPosition" options:NSKeyValueObservingOptionNew context:nil]; + } + return self; +} + - (void)reactSetFrame:(CGRect)frame { // Make sure we use the image size when available @@ -312,4 +320,14 @@ - (void)setZIndex:(NSInteger)zIndex self.layer.zPosition = zIndex; } +- (void)dealloc { + [self.layer removeObserver:self forKeyPath:@"zPosition"]; +} + +- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { + if ([keyPath isEqualToString:@"zPosition"]) { + self.layer.zPosition = _zIndex; + } +} + @end From a71d04b015794308e342bb8f536862d7d4dd0ae5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Lorber?= Date: Wed, 4 Jul 2018 18:08:09 +0200 Subject: [PATCH 0476/1148] update doc (#2363) related to https://github.com/react-community/react-native-maps/issues/2237#issuecomment-402487329 --- docs/installation.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/installation.md b/docs/installation.md index eddda00c2..15835165e 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -104,6 +104,8 @@ Add to `ios/_YOUR_PROJECT_NAME_/AppDelegate.m: ... ``` +This should be the **first line** of the method. + ## Notes on running on a real ios device The steps are as described in https://facebook.github.io/react-native/docs/running-on-device.html , however instead of opening the .xcodeproj file you should open .xcworkspace file. @@ -204,6 +206,8 @@ If you have a blank map issue, ([#118](https://github.com/airbnb/react-native-ma ### On iOS: +If google logo/markers/polylines etc are displayed, this is likely an API key issue. Verify your API keys and their restrictions. Ensure the native `provideAPIKey` call is the first line of `didFinishLaunchingWithOptions`. + If you have ran 'react-native link` by mistake: 1. delete node_modules From 12211883d3f18a5649609785430376c1cdb36d47 Mon Sep 17 00:00:00 2001 From: Guillermo Orellana <172084+wiyarmir@users.noreply.github.com> Date: Wed, 18 Jul 2018 12:58:20 +0200 Subject: [PATCH 0477/1148] Update installation.md (#2381) Formatting, indentation and syntax highlight --- docs/installation.md | 232 +++++++++++++++++++++---------------------- 1 file changed, 116 insertions(+), 116 deletions(-) diff --git a/docs/installation.md b/docs/installation.md index 15835165e..acfbb2875 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -92,7 +92,7 @@ Have ran it already? Read [this](#on-ios). Add to `ios/_YOUR_PROJECT_NAME_/AppDelegate.m: -``` +```objc + @import GoogleMaps; //add this line if you want to use Google Maps @implementation AppDelegate @@ -115,85 +115,85 @@ The steps are as described in https://facebook.github.io/react-native/docs/runni 1. In your `android/app/build.gradle` add: - ```groovy - ... - dependencies { - ... - implementation project(':react-native-maps') - } - ``` +```groovy +... +dependencies { + ... + implementation project(':react-native-maps') +} +``` If you've defined *[project-wide properties](https://developer.android.com/studio/build/gradle-tips.html)* (**recommended**) in your root `build.gradle`, this library will detect the presence of the following properties: - ```groovy - buildscript {...} - allprojects {...} - - /** - + Project-wide Gradle configuration properties - */ - ext { - compileSdkVersion = 26 - targetSdkVersion = 26 - buildToolsVersion = "26.0.2" - supportLibVersion = "26.1.0" - googlePlayServicesVersion = "11.8.0" - androidMapsUtilsVersion = "0.5+" - } - ``` +```groovy +buildscript {...} +allprojects {...} + +/** + + Project-wide Gradle configuration properties + */ +ext { + compileSdkVersion = 26 + targetSdkVersion = 26 + buildToolsVersion = "26.0.2" + supportLibVersion = "26.1.0" + googlePlayServicesVersion = "11.8.0" + androidMapsUtilsVersion = "0.5+" +} +``` If you do **not** have *project-wide properties* defined and have a different play-services version than the one included in this library, use the following instead (switch 10.0.1 for the desired version): - ```groovy +```groovy +... +dependencies { ... - dependencies { - ... - implementation(project(':react-native-maps')){ - exclude group: 'com.google.android.gms', module: 'play-services-base' - exclude group: 'com.google.android.gms', module: 'play-services-maps' - } - implementation 'com.google.android.gms:play-services-base:10.0.1' - implementation 'com.google.android.gms:play-services-maps:10.0.1' + implementation(project(':react-native-maps')){ + exclude group: 'com.google.android.gms', module: 'play-services-base' + exclude group: 'com.google.android.gms', module: 'play-services-maps' } - ``` + implementation 'com.google.android.gms:play-services-base:10.0.1' + implementation 'com.google.android.gms:play-services-maps:10.0.1' +} +``` 2. In your `android/settings.gradle` add: - ```groovy - ... - include ':react-native-maps' - project(':react-native-maps').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-maps/lib/android') - ``` +```groovy +... +include ':react-native-maps' +project(':react-native-maps').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-maps/lib/android') +``` 3. Specify your Google Maps API Key: Add your API key to your manifest file (`android/app/src/main/AndroidManifest.xml`): - ```xml - - - - - ``` +```xml + + + + +``` > Note: As shown above, com.google.android.geo.API_KEY is the recommended metadata name for the API key. A key with this name can be used to authenticate to multiple Google Maps-based APIs on the Android platform, including the Google Maps Android API. For backwards compatibility, the API also supports the name com.google.android.maps.v2.API_KEY. This legacy name allows authentication to the Android Maps API v2 only. An application can specify only one of the API key metadata names. If both are specified, the API throws an exception. Source: https://developers.google.com/maps/documentation/android-api/signup 4. Add `import com.airbnb.android.react.maps.MapsPackage;` and `new MapsPackage()` in your `MainApplication.java` : - ``` - import com.airbnb.android.react.maps.MapsPackage; - ... - @Override - protected List getPackages() { - return Arrays.asList( - new MainReactPackage(), - new MapsPackage() - ); - } - ``` +```java +import com.airbnb.android.react.maps.MapsPackage; +... + @Override + protected List getPackages() { + return Arrays.asList( + new MainReactPackage(), + new MapsPackage() + ); + } +``` 5. Ensure that you have Google Play Services installed: @@ -224,57 +224,57 @@ If you use Xcode with version less than 9 you may get `use of undeclared identif 1. Be sure to have `new MapsPackage()` in your `MainApplication.java` : - ``` - import com.airbnb.android.react.maps.MapsPackage; - ... - @Override - protected List getPackages() { - return Arrays.asList( - new MainReactPackage(), - new MapsPackage() - ); - } - ``` +```java +import com.airbnb.android.react.maps.MapsPackage; +... + @Override + protected List getPackages() { + return Arrays.asList( + new MainReactPackage(), + new MapsPackage() + ); + } +``` 1. Set this Stylesheet in your map component - ``` - import MapView from 'react-native-maps'; - ... - const styles = StyleSheet.create({ - container: { - ...StyleSheet.absoluteFillObject, - height: 400, - width: 400, - justifyContent: 'flex-end', - alignItems: 'center', - }, - map: { - ...StyleSheet.absoluteFillObject, - }, - }); - - export default class MyApp extends React.Component { - render() { - const { region } = this.props; - console.log(region); - - return ( - - - - - ); - } - } - ``` +```jsx +import MapView from 'react-native-maps'; +... +const styles = StyleSheet.create({ + container: { + ...StyleSheet.absoluteFillObject, + height: 400, + width: 400, + justifyContent: 'flex-end', + alignItems: 'center', + }, + map: { + ...StyleSheet.absoluteFillObject, + }, +}); + +export default class MyApp extends React.Component { + render() { + const { region } = this.props; + console.log(region); + + return ( + + + + + ); + } +} +``` 1. Run "android" and make sure all packages are up-to-date. 1. If not installed yet, you have to install the following packages : - Extras / Google Play services @@ -287,21 +287,21 @@ Select `Google Maps Android API` and create a new key. Enter the name of the API key and create it. 1. Clean the cache : - ``` - watchman watch-del-all - npm cache clean - ``` +``` +watchman watch-del-all +npm cache clean +``` 1. When starting emulator, make sure you have enabled `Wipe user data`. 1. Run `react-native run-android` 1. If you encounter `com.android.dex.DexException: Multiple dex files define Landroid/support/v7/appcompat/R$anim`, then clear build folder. - ``` - cd android - ./gradlew clean - cd .. - ``` +``` +cd android +./gradlew clean +cd .. +``` 1. If you are using Android Virtual Devices (AVD), ensure that `Use Host GPU` is checked in the settings for your virtual device. From b9ec81b2fb539aeda0c7f399c90cd0eff5c3b0ea Mon Sep 17 00:00:00 2001 From: Kruy Vanna Date: Wed, 18 Jul 2018 17:59:39 +0700 Subject: [PATCH 0478/1148] Android: Fix lineCap of Polyline (#2375) * Android: Fix lineCap of Polyline * update Polyline docs on lineCap property * Fix docs: update Polyline docs on lineCap property --- docs/polyline.md | 2 +- .../android/react/maps/AirMapPolyline.java | 13 ++++++++++ .../react/maps/AirMapPolylineManager.java | 24 +++++++++++++++++++ 3 files changed, 38 insertions(+), 1 deletion(-) diff --git a/docs/polyline.md b/docs/polyline.md index 6e8aaa26e..873b708ca 100644 --- a/docs/polyline.md +++ b/docs/polyline.md @@ -8,7 +8,7 @@ | `strokeWidth` | `Number` | `1` | The stroke width to use for the path. | `strokeColor` | `String` | `#000` | The stroke color to use for the path. | `strokeColors` | `Array` | `null` | The stroke colors to use for the path (iOS only). Must be the same length as `coordinates`. -| `lineCap` | `String` | `round` | The line cap style to apply to the open ends of the path. Possible values are `butt`, `round` or `square`. +| `lineCap` | `String` | `round` | The line cap style to apply to the open ends of the path. Possible values are `butt`, `round` or `square`. Note: lineCap is not yet supported for GoogleMaps provider on iOS. | `lineJoin` | `String` | `round` | The line join style to apply to corners of the path. Possible values are `miter`, `round` or `bevel`. | `miterLimit` | `Number` | | The limiting value that helps avoid spikes at junctions between connected line segments. The miter limit helps you avoid spikes in paths that use the `miter` `lineJoin` style. If the ratio of the miter length—that is, the diagonal length of the miter join—to the line thickness exceeds the miter limit, the joint is converted to a bevel join. The default miter limit is 10, which results in the conversion of miters whose angle at the joint is less than 11 degrees. | `geodesic` | `Boolean` | | Boolean to indicate whether to draw each segment of the line as a geodesic as opposed to straight lines on the Mercator projection. A geodesic is the shortest path between two points on the Earth's surface. The geodesic curve is constructed assuming the Earth is a sphere. diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapPolyline.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapPolyline.java index 488e2972f..28a13c418 100644 --- a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapPolyline.java +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapPolyline.java @@ -5,9 +5,11 @@ import com.facebook.react.bridge.ReadableArray; import com.facebook.react.bridge.ReadableMap; import com.google.android.gms.maps.GoogleMap; +import com.google.android.gms.maps.model.Cap; import com.google.android.gms.maps.model.LatLng; import com.google.android.gms.maps.model.Polyline; import com.google.android.gms.maps.model.PolylineOptions; +import com.google.android.gms.maps.model.RoundCap; import java.util.ArrayList; import java.util.List; @@ -22,6 +24,7 @@ public class AirMapPolyline extends AirMapFeature { private float width; private boolean geodesic; private float zIndex; + private Cap lineCap = new RoundCap(); public AirMapPolyline(Context context) { super(context); @@ -67,6 +70,14 @@ public void setGeodesic(boolean geodesic) { } } + public void setLineCap(Cap cap) { + this.lineCap = cap; + if (polyline != null) { + polyline.setStartCap(cap); + polyline.setEndCap(cap); + } + } + public PolylineOptions getPolylineOptions() { if (polylineOptions == null) { polylineOptions = createPolylineOptions(); @@ -81,6 +92,8 @@ private PolylineOptions createPolylineOptions() { options.width(width); options.geodesic(geodesic); options.zIndex(zIndex); + options.startCap(lineCap); + options.endCap(lineCap); return options; } diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapPolylineManager.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapPolylineManager.java index be80acfbc..b17699b33 100644 --- a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapPolylineManager.java +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapPolylineManager.java @@ -12,6 +12,10 @@ import com.facebook.react.uimanager.ThemedReactContext; import com.facebook.react.uimanager.ViewGroupManager; import com.facebook.react.uimanager.annotations.ReactProp; +import com.google.android.gms.maps.model.ButtCap; +import com.google.android.gms.maps.model.Cap; +import com.google.android.gms.maps.model.RoundCap; +import com.google.android.gms.maps.model.SquareCap; import java.util.Map; @@ -68,6 +72,26 @@ public void setZIndex(AirMapPolyline view, float zIndex) { view.setZIndex(zIndex); } + @ReactProp(name = "lineCap") + public void setlineCap(AirMapPolyline view, String lineCap) { + Cap cap = null; + switch (lineCap) { + case "butt": + cap = new ButtCap(); + break; + case "round": + cap = new RoundCap(); + break; + case "square": + cap = new SquareCap(); + break; + default: + cap = new RoundCap(); + break; + } + view.setLineCap(cap); + } + @Override @Nullable public Map getExportedCustomDirectEventTypeConstants() { From 79c7babc7ca899057d06dccad68c620dee71c1d8 Mon Sep 17 00:00:00 2001 From: Kyle Decot Date: Wed, 18 Jul 2018 10:55:48 -0400 Subject: [PATCH 0479/1148] Fixes warnings about self (#2341) --- lib/ios/AirGoogleMaps/AIRGoogleMapMarker.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/ios/AirGoogleMaps/AIRGoogleMapMarker.m b/lib/ios/AirGoogleMaps/AIRGoogleMapMarker.m index 7f5a8803c..186cc8f5c 100644 --- a/lib/ios/AirGoogleMaps/AIRGoogleMapMarker.m +++ b/lib/ios/AirGoogleMaps/AIRGoogleMapMarker.m @@ -224,7 +224,7 @@ - (void)setImageSrc:(NSString *)imageSrc dispatch_async(dispatch_get_main_queue(), ^{ // TODO(gil): This way allows different image sizes - if (_iconImageView) [_iconImageView removeFromSuperview]; + if (self->_iconImageView) [self->_iconImageView removeFromSuperview]; // ... but this way is more efficient? // if (_iconImageView) { @@ -250,7 +250,7 @@ - (void)setImageSrc:(NSString *)imageSrc CGRect selfBounds = unionRect(bounds, self.bounds); [self setFrame:selfBounds]; - _iconImageView = imageView; + self->_iconImageView = imageView; [self iconViewInsertSubview:imageView atIndex:0]; }); }]; From a1254889cdd373b62a094257e7c847e2375904ac Mon Sep 17 00:00:00 2001 From: Basit Ali Date: Wed, 18 Jul 2018 19:56:21 +0500 Subject: [PATCH 0480/1148] Fix disabling the toolbar and my location button (#2317) --- .../main/java/com/airbnb/android/react/maps/AirMapView.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java index e1adff97f..5882f8cab 100644 --- a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java @@ -439,13 +439,13 @@ public void setShowsUserLocation(boolean showUserLocation) { } public void setShowsMyLocationButton(boolean showMyLocationButton) { - if (hasPermissions()) { + if (hasPermissions() || !showMyLocationButton) { map.getUiSettings().setMyLocationButtonEnabled(showMyLocationButton); } } public void setToolbarEnabled(boolean toolbarEnabled) { - if (hasPermissions()) { + if (hasPermissions() || !toolbarEnabled) { map.getUiSettings().setMapToolbarEnabled(toolbarEnabled); } } From 2d760e19b111ba2721ca8f6dfde9e4339939ff1f Mon Sep 17 00:00:00 2001 From: Christoph Date: Thu, 19 Jul 2018 11:32:36 +0200 Subject: [PATCH 0481/1148] Added MBTiles support for iOS and Android (#2208) * Added MBTiles support for iOS and Android * Added changes regarding the comments of @h3ll0w0rld123 from here: https://github.com/react-community/react-native-maps/pull/2208#discussion_r182597094 * Added whitespaces * Hotfix: Imported exceptions. Changed database.close() * Hotfix: Removed the finally statemend. Resulted in always returning null * Removed repetition of returns. Moved everything into finally statement instead * Throwing exceptions * Added MapView.MbTile to Readme. Inclduded the component in the Readme * Added example file * Included more information in Readme * Edited example file accodring to linter errors in Pull Request * Edited index.d.ts according to merge conflicts in Pull Request. Had to change a few lines * Edited example file according to linter errors in merge request * Edited example file according to linter errors in merge request. I am starting not to like Travis... * Edited example file according to linter errors in merge request. I am starting not to like Travis... --- README.md | 33 + example/examples/MbTileOverlay.js | 91 + index.d.ts | 11 +- index.js | 16 +- .../android/react/maps/AirMapMbTile.java | 150 ++ .../react/maps/AirMapMbTileManager.java | 56 + .../airbnb/android/react/maps/AirMapView.java | 165 +- .../android/react/maps/MapsPackage.java | 2 + lib/components/MapMbTile.js | 71 + lib/components/MapView.js | 63 +- lib/ios/AirMaps.xcodeproj/project.pbxproj | 50 + lib/ios/AirMaps/AIRMap.m | 41 +- lib/ios/AirMaps/AIRMapManager.m | 77 +- lib/ios/AirMaps/AIRMapMbTile.h | 47 + lib/ios/AirMaps/AIRMapMbTile.m | 68 + lib/ios/AirMaps/AIRMapMbTileManager.h | 14 + lib/ios/AirMaps/AIRMapMbTileManager.m | 40 + lib/ios/AirMaps/AIRMapMbTileOverlay.h | 15 + lib/ios/AirMaps/AIRMapMbTileOverlay.m | 45 + lib/ios/AirMaps/fmdb/FMDB.h | 10 + lib/ios/AirMaps/fmdb/FMDatabase.h | 1360 ++++++++++++++ lib/ios/AirMaps/fmdb/FMDatabase.m | 1596 +++++++++++++++++ lib/ios/AirMaps/fmdb/FMDatabaseAdditions.h | 250 +++ lib/ios/AirMaps/fmdb/FMDatabaseAdditions.m | 245 +++ lib/ios/AirMaps/fmdb/FMDatabasePool.h | 258 +++ lib/ios/AirMaps/fmdb/FMDatabasePool.m | 316 ++++ lib/ios/AirMaps/fmdb/FMDatabaseQueue.h | 235 +++ lib/ios/AirMaps/fmdb/FMDatabaseQueue.m | 270 +++ lib/ios/AirMaps/fmdb/FMResultSet.h | 467 +++++ lib/ios/AirMaps/fmdb/FMResultSet.m | 432 +++++ 30 files changed, 6224 insertions(+), 270 deletions(-) create mode 100644 example/examples/MbTileOverlay.js mode change 100644 => 100755 index.d.ts mode change 100644 => 100755 index.js create mode 100644 lib/android/src/main/java/com/airbnb/android/react/maps/AirMapMbTile.java create mode 100644 lib/android/src/main/java/com/airbnb/android/react/maps/AirMapMbTileManager.java mode change 100644 => 100755 lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java mode change 100644 => 100755 lib/android/src/main/java/com/airbnb/android/react/maps/MapsPackage.java create mode 100644 lib/components/MapMbTile.js mode change 100644 => 100755 lib/components/MapView.js mode change 100644 => 100755 lib/ios/AirMaps/AIRMap.m mode change 100644 => 100755 lib/ios/AirMaps/AIRMapManager.m create mode 100644 lib/ios/AirMaps/AIRMapMbTile.h create mode 100644 lib/ios/AirMaps/AIRMapMbTile.m create mode 100644 lib/ios/AirMaps/AIRMapMbTileManager.h create mode 100644 lib/ios/AirMaps/AIRMapMbTileManager.m create mode 100644 lib/ios/AirMaps/AIRMapMbTileOverlay.h create mode 100644 lib/ios/AirMaps/AIRMapMbTileOverlay.m create mode 100644 lib/ios/AirMaps/fmdb/FMDB.h create mode 100644 lib/ios/AirMaps/fmdb/FMDatabase.h create mode 100644 lib/ios/AirMaps/fmdb/FMDatabase.m create mode 100644 lib/ios/AirMaps/fmdb/FMDatabaseAdditions.h create mode 100644 lib/ios/AirMaps/fmdb/FMDatabaseAdditions.m create mode 100755 lib/ios/AirMaps/fmdb/FMDatabasePool.h create mode 100755 lib/ios/AirMaps/fmdb/FMDatabasePool.m create mode 100755 lib/ios/AirMaps/fmdb/FMDatabaseQueue.h create mode 100755 lib/ios/AirMaps/fmdb/FMDatabaseQueue.m create mode 100644 lib/ios/AirMaps/fmdb/FMResultSet.h create mode 100644 lib/ios/AirMaps/fmdb/FMResultSet.m diff --git a/README.md b/README.md index e6e08cf7f..c5f02e97a 100644 --- a/README.md +++ b/README.md @@ -221,6 +221,39 @@ For Android: LocalTile is still just overlay over original map tiles. It means t See [OSM Wiki](https://wiki.openstreetmap.org/wiki/Category:Tile_downloading) for how to download tiles for offline usage. + +#### Tile Overlay using MbTile + +Tiles can be stored locally in a MBTiles database on the device using xyz tiling scheme. The locally stored tiles can be displayed as a tile overlay. This can be used for displaying maps offline. Manging many tiles in a database is especially useful if larger areas are covered by an offline map. Keeping all the files locally and "raw" on the device most likely results in bad performance as well as troublesome datahandling. Please make sure that your database follows the MBTiles [specifications](https://github.com/mapbox/mbtiles-spec). This only works with tiles stored in the [xyz scheme](https://gist.github.com/tmcw/4954720) as used by Google, OSM, MapBox, ... Make sure to include the ending .mbtiles when you pass your pathTemplate. + +```jsx +import MapView from 'react-native-maps'; + + + + +``` + +For Android: LocalTile is still just overlay over original map tiles. It means that if device is online, underlying tiles will be still downloaded. If original tiles download/display is not desirable set mapType to 'none'. For example: +``` + +``` + ### Customizing the map style Create the json object, or download a generated one from the [google style generator](https://mapstyle.withgoogle.com/). diff --git a/example/examples/MbTileOverlay.js b/example/examples/MbTileOverlay.js new file mode 100644 index 000000000..cfb185147 --- /dev/null +++ b/example/examples/MbTileOverlay.js @@ -0,0 +1,91 @@ +import React, { Component } from 'react'; +import { + StyleSheet, + View, + Dimensions, + TouchableOpacity, + Text, + Platform, +} from 'react-native'; +import MapView from 'react-native-maps'; + +const { width, height } = Dimensions.get('window'); + +const ASPECT_RATIO = width / height; +const LATITUDE = 23.736906; +const LONGITUDE = 90.397768; +const LATITUDE_DELTA = 0.022; +const LONGITUDE_DELTA = LATITUDE_DELTA * ASPECT_RATIO; + + +type Props = {}; +export default class App extends Component { + constructor(props) { + super(props); + + this.state = { + offlineMap: false, + }; + } + + _toggleOfflineMap = () => { + this.setState({ + offlineMap: !this.state.offlineMap, + }); + } + + render() { + return ( + + + {this.state.offlineMap ? + : null} + + this._toggleOfflineMap()} + > + {this.state.offlineMap ? 'Switch to Online Map' : 'Switch to Offline Map'} + + + ); + } +} + +const styles = StyleSheet.create({ + container: { + ...StyleSheet.absoluteFillObject, + alignItems: 'center', + }, + button: { + position: 'absolute', + bottom: 20, + backgroundColor: 'lightblue', + zIndex: 999999, + height: 50, + width: width / 2, + borderRadius: width / 2, + justifyContent: 'center', + alignItems: 'center', + }, + map: { + ...StyleSheet.absoluteFillObject, + }, +}); diff --git a/index.d.ts b/index.d.ts old mode 100644 new mode 100755 index 83d4f2fa3..f380d3c15 --- a/index.d.ts +++ b/index.d.ts @@ -366,7 +366,7 @@ declare module "react-native-maps" { } // ======================================================================= - // UrlTile & LocalTile + // UrlTile, LocalTile & MbTile // ======================================================================= export interface MapUrlTileProps extends ViewProperties { @@ -387,6 +387,15 @@ declare module "react-native-maps" { export class LocalTile extends React.Component { } + export interface MapMbTileProps extends ViewProperties { + pathTemplate: string; + tileSize: number; + zIndex?: number; + } + + export class MbTile extends React.Component { + } + // ======================================================================= // Overlay // ======================================================================= diff --git a/index.js b/index.js old mode 100644 new mode 100755 index acc1f7553..841cd16cd --- a/index.js +++ b/index.js @@ -1,23 +1,17 @@ -import MapView, { Animated, MAP_TYPES, ProviderPropType } from './lib/components/MapView'; -import Marker from './lib/components/MapMarker.js'; -import Overlay from './lib/components/MapOverlay.js'; +import MapView from './lib/components/MapView'; +export { default as Marker } from './lib/components/MapMarker.js'; export { default as Polyline } from './lib/components/MapPolyline.js'; export { default as Polygon } from './lib/components/MapPolygon.js'; export { default as Circle } from './lib/components/MapCircle.js'; export { default as UrlTile } from './lib/components/MapUrlTile.js'; export { default as LocalTile } from './lib/components/MapLocalTile.js'; +export { default as MbTile } from './lib/components/MapMbTile.js'; +export { default as Overlay } from './lib/components/MapOverlay.js'; export { default as Callout } from './lib/components/MapCallout.js'; export { default as AnimatedRegion } from './lib/components/AnimatedRegion.js'; - -export { Marker, Overlay }; -export { Animated, MAP_TYPES, ProviderPropType }; - +export { Animated, ProviderPropType, MAP_TYPES } from './lib/components/MapView.js'; export const PROVIDER_GOOGLE = MapView.PROVIDER_GOOGLE; export const PROVIDER_DEFAULT = MapView.PROVIDER_DEFAULT; -export const MarkerAnimated = Marker.Animated; -export const OverlayAnimated = Overlay.Animated; - export default MapView; - diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapMbTile.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapMbTile.java new file mode 100644 index 000000000..0c948adef --- /dev/null +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapMbTile.java @@ -0,0 +1,150 @@ +package com.airbnb.android.react.maps; + +import android.content.Context; + +import com.google.android.gms.maps.GoogleMap; +import com.google.android.gms.maps.model.Tile; +import com.google.android.gms.maps.model.TileOverlay; +import com.google.android.gms.maps.model.TileOverlayOptions; +import com.google.android.gms.maps.model.TileProvider; + +import java.io.File; + +import android.os.Environment; +import android.database.sqlite.SQLiteDatabase; +import android.database.sqlite.SQLiteCantOpenDatabaseException; +import android.database.sqlite.SQLiteDatabaseCorruptException; +import android.database.sqlite.SQLiteDatabaseLockedException; +import android.database.Cursor; + +/** + * Created by Christoph Lambio on 30/03/2018. + * Based on AirMapLocalTileManager.java + * Copyright (c) zavadpe + */ + +public class AirMapMbTile extends AirMapFeature { + + class AIRMapMbTileProvider implements TileProvider { + private static final int BUFFER_SIZE = 16 * 1024; + private int tileSize; + private String pathTemplate; + + + public AIRMapMbTileProvider(int tileSizet, String pathTemplate) { + this.tileSize = tileSizet; + this.pathTemplate = pathTemplate; + } + + @Override + public Tile getTile(int x, int y, int zoom) { + byte[] image = readTileImage(x, y, zoom); + return image == null ? TileProvider.NO_TILE : new Tile(this.tileSize, this.tileSize, image); + } + + public void setPathTemplate(String pathTemplate) { + this.pathTemplate = pathTemplate; + } + + public void setTileSize(int tileSize) { + this.tileSize = tileSize; + } + + private byte[] readTileImage(int x, int y, int zoom) { + String rawQuery = "SELECT * FROM map INNER JOIN images ON map.tile_id = images.tile_id WHERE map.zoom_level = {z} AND map.tile_column = {x} AND map.tile_row = {y}"; + byte[] tile = null; + try { + SQLiteDatabase offlineDataDatabase = SQLiteDatabase.openDatabase(this.pathTemplate, null, SQLiteDatabase.OPEN_READONLY); + String query = rawQuery.replace("{x}", Integer.toString(x)) + .replace("{y}", Integer.toString(y)) + .replace("{z}", Integer.toString(zoom)); + Cursor cursor = offlineDataDatabase.rawQuery(query, null); + if (cursor.moveToFirst()) { + tile = cursor.getBlob(5); + } + cursor.close(); + offlineDataDatabase.close(); + } catch (SQLiteCantOpenDatabaseException e) { + e.printStackTrace(); + throw e; + } catch (SQLiteDatabaseCorruptException e) { + e.printStackTrace(); + throw e; + } catch (SQLiteDatabaseLockedException e) { + e.printStackTrace(); + throw e; + } catch (Exception e) { + e.printStackTrace(); + throw e; + } finally { + return tile; + } + } + } + + private TileOverlayOptions tileOverlayOptions; + private TileOverlay tileOverlay; + private AirMapMbTile.AIRMapMbTileProvider tileProvider; + + private String pathTemplate; + private float tileSize; + private float zIndex; + + public AirMapMbTile(Context context) { + super(context); + } + + public void setPathTemplate(String pathTemplate) { + this.pathTemplate = pathTemplate; + if (tileProvider != null) { + tileProvider.setPathTemplate(pathTemplate); + } + if (tileOverlay != null) { + tileOverlay.clearTileCache(); + } + } + + public void setZIndex(float zIndex) { + this.zIndex = zIndex; + if (tileOverlay != null) { + tileOverlay.setZIndex(zIndex); + } + } + + public void setTileSize(float tileSize) { + this.tileSize = tileSize; + if (tileProvider != null) { + tileProvider.setTileSize((int)tileSize); + } + } + + public TileOverlayOptions getTileOverlayOptions() { + if (tileOverlayOptions == null) { + tileOverlayOptions = createTileOverlayOptions(); + } + return tileOverlayOptions; + } + + private TileOverlayOptions createTileOverlayOptions() { + TileOverlayOptions options = new TileOverlayOptions(); + options.zIndex(zIndex); + this.tileProvider = new AirMapMbTile.AIRMapMbTileProvider((int)this.tileSize, this.pathTemplate); + options.tileProvider(this.tileProvider); + return options; + } + + @Override + public Object getFeature() { + return tileOverlay; + } + + @Override + public void addToMap(GoogleMap map) { + this.tileOverlay = map.addTileOverlay(getTileOverlayOptions()); + } + + @Override + public void removeFromMap(GoogleMap map) { + tileOverlay.remove(); + } +} diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapMbTileManager.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapMbTileManager.java new file mode 100644 index 000000000..cb3e2e549 --- /dev/null +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapMbTileManager.java @@ -0,0 +1,56 @@ +package com.airbnb.android.react.maps; + +import android.content.Context; +import android.os.Build; +import android.util.DisplayMetrics; +import android.view.WindowManager; + +import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.uimanager.ThemedReactContext; +import com.facebook.react.uimanager.ViewGroupManager; +import com.facebook.react.uimanager.annotations.ReactProp; + +/** + * Created by Christoph Lambio on 30/03/2018. + * Based on AirMapLocalTileManager.java + * Copyright (c) zavadpe + */ +public class AirMapMbTileManager extends ViewGroupManager { + private DisplayMetrics metrics; + + public AirMapMbTileManager(ReactApplicationContext reactContext) { + super(); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { + metrics = new DisplayMetrics(); + ((WindowManager) reactContext.getSystemService(Context.WINDOW_SERVICE)) + .getDefaultDisplay() + .getRealMetrics(metrics); + } else { + metrics = reactContext.getResources().getDisplayMetrics(); + } + } + + @Override + public String getName() { + return "AIRMapMbTile"; + } + + @Override + public AirMapMbTile createViewInstance(ThemedReactContext context) { + return new AirMapMbTile(context); + } + + @ReactProp(name = "pathTemplate") + public void setPathTemplate(AirMapMbTile view, String pathTemplate) { view.setPathTemplate(pathTemplate); } + + @ReactProp(name = "tileSize", defaultFloat = 256f) + public void setTileSize(AirMapMbTile view, float tileSize) { + view.setTileSize(tileSize); + } + + @ReactProp(name = "zIndex", defaultFloat = -1.0f) + public void setZIndex(AirMapMbTile view, float zIndex) { + view.setZIndex(zIndex); + } + +} \ No newline at end of file diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java old mode 100644 new mode 100755 index 5882f8cab..9dd751e12 --- a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java @@ -8,6 +8,7 @@ import android.graphics.Point; import android.graphics.PorterDuff; import android.os.Build; +import android.os.Handler; import android.support.v4.view.GestureDetectorCompat; import android.support.v4.view.MotionEventCompat; import android.view.GestureDetector; @@ -17,15 +18,12 @@ import android.widget.ImageView; import android.widget.ProgressBar; import android.widget.RelativeLayout; -import android.location.Location; import com.facebook.react.bridge.LifecycleEventListener; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReadableArray; import com.facebook.react.bridge.ReadableMap; -import com.facebook.react.bridge.WritableArray; import com.facebook.react.bridge.WritableMap; -import com.facebook.react.bridge.WritableNativeArray; import com.facebook.react.bridge.WritableNativeMap; import com.facebook.react.uimanager.ThemedReactContext; import com.facebook.react.uimanager.UIManagerModule; @@ -37,37 +35,25 @@ import com.google.android.gms.maps.MapView; import com.google.android.gms.maps.OnMapReadyCallback; import com.google.android.gms.maps.Projection; -import com.google.android.gms.maps.model.BitmapDescriptorFactory; import com.google.android.gms.maps.model.CameraPosition; import com.google.android.gms.maps.model.LatLng; import com.google.android.gms.maps.model.LatLngBounds; import com.google.android.gms.maps.model.Marker; -import com.google.android.gms.maps.model.MarkerOptions; -import com.google.android.gms.maps.model.PointOfInterest; import com.google.android.gms.maps.model.Polygon; import com.google.android.gms.maps.model.Polyline; -import com.google.maps.android.data.kml.KmlContainer; -import com.google.maps.android.data.kml.KmlLayer; -import com.google.maps.android.data.kml.KmlPlacemark; -import com.google.maps.android.data.kml.KmlStyle; +import com.google.android.gms.maps.model.VisibleRegion; -import org.xmlpull.v1.XmlPullParserException; - -import java.io.IOException; -import java.io.InputStream; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.concurrent.ExecutionException; import static android.support.v4.content.PermissionChecker.checkSelfPermission; public class AirMapView extends MapView implements GoogleMap.InfoWindowAdapter, - GoogleMap.OnMarkerDragListener, OnMapReadyCallback, GoogleMap.OnPoiClickListener { + GoogleMap.OnMarkerDragListener, OnMapReadyCallback { public GoogleMap map; - private KmlLayer kmlLayer; private ProgressBar mapLoadingProgressBar; private RelativeLayout mapLoadingLayout; private ImageView cacheImageView; @@ -179,7 +165,6 @@ public void onMapReady(final GoogleMap map) { this.map = map; this.map.setInfoWindowAdapter(this); this.map.setOnMarkerDragListener(this); - this.map.setOnPoiClickListener(this); manager.pushEvent(context, this, "onMapReady", new WritableNativeMap()); @@ -211,7 +196,7 @@ public void onMyLocationChange(Location location){ @Override public boolean onMarkerClick(Marker marker) { WritableMap event; - AirMapMarker airMapMarker = getMarkerMap(marker); + AirMapMarker airMapMarker = markerMap.get(marker); event = makeClickEventData(marker.getPosition()); event.putString("action", "marker-press"); @@ -221,7 +206,7 @@ public boolean onMarkerClick(Marker marker) { event = makeClickEventData(marker.getPosition()); event.putString("action", "marker-press"); event.putString("id", airMapMarker.getIdentifier()); - manager.pushEvent(context, airMapMarker, "onPress", event); + manager.pushEvent(context, markerMap.get(marker), "onPress", event); // Return false to open the callout info window and center on the marker // https://developers.google.com/android/reference/com/google/android/gms/maps/GoogleMap @@ -264,7 +249,7 @@ public void onInfoWindowClick(Marker marker) { event = makeClickEventData(marker.getPosition()); event.putString("action", "callout-press"); - AirMapMarker markerView = getMarkerMap(marker); + AirMapMarker markerView = markerMap.get(marker); manager.pushEvent(context, markerView, "onCalloutPress", event); event = makeClickEventData(marker.getPosition()); @@ -543,6 +528,10 @@ public void addFeature(View child, int index) { AirMapLocalTile localTileView = (AirMapLocalTile) child; localTileView.addToMap(map); features.add(index, localTileView); + } else if (child instanceof AirMapMbTile) { + AirMapMbTile mbTileView = (AirMapMbTile) child; + mbTileView.addToMap(map); + features.add(index, mbTileView); } else if (child instanceof AirMapOverlay) { AirMapOverlay overlayView = (AirMapOverlay) child; overlayView.addToMap(map); @@ -763,13 +752,13 @@ public void setMapBoundaries(ReadableMap northEast, ReadableMap southWest) { @Override public View getInfoWindow(Marker marker) { - AirMapMarker markerView = getMarkerMap(marker); + AirMapMarker markerView = markerMap.get(marker); return markerView.getCallout(); } @Override public View getInfoContents(Marker marker) { - AirMapMarker markerView = getMarkerMap(marker); + AirMapMarker markerView = markerMap.get(marker); return markerView.getInfoContents(); } @@ -798,7 +787,7 @@ public void onMarkerDragStart(Marker marker) { WritableMap event = makeClickEventData(marker.getPosition()); manager.pushEvent(context, this, "onMarkerDragStart", event); - AirMapMarker markerView = getMarkerMap(marker); + AirMapMarker markerView = markerMap.get(marker); event = makeClickEventData(marker.getPosition()); manager.pushEvent(context, markerView, "onDragStart", event); } @@ -808,7 +797,7 @@ public void onMarkerDrag(Marker marker) { WritableMap event = makeClickEventData(marker.getPosition()); manager.pushEvent(context, this, "onMarkerDrag", event); - AirMapMarker markerView = getMarkerMap(marker); + AirMapMarker markerView = markerMap.get(marker); event = makeClickEventData(marker.getPosition()); manager.pushEvent(context, markerView, "onDrag", event); } @@ -818,21 +807,11 @@ public void onMarkerDragEnd(Marker marker) { WritableMap event = makeClickEventData(marker.getPosition()); manager.pushEvent(context, this, "onMarkerDragEnd", event); - AirMapMarker markerView = getMarkerMap(marker); + AirMapMarker markerView = markerMap.get(marker); event = makeClickEventData(marker.getPosition()); manager.pushEvent(context, markerView, "onDragEnd", event); } - @Override - public void onPoiClick(PointOfInterest poi) { - WritableMap event = makeClickEventData(poi.latLng); - - event.putString("placeId", poi.placeId); - event.putString("name", poi.name); - - manager.pushEvent(context, this, "onPoiClick", event); - } - private ProgressBar getMapLoadingProgressBar() { if (this.mapLoadingProgressBar == null) { this.mapLoadingProgressBar = new ProgressBar(getContext()); @@ -925,118 +904,4 @@ public void onPanDrag(MotionEvent ev) { WritableMap event = makeClickEventData(coords); manager.pushEvent(context, this, "onPanDrag", event); } - - public void setKmlSrc(String kmlSrc) { - try { - InputStream kmlStream = new FileUtil(context).execute(kmlSrc).get(); - - if (kmlStream == null) { - return; - } - - kmlLayer = new KmlLayer(map, kmlStream, context); - kmlLayer.addLayerToMap(); - - WritableMap pointers = new WritableNativeMap(); - WritableArray markers = new WritableNativeArray(); - - if (kmlLayer.getContainers() == null) { - manager.pushEvent(context, this, "onKmlReady", pointers); - return; - } - - //Retrieve a nested container within the first container - KmlContainer container = kmlLayer.getContainers().iterator().next(); - if (container == null || container.getContainers() == null) { - manager.pushEvent(context, this, "onKmlReady", pointers); - return; - } - - - if (container.getContainers().iterator().hasNext()) { - container = container.getContainers().iterator().next(); - } - - Integer index = 0; - for (KmlPlacemark placemark : container.getPlacemarks()) { - MarkerOptions options = new MarkerOptions(); - - if (placemark.getInlineStyle() != null) { - options = placemark.getMarkerOptions(); - } else { - options.icon(BitmapDescriptorFactory.defaultMarker()); - } - - LatLng latLng = ((LatLng) placemark.getGeometry().getGeometryObject()); - String title = ""; - String snippet = ""; - - if (placemark.hasProperty("name")) { - title = placemark.getProperty("name"); - } - - if (placemark.hasProperty("description")) { - snippet = placemark.getProperty("description"); - } - - options.position(latLng); - options.title(title); - options.snippet(snippet); - - AirMapMarker marker = new AirMapMarker(context, options); - - if (placemark.getInlineStyle() != null - && placemark.getInlineStyle().getIconUrl() != null) { - marker.setImage(placemark.getInlineStyle().getIconUrl()); - } else if (container.getStyle(placemark.getStyleId()) != null) { - KmlStyle style = container.getStyle(placemark.getStyleId()); - marker.setImage(style.getIconUrl()); - } - - String identifier = title + " - " + index; - - marker.setIdentifier(identifier); - - addFeature(marker, index++); - - WritableMap loadedMarker = makeClickEventData(latLng); - loadedMarker.putString("id", identifier); - loadedMarker.putString("title", title); - loadedMarker.putString("description", snippet); - - markers.pushMap(loadedMarker); - } - - pointers.putArray("markers", markers); - - manager.pushEvent(context, this, "onKmlReady", pointers); - - } catch (XmlPullParserException e) { - e.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); - } catch (InterruptedException e) { - e.printStackTrace(); - } catch (ExecutionException e) { - e.printStackTrace(); - } - } - - private AirMapMarker getMarkerMap(Marker marker) { - AirMapMarker airMarker = markerMap.get(marker); - - if (airMarker != null) { - return airMarker; - } - - for (Map.Entry entryMarker : markerMap.entrySet()) { - if (entryMarker.getKey().getPosition().equals(marker.getPosition()) - && entryMarker.getKey().getTitle().equals(marker.getTitle())) { - airMarker = entryMarker.getValue(); - break; - } - } - - return airMarker; - } } diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/MapsPackage.java b/lib/android/src/main/java/com/airbnb/android/react/maps/MapsPackage.java old mode 100644 new mode 100755 index 45364b3be..e1d385021 --- a/lib/android/src/main/java/com/airbnb/android/react/maps/MapsPackage.java +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/MapsPackage.java @@ -40,6 +40,7 @@ public List createViewManagers(ReactApplicationContext reactContext AirMapLiteManager mapLiteManager = new AirMapLiteManager(reactContext); AirMapUrlTileManager urlTileManager = new AirMapUrlTileManager(reactContext); AirMapLocalTileManager localTileManager = new AirMapLocalTileManager(reactContext); + AirMapMbTileManager mbTileManager = new AirMapMbTileManager(reactContext); AirMapOverlayManager overlayManager = new AirMapOverlayManager(reactContext); return Arrays.asList( @@ -52,6 +53,7 @@ public List createViewManagers(ReactApplicationContext reactContext mapLiteManager, urlTileManager, localTileManager, + mbTileManager, overlayManager ); } diff --git a/lib/components/MapMbTile.js b/lib/components/MapMbTile.js new file mode 100644 index 000000000..d439d2781 --- /dev/null +++ b/lib/components/MapMbTile.js @@ -0,0 +1,71 @@ +// +// MapMbTile.js +// AirMaps +// +// Created by Christoph Lambio on 27/03/2018. +// Based on AIRMapLocalTileManager.h +// + +import PropTypes from 'prop-types'; +import React from 'react'; + +import { + ViewPropTypes, + View, +} from 'react-native'; + +import decorateMapComponent, { + USES_DEFAULT_IMPLEMENTATION, + SUPPORTED, +} from './decorateMapComponent'; + +// if ViewPropTypes is not defined fall back to View.propType (to support RN < 0.44) +const viewPropTypes = ViewPropTypes || View.propTypes; + +const propTypes = { + ...viewPropTypes, + + /** + * The path template of the MBTiles database tile source. + * The patterns {x} {y} {z} will be replaced at runtime, + * for example, /storage/emulated/0/tiles/{z}/{x}/{y}.png. + */ + pathTemplate: PropTypes.string.isRequired, + + /** + * The order in which this tile overlay is drawn with respect to other overlays. An overlay + * with a larger z-index is drawn over overlays with smaller z-indices. The order of overlays + * with the same z-index is arbitrary. The default zIndex is -1. + * + * @platform android + */ + zIndex: PropTypes.number, + + /** + * Size of tile images. + */ + tileSize: PropTypes.number, +}; + +class MapMbTile extends React.Component { + render() { + const AIRMapMbTile = this.getAirComponent(); + return ( + + ); + } +} + +MapMbTile.propTypes = propTypes; + +export default decorateMapComponent(MapMbTile, { + componentType: 'MbTile', + providers: { + google: { + ios: SUPPORTED, + android: USES_DEFAULT_IMPLEMENTATION, + }, + }, +}); diff --git a/lib/components/MapView.js b/lib/components/MapView.js old mode 100644 new mode 100755 index 50c4d2657..e88651afb --- a/lib/components/MapView.js +++ b/lib/components/MapView.js @@ -19,6 +19,7 @@ import MapCallout from './MapCallout'; import MapOverlay from './MapOverlay'; import MapUrlTile from './MapUrlTile'; import MapLocalTile from './MapLocalTile'; +import MapMbTile from './MapMbTile'; import AnimatedRegion from './AnimatedRegion'; import { contextTypes as childContextTypes, @@ -358,11 +359,6 @@ const propTypes = { */ onMapReady: PropTypes.func, - /** - * Callback that is called once the kml is fully loaded. - */ - onKmlReady: PropTypes.func, - /** * Callback that is called continuously when the user is dragging the map. */ @@ -383,21 +379,11 @@ const propTypes = { */ onLongPress: PropTypes.func, - /** - * Callback that is called when the underlying map figures our users current location. - */ - onUserLocationChange: PropTypes.func, - /** * Callback that is called when user makes a "drag" somewhere on the map */ onPanDrag: PropTypes.func, - /** - * Callback that is called when user click on a POI - */ - onPoiClick: PropTypes.func, - /** * Callback that is called when a marker on the map is tapped by the user. */ @@ -450,11 +436,6 @@ const propTypes = { */ maxZoomLevel: PropTypes.number, - /** - * Url KML Source - */ - kmlSrc: PropTypes.string, - }; class MapView extends React.Component { @@ -678,7 +659,18 @@ class MapView extends React.Component { if (Platform.OS === 'android') { return NativeModules.AirMapModule.pointForCoordinate(this._getHandle(), coordinate); } else if (Platform.OS === 'ios') { - return this._runCommand('pointForCoordinate', [coordinate]); + return new Promise((resolve, reject) => { + this._runCommand('pointForCoordinate', [ + coordinate, + (err, snapshot) => { + if (err) { + reject(err); + } else { + resolve(snapshot); + } + }, + ]); + }); } return Promise.reject('pointForCoordinate not supported on this platform'); } @@ -692,13 +684,24 @@ class MapView extends React.Component { * * @return Promise Promise with the coordinate ({ latitude: Number, longitude: Number }) */ - coordinateForPoint(point) { + coordinateFromPoint(point) { if (Platform.OS === 'android') { - return NativeModules.AirMapModule.coordinateForPoint(this._getHandle(), point); + return NativeModules.AirMapModule.coordinateFromPoint(this._getHandle(), point); } else if (Platform.OS === 'ios') { - return this._runCommand('coordinateForPoint', [point]); + return new Promise((resolve, reject) => { + this._runCommand('coordinateFromPoint', [ + point, + (err, snapshot) => { + if (err) { + reject(err); + } else { + resolve(snapshot); + } + }, + ]); + }); } - return Promise.reject('coordinateForPoint not supported on this platform'); + return Promise.reject('coordinateFromPoint not supported on this platform'); } _uiManagerCommand(name) { @@ -716,17 +719,19 @@ class MapView extends React.Component { _runCommand(name, args) { switch (Platform.OS) { case 'android': - return NativeModules.UIManager.dispatchViewManagerCommand( + NativeModules.UIManager.dispatchViewManagerCommand( this._getHandle(), this._uiManagerCommand(name), args ); + break; case 'ios': - return this._mapManagerCommand(name)(this._getHandle(), ...args); + this._mapManagerCommand(name)(this._getHandle(), ...args); + break; default: - return Promise.reject(`Invalid platform was passed: ${Platform.OS}`); + break; } } @@ -790,7 +795,6 @@ const nativeComponent = Component => requireNativeComponent(Component, MapView, nativeOnly: { onChange: true, onMapReady: true, - onKmlReady: true, handlePanDrag: true, }, }); @@ -832,6 +836,7 @@ MapView.Polygon = MapPolygon; MapView.Circle = MapCircle; MapView.UrlTile = MapUrlTile; MapView.LocalTile = MapLocalTile; +MapView.MbTile = MapMbTile; MapView.Overlay = MapOverlay; MapView.Callout = MapCallout; Object.assign(MapView, ProviderConstants); diff --git a/lib/ios/AirMaps.xcodeproj/project.pbxproj b/lib/ios/AirMaps.xcodeproj/project.pbxproj index 7e2468f62..1ddaacdb1 100644 --- a/lib/ios/AirMaps.xcodeproj/project.pbxproj +++ b/lib/ios/AirMaps.xcodeproj/project.pbxproj @@ -47,6 +47,9 @@ 9B9498DA2017EFB800158761 /* AIRGoogleMapPolygon.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B9498C62017EFB800158761 /* AIRGoogleMapPolygon.m */; }; 9B9498DB2017EFB800158761 /* AIRGoogleMapMarker.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B9498C72017EFB800158761 /* AIRGoogleMapMarker.m */; }; 9B9498DC2017EFB800158761 /* AIRGoogleMapPolygonManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B9498C92017EFB800158761 /* AIRGoogleMapPolygonManager.m */; }; + BD9BE2902087408600A3E492 /* AIRMapMbTile.m in Sources */ = {isa = PBXBuildFile; fileRef = BD9BE28C2087408500A3E492 /* AIRMapMbTile.m */; }; + BD9BE2912087408600A3E492 /* AIRMapMbTileManager.m in Sources */ = {isa = PBXBuildFile; fileRef = BD9BE28D2087408600A3E492 /* AIRMapMbTileManager.m */; }; + BD9BE2922087408600A3E492 /* AIRMapMbTileOverlay.m in Sources */ = {isa = PBXBuildFile; fileRef = BD9BE28F2087408600A3E492 /* AIRMapMbTileOverlay.m */; }; B5EA3BA92098E22B000E7AFD /* AIRDummyView.m in Sources */ = {isa = PBXBuildFile; fileRef = B5EA3BA72098E22B000E7AFD /* AIRDummyView.m */; }; DA6C26381C9E2AFE0035349F /* AIRMapUrlTile.m in Sources */ = {isa = PBXBuildFile; fileRef = DA6C26371C9E2AFE0035349F /* AIRMapUrlTile.m */; }; DA6C263E1C9E324A0035349F /* AIRMapUrlTileManager.m in Sources */ = {isa = PBXBuildFile; fileRef = DA6C263D1C9E324A0035349F /* AIRMapUrlTileManager.m */; }; @@ -145,6 +148,23 @@ 9B9498C72017EFB800158761 /* AIRGoogleMapMarker.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AIRGoogleMapMarker.m; path = AirGoogleMaps/AIRGoogleMapMarker.m; sourceTree = ""; }; 9B9498C82017EFB800158761 /* AIRGoogleMapUrlTile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AIRGoogleMapUrlTile.h; path = AirGoogleMaps/AIRGoogleMapUrlTile.h; sourceTree = ""; }; 9B9498C92017EFB800158761 /* AIRGoogleMapPolygonManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AIRGoogleMapPolygonManager.m; path = AirGoogleMaps/AIRGoogleMapPolygonManager.m; sourceTree = ""; }; + BD9BE28A2087408500A3E492 /* AIRMapMbTileManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRMapMbTileManager.h; sourceTree = ""; }; + BD9BE28B2087408500A3E492 /* AIRMapMbTile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRMapMbTile.h; sourceTree = ""; }; + BD9BE28C2087408500A3E492 /* AIRMapMbTile.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRMapMbTile.m; sourceTree = ""; }; + BD9BE28D2087408600A3E492 /* AIRMapMbTileManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRMapMbTileManager.m; sourceTree = ""; }; + BD9BE28E2087408600A3E492 /* AIRMapMbTileOverlay.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRMapMbTileOverlay.h; sourceTree = ""; }; + BD9BE28F2087408600A3E492 /* AIRMapMbTileOverlay.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRMapMbTileOverlay.m; sourceTree = ""; }; + BD9BE2942087408F00A3E492 /* FMDatabase.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FMDatabase.h; sourceTree = ""; }; + BD9BE2952087408F00A3E492 /* FMDatabase.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FMDatabase.m; sourceTree = ""; }; + BD9BE2962087408F00A3E492 /* FMDatabaseAdditions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FMDatabaseAdditions.h; sourceTree = ""; }; + BD9BE2972087408F00A3E492 /* FMDatabaseAdditions.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FMDatabaseAdditions.m; sourceTree = ""; }; + BD9BE2982087408F00A3E492 /* FMDatabasePool.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FMDatabasePool.h; sourceTree = ""; }; + BD9BE2992087408F00A3E492 /* FMDatabasePool.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FMDatabasePool.m; sourceTree = ""; }; + BD9BE29A2087408F00A3E492 /* FMDatabaseQueue.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FMDatabaseQueue.h; sourceTree = ""; }; + BD9BE29B2087408F00A3E492 /* FMDatabaseQueue.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FMDatabaseQueue.m; sourceTree = ""; }; + BD9BE29C2087408F00A3E492 /* FMDB.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FMDB.h; sourceTree = ""; }; + BD9BE29D2087408F00A3E492 /* FMResultSet.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FMResultSet.h; sourceTree = ""; }; + BD9BE29E2087408F00A3E492 /* FMResultSet.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FMResultSet.m; sourceTree = ""; }; B5EA3BA72098E22B000E7AFD /* AIRDummyView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AIRDummyView.m; path = AirGoogleMaps/AIRDummyView.m; sourceTree = ""; }; B5EA3BA82098E22B000E7AFD /* AIRDummyView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AIRDummyView.h; path = AirGoogleMaps/AIRDummyView.h; sourceTree = ""; }; DA6C26361C9E2AFE0035349F /* AIRMapUrlTile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRMapUrlTile.h; sourceTree = ""; }; @@ -167,6 +187,7 @@ 11FA5C481C4A1296003AC2EE = { isa = PBXGroup; children = ( + BD9BE2932087408F00A3E492 /* fmdb */, 9B9498A32017EF9D00158761 /* AirGoogleMaps */, 62AEC4D31FD5A0AA003225E0 /* AIRMapLocalTileOverlay.m */, 11FA5C531C4A1296003AC2EE /* AirMaps */, @@ -185,6 +206,12 @@ 11FA5C531C4A1296003AC2EE /* AirMaps */ = { isa = PBXGroup; children = ( + BD9BE28B2087408500A3E492 /* AIRMapMbTile.h */, + BD9BE28C2087408500A3E492 /* AIRMapMbTile.m */, + BD9BE28A2087408500A3E492 /* AIRMapMbTileManager.h */, + BD9BE28D2087408600A3E492 /* AIRMapMbTileManager.m */, + BD9BE28E2087408600A3E492 /* AIRMapMbTileOverlay.h */, + BD9BE28F2087408600A3E492 /* AIRMapMbTileOverlay.m */, 1125B2BD1C4AD3DA007D0023 /* AIRMap.h */, 1125B2BE1C4AD3DA007D0023 /* AIRMap.m */, 1125B2BF1C4AD3DA007D0023 /* AIRMapCallout.h */, @@ -280,6 +307,25 @@ name = AirGoogleMaps; sourceTree = ""; }; + BD9BE2932087408F00A3E492 /* fmdb */ = { + isa = PBXGroup; + children = ( + BD9BE2942087408F00A3E492 /* FMDatabase.h */, + BD9BE2952087408F00A3E492 /* FMDatabase.m */, + BD9BE2962087408F00A3E492 /* FMDatabaseAdditions.h */, + BD9BE2972087408F00A3E492 /* FMDatabaseAdditions.m */, + BD9BE2982087408F00A3E492 /* FMDatabasePool.h */, + BD9BE2992087408F00A3E492 /* FMDatabasePool.m */, + BD9BE29A2087408F00A3E492 /* FMDatabaseQueue.h */, + BD9BE29B2087408F00A3E492 /* FMDatabaseQueue.m */, + BD9BE29C2087408F00A3E492 /* FMDB.h */, + BD9BE29D2087408F00A3E492 /* FMResultSet.h */, + BD9BE29E2087408F00A3E492 /* FMResultSet.m */, + ); + name = fmdb; + path = AirMaps/fmdb; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -339,6 +385,7 @@ 62AEC4D41FD5A0AA003225E0 /* AIRMapLocalTileOverlay.m in Sources */, 9B9498DC2017EFB800158761 /* AIRGoogleMapPolygonManager.m in Sources */, 1125B2E31C4AD3DA007D0023 /* AIRMapPolygon.m in Sources */, + BD9BE2922087408600A3E492 /* AIRMapMbTileOverlay.m in Sources */, 1125B2E41C4AD3DA007D0023 /* AIRMapPolygonManager.m in Sources */, 9B9498CB2017EFB800158761 /* AIRGoogleMapURLTileManager.m in Sources */, 1125B2DB1C4AD3DA007D0023 /* AIRMapCallout.m in Sources */, @@ -352,6 +399,8 @@ 9B9498D72017EFB800158761 /* AIRGoogleMapManager.m in Sources */, 19DABC7F1E7C9D3C00F41150 /* RCTConvert+AirMap.m in Sources */, 1125B2E51C4AD3DA007D0023 /* AIRMapPolyline.m in Sources */, + BD9BE2902087408600A3E492 /* AIRMapMbTile.m in Sources */, + 9B9498D82017EFB800158761 /* DummyView.m in Sources */, 9B9498D52017EFB800158761 /* AIRGoogleMapPolyline.m in Sources */, 9B9498CF2017EFB800158761 /* AIRGMSPolyline.m in Sources */, 9B9498D42017EFB800158761 /* RCTConvert+GMSMapViewType.m in Sources */, @@ -366,6 +415,7 @@ 1125B2DF1C4AD3DA007D0023 /* AIRMapCoordinate.m in Sources */, 9B9498D62017EFB800158761 /* AIRGoogleMapCircleManager.m in Sources */, 1125B2F21C4AD445007D0023 /* SMCalloutView.m in Sources */, + BD9BE2912087408600A3E492 /* AIRMapMbTileManager.m in Sources */, 2163AA501FEAEDD100BBEC95 /* AIRMapPolylineRenderer.m in Sources */, 9B9498D02017EFB800158761 /* AIRGoogleMapPolylineManager.m in Sources */, 1125B2E11C4AD3DA007D0023 /* AIRMapMarker.m in Sources */, diff --git a/lib/ios/AirMaps/AIRMap.m b/lib/ios/AirMaps/AIRMap.m old mode 100644 new mode 100755 index 1e3e76193..8ce4bb411 --- a/lib/ios/AirMaps/AIRMap.m +++ b/lib/ios/AirMaps/AIRMap.m @@ -18,7 +18,7 @@ #import #import "AIRMapUrlTile.h" #import "AIRMapLocalTile.h" -#import "AIRMapOverlay.h" +#import "AIRMapMbTile.h" const CLLocationDegrees AIRMapDefaultSpan = 0.005; const NSTimeInterval AIRMapRegionChangeObserveInterval = 0.1; @@ -116,7 +116,6 @@ - (void)insertReactSubview:(id)subview atIndex:(NSInteger)atIndex ((AIRMapPolygon *)subview).map = self; [self addOverlay:(id)subview]; } else if ([subview isKindOfClass:[AIRMapCircle class]]) { - ((AIRMapCircle *)subview).map = self; [self addOverlay:(id)subview]; } else if ([subview isKindOfClass:[AIRMapUrlTile class]]) { ((AIRMapUrlTile *)subview).map = self; @@ -124,8 +123,8 @@ - (void)insertReactSubview:(id)subview atIndex:(NSInteger)atIndex } else if ([subview isKindOfClass:[AIRMapLocalTile class]]) { ((AIRMapLocalTile *)subview).map = self; [self addOverlay:(id)subview]; - } else if ([subview isKindOfClass:[AIRMapOverlay class]]) { - ((AIRMapOverlay *)subview).map = self; + } else if ([subview isKindOfClass:[AIRMapMbTile class]]) { + ((AIRMapMbTile *)subview).map = self; [self addOverlay:(id)subview]; } else { NSArray> *childSubviews = [subview reactSubviews]; @@ -154,7 +153,7 @@ - (void)removeReactSubview:(id)subview { [self removeOverlay:(id ) subview]; } else if ([subview isKindOfClass:[AIRMapLocalTile class]]) { [self removeOverlay:(id ) subview]; - } else if ([subview isKindOfClass:[AIRMapOverlay class]]) { + } else if ([subview isKindOfClass:[AIRMapMbTile class]]) { [self removeOverlay:(id ) subview]; } else { NSArray> *childSubviews = [subview reactSubviews]; @@ -317,6 +316,38 @@ - (void)setLoadingIndicatorColor:(UIColor *)loadingIndicatorColor { self.activityIndicatorView.color = loadingIndicatorColor; } +RCT_EXPORT_METHOD(pointForCoordinate:(NSDictionary *)coordinate resolver: (RCTPromiseResolveBlock)resolve + rejecter:(RCTPromiseRejectBlock)reject) +{ + CGPoint touchPoint = [self convertCoordinate: + CLLocationCoordinate2DMake( + [coordinate[@"lat"] doubleValue], + [coordinate[@"lng"] doubleValue] + ) + toPointToView:self]; + + resolve(@{ + @"x": @(touchPoint.x), + @"y": @(touchPoint.y), + }); +} + +RCT_EXPORT_METHOD(coordinateForPoint:(NSDictionary *)point resolver: (RCTPromiseResolveBlock)resolve + rejecter:(RCTPromiseRejectBlock)reject) +{ + CLLocationCoordinate2D coordinate = [self convertPoint: + CGPointMake( + [point[@"x"] doubleValue], + [point[@"y"] doubleValue] + ) + toCoordinateFromView:self]; + + resolve(@{ + @"lat": @(coordinate.latitude), + @"lng": @(coordinate.longitude), + }); +} + // Include properties of MKMapView which are only available on iOS 9+ // and check if their selector is available before calling super method. diff --git a/lib/ios/AirMaps/AIRMapManager.m b/lib/ios/AirMaps/AIRMapManager.m old mode 100644 new mode 100755 index da1efc08e..26e29a38b --- a/lib/ios/AirMaps/AIRMapManager.m +++ b/lib/ios/AirMaps/AIRMapManager.m @@ -24,9 +24,9 @@ #import "SMCalloutView.h" #import "AIRMapUrlTile.h" #import "AIRMapLocalTile.h" +#import "AIRMapMbTile.h" #import "AIRMapSnapshot.h" #import "RCTConvert+AirMap.h" -#import "AIRMapOverlay.h" #import @@ -75,7 +75,6 @@ - (UIView *)view RCT_EXPORT_VIEW_PROPERTY(showsScale, BOOL) RCT_EXPORT_VIEW_PROPERTY(showsTraffic, BOOL) RCT_EXPORT_VIEW_PROPERTY(zoomEnabled, BOOL) -RCT_EXPORT_VIEW_PROPERTY(kmlSrc, NSString) RCT_EXPORT_VIEW_PROPERTY(rotateEnabled, BOOL) RCT_EXPORT_VIEW_PROPERTY(scrollEnabled, BOOL) RCT_EXPORT_VIEW_PROPERTY(pitchEnabled, BOOL) @@ -341,58 +340,6 @@ - (UIView *)view }]; } -RCT_EXPORT_METHOD(pointForCoordinate:(nonnull NSNumber *)reactTag - coordinate: (NSDictionary *)coordinate - resolver: (RCTPromiseResolveBlock)resolve - rejecter:(RCTPromiseRejectBlock)reject) -{ - [self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary *viewRegistry) { - id view = viewRegistry[reactTag]; - AIRMap *mapView = (AIRMap *)view; - if (![view isKindOfClass:[AIRMap class]]) { - reject(@"Invalid argument", [NSString stringWithFormat:@"Invalid view returned from registry, expecting AIRMap, got: %@", view], NULL); - } else { - CGPoint touchPoint = [mapView convertCoordinate: - CLLocationCoordinate2DMake( - [coordinate[@"lat"] doubleValue], - [coordinate[@"lng"] doubleValue] - ) - toPointToView:mapView]; - - resolve(@{ - @"x": @(touchPoint.x), - @"y": @(touchPoint.y), - }); - } - }]; -} - -RCT_EXPORT_METHOD(coordinateForPoint:(nonnull NSNumber *)reactTag - point:(NSDictionary *)point - resolver: (RCTPromiseResolveBlock)resolve - rejecter:(RCTPromiseRejectBlock)reject) -{ - [self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary *viewRegistry) { - id view = viewRegistry[reactTag]; - AIRMap *mapView = (AIRMap *)view; - if (![view isKindOfClass:[AIRMap class]]) { - reject(@"Invalid argument", [NSString stringWithFormat:@"Invalid view returned from registry, expecting AIRMap, got: %@", view], NULL); - } else { - CLLocationCoordinate2D coordinate = [mapView convertPoint: - CGPointMake( - [point[@"x"] doubleValue], - [point[@"y"] doubleValue] - ) - toCoordinateFromView:mapView]; - - resolve(@{ - @"lat": @(coordinate.latitude), - @"lng": @(coordinate.longitude), - }); - } - }]; -} - #pragma mark Take Snapshot - (void)takeMapSnapshot:(AIRMap *)mapView snapshotter:(MKMapSnapshotter *) snapshotter @@ -534,24 +481,6 @@ - (void)handleMapTap:(UITapGestureRecognizer *)recognizer { } } } - - if ([overlay isKindOfClass:[AIRMapOverlay class]]) { - AIRMapOverlay *imageOverlay = (AIRMapOverlay*) overlay; - if (MKMapRectContainsPoint(imageOverlay.boundingMapRect, mapPoint)) { - if (imageOverlay.onPress) { - id event = @{ - @"action": @"image-overlay-press", - @"name": imageOverlay.name ?: @"unknown", - @"coordinate": @{ - @"latitude": @(imageOverlay.coordinate.latitude), - @"longitude": @(imageOverlay.coordinate.longitude) - } - }; - imageOverlay.onPress(event); - } - } - } - } if (nearestDistance <= maxMeters) { @@ -633,8 +562,8 @@ - (MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id +#import +#import + +#import +#import +#import "AIRMapCoordinate.h" +#import "AIRMap.h" +#import "RCTConvert+AirMap.h" + +#import +#import +#import + +#import +#import +#import "AIRMapCoordinate.h" +#import "AIRMap.h" +#import "RCTConvert+AirMap.h" + +@interface AIRMapMbTile : MKAnnotationView + +@property (nonatomic, weak) AIRMap *map; + +@property (nonatomic, strong) MKTileOverlay *tileOverlay; +@property (nonatomic, strong) MKTileOverlayRenderer *renderer; + +@property (nonatomic, copy) NSString *pathTemplate; +@property (nonatomic, assign) CGFloat tileSize; + +#pragma mark MKOverlay protocol + +@property(nonatomic, readonly) CLLocationCoordinate2D coordinate; +@property(nonatomic, readonly) MKMapRect boundingMapRect; +- (BOOL)canReplaceMapContent; + +@end + diff --git a/lib/ios/AirMaps/AIRMapMbTile.m b/lib/ios/AirMaps/AIRMapMbTile.m new file mode 100644 index 000000000..d63f44d1d --- /dev/null +++ b/lib/ios/AirMaps/AIRMapMbTile.m @@ -0,0 +1,68 @@ +// +// AIRMapMbTile.m +// AirMaps +// +// Created by Christoph Lambio on 28/03/2018. +// Based on AIRMapLocalTile.m +// Copyright (c) 2017 Christopher. All rights reserved. +// + +#import "AIRMapMbTile.h" +#import +#import "AIRMapMbTileOverlay.h" + +@implementation AIRMapMbTile { + BOOL _pathTemplateSet; + BOOL _tileSizeSet; +} + +- (void)setPathTemplate:(NSString *)pathTemplate{ + _pathTemplate = pathTemplate; + _pathTemplateSet = YES; + [self createTileOverlayAndRendererIfPossible]; + [self update]; +} + +- (void)setTileSize:(CGFloat)tileSize{ + _tileSize = tileSize; + _tileSizeSet = YES; + [self createTileOverlayAndRendererIfPossible]; + [self update]; +} + +- (void) createTileOverlayAndRendererIfPossible +{ + if (!_pathTemplateSet || !_tileSizeSet) return; + self.tileOverlay = [[AIRMapMbTileOverlay alloc] initWithURLTemplate:self.pathTemplate]; + self.tileOverlay.canReplaceMapContent = YES; + self.tileOverlay.tileSize = CGSizeMake(_tileSize, _tileSize); + self.renderer = [[MKTileOverlayRenderer alloc] initWithTileOverlay:self.tileOverlay]; +} + +- (void) update +{ + if (!_renderer) return; + + if (_map == nil) return; + [_map removeOverlay:self]; + [_map addOverlay:self level:MKOverlayLevelAboveLabels]; +} + +#pragma mark MKOverlay implementation + +- (CLLocationCoordinate2D) coordinate +{ + return self.tileOverlay.coordinate; +} + +- (MKMapRect) boundingMapRect +{ + return self.tileOverlay.boundingMapRect; +} + +- (BOOL)canReplaceMapContent +{ + return self.tileOverlay.canReplaceMapContent; +} + +@end diff --git a/lib/ios/AirMaps/AIRMapMbTileManager.h b/lib/ios/AirMaps/AIRMapMbTileManager.h new file mode 100644 index 000000000..2a81982e8 --- /dev/null +++ b/lib/ios/AirMaps/AIRMapMbTileManager.h @@ -0,0 +1,14 @@ +// +// AIRMapMbTileManager.h +// AirMaps +// +// Created by Christoph Lambio on 27/03/2018. +// Based on AIRMapLocalTileManager.h +// Copyright (c) 2017 Christopher. All rights reserved. +// + +#import + +@interface AIRMapMbTileManager : RCTViewManager + +@end diff --git a/lib/ios/AirMaps/AIRMapMbTileManager.m b/lib/ios/AirMaps/AIRMapMbTileManager.m new file mode 100644 index 000000000..5d815e608 --- /dev/null +++ b/lib/ios/AirMaps/AIRMapMbTileManager.m @@ -0,0 +1,40 @@ +// +// AIRMapMbTileManager.m +// AirMaps +// +// Created by Christoph Lambio on 27/03/2018. +// Based on AIRMapLocalTileManager.m +// Copyright (c) 2017 Christopher. All rights reserved. +// + +#import +#import +#import +#import +#import +#import +#import "AIRMapMarker.h" +#import "AIRMapMbTile.h" + +#import "AIRMapMbTileManager.h" + +@interface AIRMapMbTileManager() + +@end + +@implementation AIRMapMbTileManager + + +RCT_EXPORT_MODULE() + +- (UIView *)view +{ + AIRMapMbTile *tile = [AIRMapMbTile new]; + return tile; +} + +RCT_EXPORT_VIEW_PROPERTY(pathTemplate, NSString) +RCT_EXPORT_VIEW_PROPERTY(tileSize, CGFloat) + +@end + diff --git a/lib/ios/AirMaps/AIRMapMbTileOverlay.h b/lib/ios/AirMaps/AIRMapMbTileOverlay.h new file mode 100644 index 000000000..18b5d4791 --- /dev/null +++ b/lib/ios/AirMaps/AIRMapMbTileOverlay.h @@ -0,0 +1,15 @@ +// +// AIRMapMbTileOverlay.h +// Pods +// +// Created by Christoph Lambio on 28/03/2018. +// Based on AIRMapLocalTileOverlay.h +// Copyright by (c) by Peter Zavadsky on. +// + +#import + +@interface AIRMapMbTileOverlay : MKTileOverlay + +@end + diff --git a/lib/ios/AirMaps/AIRMapMbTileOverlay.m b/lib/ios/AirMaps/AIRMapMbTileOverlay.m new file mode 100644 index 000000000..1eb6906b5 --- /dev/null +++ b/lib/ios/AirMaps/AIRMapMbTileOverlay.m @@ -0,0 +1,45 @@ +// +// AIRMapMbTileOverlay.m +// Pods-AirMapsExplorer +// +// Created by Christoph Lambio on 28/03/2018 +// Based on AIRMapLocalTileOverlay.m +// Copyright (c) by Peter Zavadsky. +// + +#import "AIRMapMbTileOverlay.h" +#import "FMDatabase.h" + +@interface AIRMapMbTileOverlay () + +@end + +@implementation AIRMapMbTileOverlay + + +-(void)loadTileAtPath:(MKTileOverlayPath)path result:(void (^)(NSData *, NSError *))result { + NSFileManager *fileManager = [NSFileManager defaultManager]; + if ([fileManager fileExistsAtPath:self.URLTemplate]) { + FMDatabase *offlineDataDatabase = [FMDatabase databaseWithPath:self.URLTemplate]; + [offlineDataDatabase open]; + NSMutableString *query = [NSMutableString stringWithString: @"SELECT * FROM map INNER JOIN images ON map.tile_id = images.tile_id WHERE map.zoom_level = {z} AND map.tile_column = {x} AND map.tile_row = {y};"]; + [query replaceCharactersInRange: [query rangeOfString: @"{z}"] withString:[NSString stringWithFormat:@"%li", path.z]]; + [query replaceCharactersInRange: [query rangeOfString: @"{x}"] withString:[NSString stringWithFormat:@"%li", path.x]]; + [query replaceCharactersInRange: [query rangeOfString: @"{y}"] withString:[NSString stringWithFormat:@"%li", path.y]]; + FMResultSet *databaseResult = [offlineDataDatabase executeQuery:query]; + if ([databaseResult next]) { + NSData *tile = [databaseResult dataForColumn:@"tile_data"]; + [offlineDataDatabase close]; + result(tile,nil); + } else { + [offlineDataDatabase close]; + result(nil,nil); + } + } else { + NSLog(@"Database not found. Wrong path."); + } +} + + +@end + diff --git a/lib/ios/AirMaps/fmdb/FMDB.h b/lib/ios/AirMaps/fmdb/FMDB.h new file mode 100644 index 000000000..1ff546504 --- /dev/null +++ b/lib/ios/AirMaps/fmdb/FMDB.h @@ -0,0 +1,10 @@ +#import + +FOUNDATION_EXPORT double FMDBVersionNumber; +FOUNDATION_EXPORT const unsigned char FMDBVersionString[]; + +#import "FMDatabase.h" +#import "FMResultSet.h" +#import "FMDatabaseAdditions.h" +#import "FMDatabaseQueue.h" +#import "FMDatabasePool.h" diff --git a/lib/ios/AirMaps/fmdb/FMDatabase.h b/lib/ios/AirMaps/fmdb/FMDatabase.h new file mode 100644 index 000000000..b779d542e --- /dev/null +++ b/lib/ios/AirMaps/fmdb/FMDatabase.h @@ -0,0 +1,1360 @@ +#import +#import "FMResultSet.h" +#import "FMDatabasePool.h" + +NS_ASSUME_NONNULL_BEGIN + +#if ! __has_feature(objc_arc) + #define FMDBAutorelease(__v) ([__v autorelease]); + #define FMDBReturnAutoreleased FMDBAutorelease + + #define FMDBRetain(__v) ([__v retain]); + #define FMDBReturnRetained FMDBRetain + + #define FMDBRelease(__v) ([__v release]); + + #define FMDBDispatchQueueRelease(__v) (dispatch_release(__v)); +#else + // -fobjc-arc + #define FMDBAutorelease(__v) + #define FMDBReturnAutoreleased(__v) (__v) + + #define FMDBRetain(__v) + #define FMDBReturnRetained(__v) (__v) + + #define FMDBRelease(__v) + +// If OS_OBJECT_USE_OBJC=1, then the dispatch objects will be treated like ObjC objects +// and will participate in ARC. +// See the section on "Dispatch Queues and Automatic Reference Counting" in "Grand Central Dispatch (GCD) Reference" for details. + #if OS_OBJECT_USE_OBJC + #define FMDBDispatchQueueRelease(__v) + #else + #define FMDBDispatchQueueRelease(__v) (dispatch_release(__v)); + #endif +#endif + +#if !__has_feature(objc_instancetype) + #define instancetype id +#endif + + +typedef int(^FMDBExecuteStatementsCallbackBlock)(NSDictionary *resultsDictionary); + + +/** A SQLite ([http://sqlite.org/](http://sqlite.org/)) Objective-C wrapper. + + ### Usage + The three main classes in FMDB are: + + - `FMDatabase` - Represents a single SQLite database. Used for executing SQL statements. + - `` - Represents the results of executing a query on an `FMDatabase`. + - `` - If you want to perform queries and updates on multiple threads, you'll want to use this class. + + ### See also + + - `` - A pool of `FMDatabase` objects. + - `` - A wrapper for `sqlite_stmt`. + + ### External links + + - [FMDB on GitHub](https://github.com/ccgus/fmdb) including introductory documentation + - [SQLite web site](http://sqlite.org/) + - [FMDB mailing list](http://groups.google.com/group/fmdb) + - [SQLite FAQ](http://www.sqlite.org/faq.html) + + @warning Do not instantiate a single `FMDatabase` object and use it across multiple threads. Instead, use ``. + + */ + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wobjc-interface-ivars" + + +@interface FMDatabase : NSObject + +///----------------- +/// @name Properties +///----------------- + +/** Whether should trace execution */ + +@property (atomic, assign) BOOL traceExecution; + +/** Whether checked out or not */ + +@property (atomic, assign) BOOL checkedOut; + +/** Crash on errors */ + +@property (atomic, assign) BOOL crashOnErrors; + +/** Logs errors */ + +@property (atomic, assign) BOOL logsErrors; + +/** Dictionary of cached statements */ + +@property (atomic, retain, nullable) NSMutableDictionary *cachedStatements; + +///--------------------- +/// @name Initialization +///--------------------- + +/** Create a `FMDatabase` object. + + An `FMDatabase` is created with a path to a SQLite database file. This path can be one of these three: + + 1. A file system path. The file does not have to exist on disk. If it does not exist, it is created for you. + 2. An empty string (`@""`). An empty database is created at a temporary location. This database is deleted with the `FMDatabase` connection is closed. + 3. `nil`. An in-memory database is created. This database will be destroyed with the `FMDatabase` connection is closed. + + For example, to create/open a database in your Mac OS X `tmp` folder: + + FMDatabase *db = [FMDatabase databaseWithPath:@"/tmp/tmp.db"]; + + Or, in iOS, you might open a database in the app's `Documents` directory: + + NSString *docsPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0]; + NSString *dbPath = [docsPath stringByAppendingPathComponent:@"test.db"]; + FMDatabase *db = [FMDatabase databaseWithPath:dbPath]; + + (For more information on temporary and in-memory databases, read the sqlite documentation on the subject: [http://www.sqlite.org/inmemorydb.html](http://www.sqlite.org/inmemorydb.html)) + + @param inPath Path of database file + + @return `FMDatabase` object if successful; `nil` if failure. + + */ + ++ (instancetype)databaseWithPath:(NSString * _Nullable)inPath; + +/** Create a `FMDatabase` object. + + An `FMDatabase` is created with a path to a SQLite database file. This path can be one of these three: + + 1. A file system URL. The file does not have to exist on disk. If it does not exist, it is created for you. + 2. `nil`. An in-memory database is created. This database will be destroyed with the `FMDatabase` connection is closed. + + For example, to create/open a database in your Mac OS X `tmp` folder: + + FMDatabase *db = [FMDatabase databaseWithPath:@"/tmp/tmp.db"]; + + Or, in iOS, you might open a database in the app's `Documents` directory: + + NSString *docsPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0]; + NSString *dbPath = [docsPath stringByAppendingPathComponent:@"test.db"]; + FMDatabase *db = [FMDatabase databaseWithPath:dbPath]; + + (For more information on temporary and in-memory databases, read the sqlite documentation on the subject: [http://www.sqlite.org/inmemorydb.html](http://www.sqlite.org/inmemorydb.html)) + + @param url The local file URL (not remote URL) of database file + + @return `FMDatabase` object if successful; `nil` if failure. + + */ + ++ (instancetype)databaseWithURL:(NSURL * _Nullable)url; + +/** Initialize a `FMDatabase` object. + + An `FMDatabase` is created with a path to a SQLite database file. This path can be one of these three: + + 1. A file system path. The file does not have to exist on disk. If it does not exist, it is created for you. + 2. An empty string (`@""`). An empty database is created at a temporary location. This database is deleted with the `FMDatabase` connection is closed. + 3. `nil`. An in-memory database is created. This database will be destroyed with the `FMDatabase` connection is closed. + + For example, to create/open a database in your Mac OS X `tmp` folder: + + FMDatabase *db = [FMDatabase databaseWithPath:@"/tmp/tmp.db"]; + + Or, in iOS, you might open a database in the app's `Documents` directory: + + NSString *docsPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0]; + NSString *dbPath = [docsPath stringByAppendingPathComponent:@"test.db"]; + FMDatabase *db = [FMDatabase databaseWithPath:dbPath]; + + (For more information on temporary and in-memory databases, read the sqlite documentation on the subject: [http://www.sqlite.org/inmemorydb.html](http://www.sqlite.org/inmemorydb.html)) + + @param path Path of database file. + + @return `FMDatabase` object if successful; `nil` if failure. + + */ + +- (instancetype)initWithPath:(NSString * _Nullable)path; + +/** Initialize a `FMDatabase` object. + + An `FMDatabase` is created with a local file URL to a SQLite database file. This path can be one of these three: + + 1. A file system URL. The file does not have to exist on disk. If it does not exist, it is created for you. + 2. `nil`. An in-memory database is created. This database will be destroyed with the `FMDatabase` connection is closed. + + For example, to create/open a database in your Mac OS X `tmp` folder: + + FMDatabase *db = [FMDatabase databaseWithPath:@"/tmp/tmp.db"]; + + Or, in iOS, you might open a database in the app's `Documents` directory: + + NSString *docsPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0]; + NSString *dbPath = [docsPath stringByAppendingPathComponent:@"test.db"]; + FMDatabase *db = [FMDatabase databaseWithPath:dbPath]; + + (For more information on temporary and in-memory databases, read the sqlite documentation on the subject: [http://www.sqlite.org/inmemorydb.html](http://www.sqlite.org/inmemorydb.html)) + + @param url The file `NSURL` of database file. + + @return `FMDatabase` object if successful; `nil` if failure. + + */ + +- (instancetype)initWithURL:(NSURL * _Nullable)url; + +///----------------------------------- +/// @name Opening and closing database +///----------------------------------- + +/** Opening a new database connection + + The database is opened for reading and writing, and is created if it does not already exist. + + @return `YES` if successful, `NO` on error. + + @see [sqlite3_open()](http://sqlite.org/c3ref/open.html) + @see openWithFlags: + @see close + */ + +- (BOOL)open; + +/** Opening a new database connection with flags and an optional virtual file system (VFS) + + @param flags one of the following three values, optionally combined with the `SQLITE_OPEN_NOMUTEX`, `SQLITE_OPEN_FULLMUTEX`, `SQLITE_OPEN_SHAREDCACHE`, `SQLITE_OPEN_PRIVATECACHE`, and/or `SQLITE_OPEN_URI` flags: + + `SQLITE_OPEN_READONLY` + + The database is opened in read-only mode. If the database does not already exist, an error is returned. + + `SQLITE_OPEN_READWRITE` + + The database is opened for reading and writing if possible, or reading only if the file is write protected by the operating system. In either case the database must already exist, otherwise an error is returned. + + `SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE` + + The database is opened for reading and writing, and is created if it does not already exist. This is the behavior that is always used for `open` method. + + @return `YES` if successful, `NO` on error. + + @see [sqlite3_open_v2()](http://sqlite.org/c3ref/open.html) + @see open + @see close + */ + +- (BOOL)openWithFlags:(int)flags; + +/** Opening a new database connection with flags and an optional virtual file system (VFS) + + @param flags one of the following three values, optionally combined with the `SQLITE_OPEN_NOMUTEX`, `SQLITE_OPEN_FULLMUTEX`, `SQLITE_OPEN_SHAREDCACHE`, `SQLITE_OPEN_PRIVATECACHE`, and/or `SQLITE_OPEN_URI` flags: + + `SQLITE_OPEN_READONLY` + + The database is opened in read-only mode. If the database does not already exist, an error is returned. + + `SQLITE_OPEN_READWRITE` + + The database is opened for reading and writing if possible, or reading only if the file is write protected by the operating system. In either case the database must already exist, otherwise an error is returned. + + `SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE` + + The database is opened for reading and writing, and is created if it does not already exist. This is the behavior that is always used for `open` method. + + @param vfsName If vfs is given the value is passed to the vfs parameter of sqlite3_open_v2. + + @return `YES` if successful, `NO` on error. + + @see [sqlite3_open_v2()](http://sqlite.org/c3ref/open.html) + @see open + @see close + */ + +- (BOOL)openWithFlags:(int)flags vfs:(NSString * _Nullable)vfsName; + +/** Closing a database connection + + @return `YES` if success, `NO` on error. + + @see [sqlite3_close()](http://sqlite.org/c3ref/close.html) + @see open + @see openWithFlags: + */ + +- (BOOL)close; + +/** Test to see if we have a good connection to the database. + + This will confirm whether: + + - is database open + - if open, it will try a simple SELECT statement and confirm that it succeeds. + + @return `YES` if everything succeeds, `NO` on failure. + */ + +@property (nonatomic, readonly) BOOL goodConnection; + + +///---------------------- +/// @name Perform updates +///---------------------- + +/** Execute single update statement + + This method executes a single SQL update statement (i.e. any SQL that does not return results, such as `UPDATE`, `INSERT`, or `DELETE`. This method employs [`sqlite3_prepare_v2`](http://sqlite.org/c3ref/prepare.html), [`sqlite3_bind`](http://sqlite.org/c3ref/bind_blob.html) to bind values to `?` placeholders in the SQL with the optional list of parameters, and [`sqlite_step`](http://sqlite.org/c3ref/step.html) to perform the update. + + The optional values provided to this method should be objects (e.g. `NSString`, `NSNumber`, `NSNull`, `NSDate`, and `NSData` objects), not fundamental data types (e.g. `int`, `long`, `NSInteger`, etc.). This method automatically handles the aforementioned object types, and all other object types will be interpreted as text values using the object's `description` method. + + @param sql The SQL to be performed, with optional `?` placeholders. + + @param outErr A reference to the `NSError` pointer to be updated with an auto released `NSError` object if an error if an error occurs. If `nil`, no `NSError` object will be returned. + + @param ... Optional parameters to bind to `?` placeholders in the SQL statement. These should be Objective-C objects (e.g. `NSString`, `NSNumber`, etc.), not fundamental C data types (e.g. `int`, `char *`, etc.). + + @return `YES` upon success; `NO` upon failure. If failed, you can call ``, ``, or `` for diagnostic information regarding the failure. + + @see lastError + @see lastErrorCode + @see lastErrorMessage + @see [`sqlite3_bind`](http://sqlite.org/c3ref/bind_blob.html) + */ + +- (BOOL)executeUpdate:(NSString*)sql withErrorAndBindings:(NSError * _Nullable *)outErr, ...; + +/** Execute single update statement + + @see executeUpdate:withErrorAndBindings: + + @warning **Deprecated**: Please use `` instead. + */ + +- (BOOL)update:(NSString*)sql withErrorAndBindings:(NSError * _Nullable*)outErr, ... __deprecated_msg("Use executeUpdate:withErrorAndBindings: instead");; + +/** Execute single update statement + + This method executes a single SQL update statement (i.e. any SQL that does not return results, such as `UPDATE`, `INSERT`, or `DELETE`. This method employs [`sqlite3_prepare_v2`](http://sqlite.org/c3ref/prepare.html), [`sqlite3_bind`](http://sqlite.org/c3ref/bind_blob.html) to bind values to `?` placeholders in the SQL with the optional list of parameters, and [`sqlite_step`](http://sqlite.org/c3ref/step.html) to perform the update. + + The optional values provided to this method should be objects (e.g. `NSString`, `NSNumber`, `NSNull`, `NSDate`, and `NSData` objects), not fundamental data types (e.g. `int`, `long`, `NSInteger`, etc.). This method automatically handles the aforementioned object types, and all other object types will be interpreted as text values using the object's `description` method. + + @param sql The SQL to be performed, with optional `?` placeholders. + + @param ... Optional parameters to bind to `?` placeholders in the SQL statement. These should be Objective-C objects (e.g. `NSString`, `NSNumber`, etc.), not fundamental C data types (e.g. `int`, `char *`, etc.). + + @return `YES` upon success; `NO` upon failure. If failed, you can call ``, ``, or `` for diagnostic information regarding the failure. + + @see lastError + @see lastErrorCode + @see lastErrorMessage + @see [`sqlite3_bind`](http://sqlite.org/c3ref/bind_blob.html) + + @note This technique supports the use of `?` placeholders in the SQL, automatically binding any supplied value parameters to those placeholders. This approach is more robust than techniques that entail using `stringWithFormat` to manually build SQL statements, which can be problematic if the values happened to include any characters that needed to be quoted. + + @note You cannot use this method from Swift due to incompatibilities between Swift and Objective-C variadic implementations. Consider using `` instead. + */ + +- (BOOL)executeUpdate:(NSString*)sql, ...; + +/** Execute single update statement + + This method executes a single SQL update statement (i.e. any SQL that does not return results, such as `UPDATE`, `INSERT`, or `DELETE`. This method employs [`sqlite3_prepare_v2`](http://sqlite.org/c3ref/prepare.html) and [`sqlite_step`](http://sqlite.org/c3ref/step.html) to perform the update. Unlike the other `executeUpdate` methods, this uses printf-style formatters (e.g. `%s`, `%d`, etc.) to build the SQL. Do not use `?` placeholders in the SQL if you use this method. + + @param format The SQL to be performed, with `printf`-style escape sequences. + + @param ... Optional parameters to bind to use in conjunction with the `printf`-style escape sequences in the SQL statement. + + @return `YES` upon success; `NO` upon failure. If failed, you can call ``, ``, or `` for diagnostic information regarding the failure. + + @see executeUpdate: + @see lastError + @see lastErrorCode + @see lastErrorMessage + + @note This method does not technically perform a traditional printf-style replacement. What this method actually does is replace the printf-style percent sequences with a SQLite `?` placeholder, and then bind values to that placeholder. Thus the following command + + [db executeUpdateWithFormat:@"INSERT INTO test (name) VALUES (%@)", @"Gus"]; + + is actually replacing the `%@` with `?` placeholder, and then performing something equivalent to `` + + [db executeUpdate:@"INSERT INTO test (name) VALUES (?)", @"Gus"]; + + There are two reasons why this distinction is important. First, the printf-style escape sequences can only be used where it is permissible to use a SQLite `?` placeholder. You can use it only for values in SQL statements, but not for table names or column names or any other non-value context. This method also cannot be used in conjunction with `pragma` statements and the like. Second, note the lack of quotation marks in the SQL. The `VALUES` clause was _not_ `VALUES ('%@')` (like you might have to do if you built a SQL statement using `NSString` method `stringWithFormat`), but rather simply `VALUES (%@)`. + */ + +- (BOOL)executeUpdateWithFormat:(NSString *)format, ... NS_FORMAT_FUNCTION(1,2); + +/** Execute single update statement + + This method executes a single SQL update statement (i.e. any SQL that does not return results, such as `UPDATE`, `INSERT`, or `DELETE`. This method employs [`sqlite3_prepare_v2`](http://sqlite.org/c3ref/prepare.html) and [`sqlite3_bind`](http://sqlite.org/c3ref/bind_blob.html) binding any `?` placeholders in the SQL with the optional list of parameters. + + The optional values provided to this method should be objects (e.g. `NSString`, `NSNumber`, `NSNull`, `NSDate`, and `NSData` objects), not fundamental data types (e.g. `int`, `long`, `NSInteger`, etc.). This method automatically handles the aforementioned object types, and all other object types will be interpreted as text values using the object's `description` method. + + @param sql The SQL to be performed, with optional `?` placeholders. + + @param arguments A `NSArray` of objects to be used when binding values to the `?` placeholders in the SQL statement. + + @return `YES` upon success; `NO` upon failure. If failed, you can call ``, ``, or `` for diagnostic information regarding the failure. + + @see executeUpdate:values:error: + @see lastError + @see lastErrorCode + @see lastErrorMessage + */ + +- (BOOL)executeUpdate:(NSString*)sql withArgumentsInArray:(NSArray *)arguments; + +/** Execute single update statement + + This method executes a single SQL update statement (i.e. any SQL that does not return results, such as `UPDATE`, `INSERT`, or `DELETE`. This method employs [`sqlite3_prepare_v2`](http://sqlite.org/c3ref/prepare.html) and [`sqlite3_bind`](http://sqlite.org/c3ref/bind_blob.html) binding any `?` placeholders in the SQL with the optional list of parameters. + + The optional values provided to this method should be objects (e.g. `NSString`, `NSNumber`, `NSNull`, `NSDate`, and `NSData` objects), not fundamental data types (e.g. `int`, `long`, `NSInteger`, etc.). This method automatically handles the aforementioned object types, and all other object types will be interpreted as text values using the object's `description` method. + + This is similar to ``, except that this also accepts a pointer to a `NSError` pointer, so that errors can be returned. + + In Swift, this throws errors, as if it were defined as follows: + + `func executeUpdate(sql: String, values: [Any]?) throws -> Bool` + + @param sql The SQL to be performed, with optional `?` placeholders. + + @param values A `NSArray` of objects to be used when binding values to the `?` placeholders in the SQL statement. + + @param error A `NSError` object to receive any error object (if any). + + @return `YES` upon success; `NO` upon failure. If failed, you can call ``, ``, or `` for diagnostic information regarding the failure. + + @see lastError + @see lastErrorCode + @see lastErrorMessage + + */ + +- (BOOL)executeUpdate:(NSString*)sql values:(NSArray * _Nullable)values error:(NSError * _Nullable __autoreleasing *)error; + +/** Execute single update statement + + This method executes a single SQL update statement (i.e. any SQL that does not return results, such as `UPDATE`, `INSERT`, or `DELETE`. This method employs [`sqlite3_prepare_v2`](http://sqlite.org/c3ref/prepare.html) and [`sqlite_step`](http://sqlite.org/c3ref/step.html) to perform the update. Unlike the other `executeUpdate` methods, this uses printf-style formatters (e.g. `%s`, `%d`, etc.) to build the SQL. + + The optional values provided to this method should be objects (e.g. `NSString`, `NSNumber`, `NSNull`, `NSDate`, and `NSData` objects), not fundamental data types (e.g. `int`, `long`, `NSInteger`, etc.). This method automatically handles the aforementioned object types, and all other object types will be interpreted as text values using the object's `description` method. + + @param sql The SQL to be performed, with optional `?` placeholders. + + @param arguments A `NSDictionary` of objects keyed by column names that will be used when binding values to the `?` placeholders in the SQL statement. + + @return `YES` upon success; `NO` upon failure. If failed, you can call ``, ``, or `` for diagnostic information regarding the failure. + + @see lastError + @see lastErrorCode + @see lastErrorMessage +*/ + +- (BOOL)executeUpdate:(NSString*)sql withParameterDictionary:(NSDictionary *)arguments; + + +/** Execute single update statement + + This method executes a single SQL update statement (i.e. any SQL that does not return results, such as `UPDATE`, `INSERT`, or `DELETE`. This method employs [`sqlite3_prepare_v2`](http://sqlite.org/c3ref/prepare.html) and [`sqlite_step`](http://sqlite.org/c3ref/step.html) to perform the update. Unlike the other `executeUpdate` methods, this uses printf-style formatters (e.g. `%s`, `%d`, etc.) to build the SQL. + + The optional values provided to this method should be objects (e.g. `NSString`, `NSNumber`, `NSNull`, `NSDate`, and `NSData` objects), not fundamental data types (e.g. `int`, `long`, `NSInteger`, etc.). This method automatically handles the aforementioned object types, and all other object types will be interpreted as text values using the object's `description` method. + + @param sql The SQL to be performed, with optional `?` placeholders. + + @param args A `va_list` of arguments. + + @return `YES` upon success; `NO` upon failure. If failed, you can call ``, ``, or `` for diagnostic information regarding the failure. + + @see lastError + @see lastErrorCode + @see lastErrorMessage + */ + +- (BOOL)executeUpdate:(NSString*)sql withVAList: (va_list)args; + +/** Execute multiple SQL statements + + This executes a series of SQL statements that are combined in a single string (e.g. the SQL generated by the `sqlite3` command line `.dump` command). This accepts no value parameters, but rather simply expects a single string with multiple SQL statements, each terminated with a semicolon. This uses `sqlite3_exec`. + + @param sql The SQL to be performed + + @return `YES` upon success; `NO` upon failure. If failed, you can call ``, ``, or `` for diagnostic information regarding the failure. + + @see executeStatements:withResultBlock: + @see [sqlite3_exec()](http://sqlite.org/c3ref/exec.html) + + */ + +- (BOOL)executeStatements:(NSString *)sql; + +/** Execute multiple SQL statements with callback handler + + This executes a series of SQL statements that are combined in a single string (e.g. the SQL generated by the `sqlite3` command line `.dump` command). This accepts no value parameters, but rather simply expects a single string with multiple SQL statements, each terminated with a semicolon. This uses `sqlite3_exec`. + + @param sql The SQL to be performed. + @param block A block that will be called for any result sets returned by any SQL statements. + Note, if you supply this block, it must return integer value, zero upon success (this would be a good opportunity to use SQLITE_OK), + non-zero value upon failure (which will stop the bulk execution of the SQL). If a statement returns values, the block will be called with the results from the query in NSDictionary *resultsDictionary. + This may be `nil` if you don't care to receive any results. + + @return `YES` upon success; `NO` upon failure. If failed, you can call ``, + ``, or `` for diagnostic information regarding the failure. + + @see executeStatements: + @see [sqlite3_exec()](http://sqlite.org/c3ref/exec.html) + + */ + +- (BOOL)executeStatements:(NSString *)sql withResultBlock:(__attribute__((noescape)) FMDBExecuteStatementsCallbackBlock _Nullable)block; + +/** Last insert rowid + + Each entry in an SQLite table has a unique 64-bit signed integer key called the "rowid". The rowid is always available as an undeclared column named `ROWID`, `OID`, or `_ROWID_` as long as those names are not also used by explicitly declared columns. If the table has a column of type `INTEGER PRIMARY KEY` then that column is another alias for the rowid. + + This routine returns the rowid of the most recent successful `INSERT` into the database from the database connection in the first argument. As of SQLite version 3.7.7, this routines records the last insert rowid of both ordinary tables and virtual tables. If no successful `INSERT`s have ever occurred on that database connection, zero is returned. + + @return The rowid of the last inserted row. + + @see [sqlite3_last_insert_rowid()](http://sqlite.org/c3ref/last_insert_rowid.html) + + */ + +@property (nonatomic, readonly) int64_t lastInsertRowId; + +/** The number of rows changed by prior SQL statement. + + This function returns the number of database rows that were changed or inserted or deleted by the most recently completed SQL statement on the database connection specified by the first parameter. Only changes that are directly specified by the INSERT, UPDATE, or DELETE statement are counted. + + @return The number of rows changed by prior SQL statement. + + @see [sqlite3_changes()](http://sqlite.org/c3ref/changes.html) + + */ + +@property (nonatomic, readonly) int changes; + + +///------------------------- +/// @name Retrieving results +///------------------------- + +/** Execute select statement + + Executing queries returns an `` object if successful, and `nil` upon failure. Like executing updates, there is a variant that accepts an `NSError **` parameter. Otherwise you should use the `` and `` methods to determine why a query failed. + + In order to iterate through the results of your query, you use a `while()` loop. You also need to "step" (via `<[FMResultSet next]>`) from one record to the other. + + This method employs [`sqlite3_bind`](http://sqlite.org/c3ref/bind_blob.html) for any optional value parameters. This properly escapes any characters that need escape sequences (e.g. quotation marks), which eliminates simple SQL errors as well as protects against SQL injection attacks. This method natively handles `NSString`, `NSNumber`, `NSNull`, `NSDate`, and `NSData` objects. All other object types will be interpreted as text values using the object's `description` method. + + @param sql The SELECT statement to be performed, with optional `?` placeholders. + + @param ... Optional parameters to bind to `?` placeholders in the SQL statement. These should be Objective-C objects (e.g. `NSString`, `NSNumber`, etc.), not fundamental C data types (e.g. `int`, `char *`, etc.). + + @return A `` for the result set upon success; `nil` upon failure. If failed, you can call ``, ``, or `` for diagnostic information regarding the failure. + + @see FMResultSet + @see [`FMResultSet next`](<[FMResultSet next]>) + @see [`sqlite3_bind`](http://sqlite.org/c3ref/bind_blob.html) + + @note You cannot use this method from Swift due to incompatibilities between Swift and Objective-C variadic implementations. Consider using `` instead. + */ + +- (FMResultSet * _Nullable)executeQuery:(NSString*)sql, ...; + +/** Execute select statement + + Executing queries returns an `` object if successful, and `nil` upon failure. Like executing updates, there is a variant that accepts an `NSError **` parameter. Otherwise you should use the `` and `` methods to determine why a query failed. + + In order to iterate through the results of your query, you use a `while()` loop. You also need to "step" (via `<[FMResultSet next]>`) from one record to the other. + + @param format The SQL to be performed, with `printf`-style escape sequences. + + @param ... Optional parameters to bind to use in conjunction with the `printf`-style escape sequences in the SQL statement. + + @return A `` for the result set upon success; `nil` upon failure. If failed, you can call ``, ``, or `` for diagnostic information regarding the failure. + + @see executeQuery: + @see FMResultSet + @see [`FMResultSet next`](<[FMResultSet next]>) + + @note This method does not technically perform a traditional printf-style replacement. What this method actually does is replace the printf-style percent sequences with a SQLite `?` placeholder, and then bind values to that placeholder. Thus the following command + + [db executeQueryWithFormat:@"SELECT * FROM test WHERE name=%@", @"Gus"]; + + is actually replacing the `%@` with `?` placeholder, and then performing something equivalent to `` + + [db executeQuery:@"SELECT * FROM test WHERE name=?", @"Gus"]; + + There are two reasons why this distinction is important. First, the printf-style escape sequences can only be used where it is permissible to use a SQLite `?` placeholder. You can use it only for values in SQL statements, but not for table names or column names or any other non-value context. This method also cannot be used in conjunction with `pragma` statements and the like. Second, note the lack of quotation marks in the SQL. The `WHERE` clause was _not_ `WHERE name='%@'` (like you might have to do if you built a SQL statement using `NSString` method `stringWithFormat`), but rather simply `WHERE name=%@`. + + */ + +- (FMResultSet * _Nullable)executeQueryWithFormat:(NSString*)format, ... NS_FORMAT_FUNCTION(1,2); + +/** Execute select statement + + Executing queries returns an `` object if successful, and `nil` upon failure. Like executing updates, there is a variant that accepts an `NSError **` parameter. Otherwise you should use the `` and `` methods to determine why a query failed. + + In order to iterate through the results of your query, you use a `while()` loop. You also need to "step" (via `<[FMResultSet next]>`) from one record to the other. + + @param sql The SELECT statement to be performed, with optional `?` placeholders. + + @param arguments A `NSArray` of objects to be used when binding values to the `?` placeholders in the SQL statement. + + @return A `` for the result set upon success; `nil` upon failure. If failed, you can call ``, ``, or `` for diagnostic information regarding the failure. + + @see -executeQuery:values:error: + @see FMResultSet + @see [`FMResultSet next`](<[FMResultSet next]>) + */ + +- (FMResultSet * _Nullable)executeQuery:(NSString *)sql withArgumentsInArray:(NSArray *)arguments; + +/** Execute select statement + + Executing queries returns an `` object if successful, and `nil` upon failure. Like executing updates, there is a variant that accepts an `NSError **` parameter. Otherwise you should use the `` and `` methods to determine why a query failed. + + In order to iterate through the results of your query, you use a `while()` loop. You also need to "step" (via `<[FMResultSet next]>`) from one record to the other. + + This is similar to ``, except that this also accepts a pointer to a `NSError` pointer, so that errors can be returned. + + In Swift, this throws errors, as if it were defined as follows: + + `func executeQuery(sql: String, values: [Any]?) throws -> FMResultSet!` + + @param sql The SELECT statement to be performed, with optional `?` placeholders. + + @param values A `NSArray` of objects to be used when binding values to the `?` placeholders in the SQL statement. + + @param error A `NSError` object to receive any error object (if any). + + @return A `` for the result set upon success; `nil` upon failure. If failed, you can call ``, ``, or `` for diagnostic information regarding the failure. + + @see FMResultSet + @see [`FMResultSet next`](<[FMResultSet next]>) + + @note When called from Swift, only use the first two parameters, `sql` and `values`. This but throws the error. + + */ + +- (FMResultSet * _Nullable)executeQuery:(NSString *)sql values:(NSArray * _Nullable)values error:(NSError * _Nullable __autoreleasing *)error; + +/** Execute select statement + + Executing queries returns an `` object if successful, and `nil` upon failure. Like executing updates, there is a variant that accepts an `NSError **` parameter. Otherwise you should use the `` and `` methods to determine why a query failed. + + In order to iterate through the results of your query, you use a `while()` loop. You also need to "step" (via `<[FMResultSet next]>`) from one record to the other. + + @param sql The SELECT statement to be performed, with optional `?` placeholders. + + @param arguments A `NSDictionary` of objects keyed by column names that will be used when binding values to the `?` placeholders in the SQL statement. + + @return A `` for the result set upon success; `nil` upon failure. If failed, you can call ``, ``, or `` for diagnostic information regarding the failure. + + @see FMResultSet + @see [`FMResultSet next`](<[FMResultSet next]>) + */ + +- (FMResultSet * _Nullable)executeQuery:(NSString *)sql withParameterDictionary:(NSDictionary * _Nullable)arguments; + + +// Documentation forthcoming. +- (FMResultSet * _Nullable)executeQuery:(NSString *)sql withVAList:(va_list)args; + +///------------------- +/// @name Transactions +///------------------- + +/** Begin a transaction + + @return `YES` on success; `NO` on failure. If failed, you can call ``, ``, or `` for diagnostic information regarding the failure. + + @see commit + @see rollback + @see beginDeferredTransaction + @see isInTransaction + */ + +- (BOOL)beginTransaction; + +/** Begin a deferred transaction + + @return `YES` on success; `NO` on failure. If failed, you can call ``, ``, or `` for diagnostic information regarding the failure. + + @see commit + @see rollback + @see beginTransaction + @see isInTransaction + */ + +- (BOOL)beginDeferredTransaction; + +/** Commit a transaction + + Commit a transaction that was initiated with either `` or with ``. + + @return `YES` on success; `NO` on failure. If failed, you can call ``, ``, or `` for diagnostic information regarding the failure. + + @see beginTransaction + @see beginDeferredTransaction + @see rollback + @see isInTransaction + */ + +- (BOOL)commit; + +/** Rollback a transaction + + Rollback a transaction that was initiated with either `` or with ``. + + @return `YES` on success; `NO` on failure. If failed, you can call ``, ``, or `` for diagnostic information regarding the failure. + + @see beginTransaction + @see beginDeferredTransaction + @see commit + @see isInTransaction + */ + +- (BOOL)rollback; + +/** Identify whether currently in a transaction or not + + @see beginTransaction + @see beginDeferredTransaction + @see commit + @see rollback + */ + +@property (nonatomic, readonly) BOOL isInTransaction; + +- (BOOL)inTransaction __deprecated_msg("Use isInTransaction property instead"); + + +///---------------------------------------- +/// @name Cached statements and result sets +///---------------------------------------- + +/** Clear cached statements */ + +- (void)clearCachedStatements; + +/** Close all open result sets */ + +- (void)closeOpenResultSets; + +/** Whether database has any open result sets + + @return `YES` if there are open result sets; `NO` if not. + */ + +@property (nonatomic, readonly) BOOL hasOpenResultSets; + +/** Whether should cache statements or not + */ + +@property (nonatomic) BOOL shouldCacheStatements; + +/** Interupt pending database operation + + This method causes any pending database operation to abort and return at its earliest opportunity + + @return `YES` on success; `NO` on failure. If failed, you can call ``, ``, or `` for diagnostic information regarding the failure. + + */ + +- (BOOL)interrupt; + +///------------------------- +/// @name Encryption methods +///------------------------- + +/** Set encryption key. + + @param key The key to be used. + + @return `YES` if success, `NO` on error. + + @see https://www.zetetic.net/sqlcipher/ + + @warning You need to have purchased the sqlite encryption extensions for this method to work. + */ + +- (BOOL)setKey:(NSString*)key; + +/** Reset encryption key + + @param key The key to be used. + + @return `YES` if success, `NO` on error. + + @see https://www.zetetic.net/sqlcipher/ + + @warning You need to have purchased the sqlite encryption extensions for this method to work. + */ + +- (BOOL)rekey:(NSString*)key; + +/** Set encryption key using `keyData`. + + @param keyData The `NSData` to be used. + + @return `YES` if success, `NO` on error. + + @see https://www.zetetic.net/sqlcipher/ + + @warning You need to have purchased the sqlite encryption extensions for this method to work. + */ + +- (BOOL)setKeyWithData:(NSData *)keyData; + +/** Reset encryption key using `keyData`. + + @param keyData The `NSData` to be used. + + @return `YES` if success, `NO` on error. + + @see https://www.zetetic.net/sqlcipher/ + + @warning You need to have purchased the sqlite encryption extensions for this method to work. + */ + +- (BOOL)rekeyWithData:(NSData *)keyData; + + +///------------------------------ +/// @name General inquiry methods +///------------------------------ + +/** The path of the database file + */ + +@property (nonatomic, readonly, nullable) NSString *databasePath; + +/** The file URL of the database file. + */ + +@property (nonatomic, readonly, nullable) NSURL *databaseURL; + +/** The underlying SQLite handle + + @return The `sqlite3` pointer. + + */ + +@property (nonatomic, readonly) void *sqliteHandle; + + +///----------------------------- +/// @name Retrieving error codes +///----------------------------- + +/** Last error message + + Returns the English-language text that describes the most recent failed SQLite API call associated with a database connection. If a prior API call failed but the most recent API call succeeded, this return value is undefined. + + @return `NSString` of the last error message. + + @see [sqlite3_errmsg()](http://sqlite.org/c3ref/errcode.html) + @see lastErrorCode + @see lastError + + */ + +- (NSString*)lastErrorMessage; + +/** Last error code + + Returns the numeric result code or extended result code for the most recent failed SQLite API call associated with a database connection. If a prior API call failed but the most recent API call succeeded, this return value is undefined. + + @return Integer value of the last error code. + + @see [sqlite3_errcode()](http://sqlite.org/c3ref/errcode.html) + @see lastErrorMessage + @see lastError + + */ + +- (int)lastErrorCode; + +/** Last extended error code + + Returns the numeric extended result code for the most recent failed SQLite API call associated with a database connection. If a prior API call failed but the most recent API call succeeded, this return value is undefined. + + @return Integer value of the last extended error code. + + @see [sqlite3_errcode()](http://sqlite.org/c3ref/errcode.html) + @see [2. Primary Result Codes versus Extended Result Codes](http://sqlite.org/rescode.html#primary_result_codes_versus_extended_result_codes) + @see [5. Extended Result Code List](http://sqlite.org/rescode.html#extrc) + @see lastErrorMessage + @see lastError + + */ + +- (int)lastExtendedErrorCode; + +/** Had error + + @return `YES` if there was an error, `NO` if no error. + + @see lastError + @see lastErrorCode + @see lastErrorMessage + + */ + +- (BOOL)hadError; + +/** Last error + + @return `NSError` representing the last error. + + @see lastErrorCode + @see lastErrorMessage + + */ + +- (NSError *)lastError; + + +// description forthcoming +@property (nonatomic) NSTimeInterval maxBusyRetryTimeInterval; + + +///------------------ +/// @name Save points +///------------------ + +/** Start save point + + @param name Name of save point. + + @param outErr A `NSError` object to receive any error object (if any). + + @return `YES` on success; `NO` on failure. If failed, you can call ``, ``, or `` for diagnostic information regarding the failure. + + @see releaseSavePointWithName:error: + @see rollbackToSavePointWithName:error: + */ + +- (BOOL)startSavePointWithName:(NSString*)name error:(NSError * _Nullable *)outErr; + +/** Release save point + + @param name Name of save point. + + @param outErr A `NSError` object to receive any error object (if any). + + @return `YES` on success; `NO` on failure. If failed, you can call ``, ``, or `` for diagnostic information regarding the failure. + + @see startSavePointWithName:error: + @see rollbackToSavePointWithName:error: + + */ + +- (BOOL)releaseSavePointWithName:(NSString*)name error:(NSError * _Nullable *)outErr; + +/** Roll back to save point + + @param name Name of save point. + @param outErr A `NSError` object to receive any error object (if any). + + @return `YES` on success; `NO` on failure. If failed, you can call ``, ``, or `` for diagnostic information regarding the failure. + + @see startSavePointWithName:error: + @see releaseSavePointWithName:error: + + */ + +- (BOOL)rollbackToSavePointWithName:(NSString*)name error:(NSError * _Nullable *)outErr; + +/** Start save point + + @param block Block of code to perform from within save point. + + @return The NSError corresponding to the error, if any. If no error, returns `nil`. + + @see startSavePointWithName:error: + @see releaseSavePointWithName:error: + @see rollbackToSavePointWithName:error: + + */ + +- (NSError * _Nullable)inSavePoint:(__attribute__((noescape)) void (^)(BOOL *rollback))block; + +///---------------------------- +/// @name SQLite library status +///---------------------------- + +/** Test to see if the library is threadsafe + + @return `NO` if and only if SQLite was compiled with mutexing code omitted due to the SQLITE_THREADSAFE compile-time option being set to 0. + + @see [sqlite3_threadsafe()](http://sqlite.org/c3ref/threadsafe.html) + */ + ++ (BOOL)isSQLiteThreadSafe; + +/** Run-time library version numbers + + @return The sqlite library version string. + + @see [sqlite3_libversion()](http://sqlite.org/c3ref/libversion.html) + */ + ++ (NSString*)sqliteLibVersion; + + ++ (NSString*)FMDBUserVersion; + ++ (SInt32)FMDBVersion; + + +///------------------------ +/// @name Make SQL function +///------------------------ + +/** Adds SQL functions or aggregates or to redefine the behavior of existing SQL functions or aggregates. + + For example: + + [db makeFunctionNamed:@"RemoveDiacritics" arguments:1 block:^(void *context, int argc, void **argv) { + SqliteValueType type = [self.db valueType:argv[0]]; + if (type == SqliteValueTypeNull) { + [self.db resultNullInContext:context]; + return; + } + if (type != SqliteValueTypeText) { + [self.db resultError:@"Expected text" context:context]; + return; + } + NSString *string = [self.db valueString:argv[0]]; + NSString *result = [string stringByFoldingWithOptions:NSDiacriticInsensitiveSearch locale:nil]; + [self.db resultString:result context:context]; + }]; + + FMResultSet *rs = [db executeQuery:@"SELECT * FROM employees WHERE RemoveDiacritics(first_name) LIKE 'jose'"]; + NSAssert(rs, @"Error %@", [db lastErrorMessage]); + + @param name Name of function. + + @param arguments Maximum number of parameters. + + @param block The block of code for the function. + + @see [sqlite3_create_function()](http://sqlite.org/c3ref/create_function.html) + */ + +- (void)makeFunctionNamed:(NSString *)name arguments:(int)arguments block:(void (^)(void *context, int argc, void * _Nonnull * _Nonnull argv))block; + +- (void)makeFunctionNamed:(NSString *)name maximumArguments:(int)count withBlock:(void (^)(void *context, int argc, void * _Nonnull * _Nonnull argv))block __deprecated_msg("Use makeFunctionNamed:arguments:block:"); + +typedef NS_ENUM(int, SqliteValueType) { + SqliteValueTypeInteger = 1, + SqliteValueTypeFloat = 2, + SqliteValueTypeText = 3, + SqliteValueTypeBlob = 4, + SqliteValueTypeNull = 5 +}; + +- (SqliteValueType)valueType:(void *)argv; + +/** + Get integer value of parameter in custom function. + + @param value The argument whose value to return. + @return The integer value. + + @see makeFunctionNamed:arguments:block: + */ +- (int)valueInt:(void *)value; + +/** + Get long value of parameter in custom function. + + @param value The argument whose value to return. + @return The long value. + + @see makeFunctionNamed:arguments:block: + */ +- (long long)valueLong:(void *)value; + +/** + Get double value of parameter in custom function. + + @param value The argument whose value to return. + @return The double value. + + @see makeFunctionNamed:arguments:block: + */ +- (double)valueDouble:(void *)value; + +/** + Get `NSData` value of parameter in custom function. + + @param value The argument whose value to return. + @return The data object. + + @see makeFunctionNamed:arguments:block: + */ +- (NSData * _Nullable)valueData:(void *)value; + +/** + Get string value of parameter in custom function. + + @param value The argument whose value to return. + @return The string value. + + @see makeFunctionNamed:arguments:block: + */ +- (NSString * _Nullable)valueString:(void *)value; + +/** + Return null value from custom function. + + @param context The context to which the null value will be returned. + + @see makeFunctionNamed:arguments:block: + */ +- (void)resultNullInContext:(void *)context NS_SWIFT_NAME(resultNull(context:)); + +/** + Return integer value from custom function. + + @param value The integer value to be returned. + @param context The context to which the value will be returned. + + @see makeFunctionNamed:arguments:block: + */ +- (void)resultInt:(int) value context:(void *)context; + +/** + Return long value from custom function. + + @param value The long value to be returned. + @param context The context to which the value will be returned. + + @see makeFunctionNamed:arguments:block: + */ +- (void)resultLong:(long long)value context:(void *)context; + +/** + Return double value from custom function. + + @param value The double value to be returned. + @param context The context to which the value will be returned. + + @see makeFunctionNamed:arguments:block: + */ +- (void)resultDouble:(double)value context:(void *)context; + +/** + Return `NSData` object from custom function. + + @param data The `NSData` object to be returned. + @param context The context to which the value will be returned. + + @see makeFunctionNamed:arguments:block: + */ +- (void)resultData:(NSData *)data context:(void *)context; + +/** + Return string value from custom function. + + @param value The string value to be returned. + @param context The context to which the value will be returned. + + @see makeFunctionNamed:arguments:block: + */ +- (void)resultString:(NSString *)value context:(void *)context; + +/** + Return error string from custom function. + + @param error The error string to be returned. + @param context The context to which the error will be returned. + + @see makeFunctionNamed:arguments:block: + */ +- (void)resultError:(NSString *)error context:(void *)context; + +/** + Return error code from custom function. + + @param errorCode The integer error code to be returned. + @param context The context to which the error will be returned. + + @see makeFunctionNamed:arguments:block: + */ +- (void)resultErrorCode:(int)errorCode context:(void *)context; + +/** + Report memory error in custom function. + + @param context The context to which the error will be returned. + + @see makeFunctionNamed:arguments:block: + */ +- (void)resultErrorNoMemoryInContext:(void *)context NS_SWIFT_NAME(resultErrorNoMemory(context:)); + +/** + Report that string or BLOB is too long to represent in custom function. + + @param context The context to which the error will be returned. + + @see makeFunctionNamed:arguments:block: + */ +- (void)resultErrorTooBigInContext:(void *)context NS_SWIFT_NAME(resultErrorTooBig(context:)); + +///--------------------- +/// @name Date formatter +///--------------------- + +/** Generate an `NSDateFormatter` that won't be broken by permutations of timezones or locales. + + Use this method to generate values to set the dateFormat property. + + Example: + + myDB.dateFormat = [FMDatabase storeableDateFormat:@"yyyy-MM-dd HH:mm:ss"]; + + @param format A valid NSDateFormatter format string. + + @return A `NSDateFormatter` that can be used for converting dates to strings and vice versa. + + @see hasDateFormatter + @see setDateFormat: + @see dateFromString: + @see stringFromDate: + @see storeableDateFormat: + + @warning Note that `NSDateFormatter` is not thread-safe, so the formatter generated by this method should be assigned to only one FMDB instance and should not be used for other purposes. + + */ + ++ (NSDateFormatter *)storeableDateFormat:(NSString *)format; + +/** Test whether the database has a date formatter assigned. + + @return `YES` if there is a date formatter; `NO` if not. + + @see hasDateFormatter + @see setDateFormat: + @see dateFromString: + @see stringFromDate: + @see storeableDateFormat: + */ + +- (BOOL)hasDateFormatter; + +/** Set to a date formatter to use string dates with sqlite instead of the default UNIX timestamps. + + @param format Set to nil to use UNIX timestamps. Defaults to nil. Should be set using a formatter generated using FMDatabase::storeableDateFormat. + + @see hasDateFormatter + @see setDateFormat: + @see dateFromString: + @see stringFromDate: + @see storeableDateFormat: + + @warning Note there is no direct getter for the `NSDateFormatter`, and you should not use the formatter you pass to FMDB for other purposes, as `NSDateFormatter` is not thread-safe. + */ + +- (void)setDateFormat:(NSDateFormatter *)format; + +/** Convert the supplied NSString to NSDate, using the current database formatter. + + @param s `NSString` to convert to `NSDate`. + + @return The `NSDate` object; or `nil` if no formatter is set. + + @see hasDateFormatter + @see setDateFormat: + @see dateFromString: + @see stringFromDate: + @see storeableDateFormat: + */ + +- (NSDate * _Nullable)dateFromString:(NSString *)s; + +/** Convert the supplied NSDate to NSString, using the current database formatter. + + @param date `NSDate` of date to convert to `NSString`. + + @return The `NSString` representation of the date; `nil` if no formatter is set. + + @see hasDateFormatter + @see setDateFormat: + @see dateFromString: + @see stringFromDate: + @see storeableDateFormat: + */ + +- (NSString *)stringFromDate:(NSDate *)date; + +@end + + +/** Objective-C wrapper for `sqlite3_stmt` + + This is a wrapper for a SQLite `sqlite3_stmt`. Generally when using FMDB you will not need to interact directly with `FMStatement`, but rather with `` and `` only. + + ### See also + + - `` + - `` + - [`sqlite3_stmt`](http://www.sqlite.org/c3ref/stmt.html) + */ + +@interface FMStatement : NSObject { + void *_statement; + NSString *_query; + long _useCount; + BOOL _inUse; +} + +///----------------- +/// @name Properties +///----------------- + +/** Usage count */ + +@property (atomic, assign) long useCount; + +/** SQL statement */ + +@property (atomic, retain) NSString *query; + +/** SQLite sqlite3_stmt + + @see [`sqlite3_stmt`](http://www.sqlite.org/c3ref/stmt.html) + */ + +@property (atomic, assign) void *statement; + +/** Indication of whether the statement is in use */ + +@property (atomic, assign) BOOL inUse; + +///---------------------------- +/// @name Closing and Resetting +///---------------------------- + +/** Close statement */ + +- (void)close; + +/** Reset statement */ + +- (void)reset; + +@end + +#pragma clang diagnostic pop + +NS_ASSUME_NONNULL_END diff --git a/lib/ios/AirMaps/fmdb/FMDatabase.m b/lib/ios/AirMaps/fmdb/FMDatabase.m new file mode 100644 index 000000000..493e772ea --- /dev/null +++ b/lib/ios/AirMaps/fmdb/FMDatabase.m @@ -0,0 +1,1596 @@ +#import "FMDatabase.h" +#import "unistd.h" +#import + +#if FMDB_SQLITE_STANDALONE +#import +#else +#import +#endif + +@interface FMDatabase () { + void* _db; + BOOL _isExecutingStatement; + NSTimeInterval _startBusyRetryTime; + + NSMutableSet *_openResultSets; + NSMutableSet *_openFunctions; + + NSDateFormatter *_dateFormat; +} + +NS_ASSUME_NONNULL_BEGIN + +- (FMResultSet * _Nullable)executeQuery:(NSString *)sql withArgumentsInArray:(NSArray * _Nullable)arrayArgs orDictionary:(NSDictionary * _Nullable)dictionaryArgs orVAList:(va_list)args; +- (BOOL)executeUpdate:(NSString *)sql error:(NSError * _Nullable *)outErr withArgumentsInArray:(NSArray * _Nullable)arrayArgs orDictionary:(NSDictionary * _Nullable)dictionaryArgs orVAList:(va_list)args; + +NS_ASSUME_NONNULL_END + +@end + +@implementation FMDatabase + +// Because these two properties have all of their accessor methods implemented, +// we have to synthesize them to get the corresponding ivars. The rest of the +// properties have their ivars synthesized automatically for us. + +@synthesize shouldCacheStatements = _shouldCacheStatements; +@synthesize maxBusyRetryTimeInterval = _maxBusyRetryTimeInterval; + +#pragma mark FMDatabase instantiation and deallocation + ++ (instancetype)databaseWithPath:(NSString *)aPath { + return FMDBReturnAutoreleased([[self alloc] initWithPath:aPath]); +} + ++ (instancetype)databaseWithURL:(NSURL *)url { + return FMDBReturnAutoreleased([[self alloc] initWithURL:url]); +} + +- (instancetype)init { + return [self initWithPath:nil]; +} + +- (instancetype)initWithURL:(NSURL *)url { + return [self initWithPath:url.path]; +} + +- (instancetype)initWithPath:(NSString *)path { + + assert(sqlite3_threadsafe()); // whoa there big boy- gotta make sure sqlite it happy with what we're going to do. + + self = [super init]; + + if (self) { + _databasePath = [path copy]; + _openResultSets = [[NSMutableSet alloc] init]; + _db = nil; + _logsErrors = YES; + _crashOnErrors = NO; + _maxBusyRetryTimeInterval = 2; + } + + return self; +} + +#if ! __has_feature(objc_arc) +- (void)finalize { + [self close]; + [super finalize]; +} +#endif + +- (void)dealloc { + [self close]; + FMDBRelease(_openResultSets); + FMDBRelease(_cachedStatements); + FMDBRelease(_dateFormat); + FMDBRelease(_databasePath); + FMDBRelease(_openFunctions); + +#if ! __has_feature(objc_arc) + [super dealloc]; +#endif +} + +- (NSURL *)databaseURL { + return _databasePath ? [NSURL fileURLWithPath:_databasePath] : nil; +} + ++ (NSString*)FMDBUserVersion { + return @"2.7.2"; +} + +// returns 0x0240 for version 2.4. This makes it super easy to do things like: +// /* need to make sure to do X with FMDB version 2.4 or later */ +// if ([FMDatabase FMDBVersion] >= 0x0240) { … } + ++ (SInt32)FMDBVersion { + + // we go through these hoops so that we only have to change the version number in a single spot. + static dispatch_once_t once; + static SInt32 FMDBVersionVal = 0; + + dispatch_once(&once, ^{ + NSString *prodVersion = [self FMDBUserVersion]; + + if ([[prodVersion componentsSeparatedByString:@"."] count] < 3) { + prodVersion = [prodVersion stringByAppendingString:@".0"]; + } + + NSString *junk = [prodVersion stringByReplacingOccurrencesOfString:@"." withString:@""]; + + char *e = nil; + FMDBVersionVal = (int) strtoul([junk UTF8String], &e, 16); + + }); + + return FMDBVersionVal; +} + +#pragma mark SQLite information + ++ (NSString*)sqliteLibVersion { + return [NSString stringWithFormat:@"%s", sqlite3_libversion()]; +} + ++ (BOOL)isSQLiteThreadSafe { + // make sure to read the sqlite headers on this guy! + return sqlite3_threadsafe() != 0; +} + +- (void*)sqliteHandle { + return _db; +} + +- (const char*)sqlitePath { + + if (!_databasePath) { + return ":memory:"; + } + + if ([_databasePath length] == 0) { + return ""; // this creates a temporary database (it's an sqlite thing). + } + + return [_databasePath fileSystemRepresentation]; + +} + +#pragma mark Open and close database + +- (BOOL)open { + if (_db) { + return YES; + } + + int err = sqlite3_open([self sqlitePath], (sqlite3**)&_db ); + if(err != SQLITE_OK) { + NSLog(@"error opening!: %d", err); + return NO; + } + + if (_maxBusyRetryTimeInterval > 0.0) { + // set the handler + [self setMaxBusyRetryTimeInterval:_maxBusyRetryTimeInterval]; + } + + + return YES; +} + +- (BOOL)openWithFlags:(int)flags { + return [self openWithFlags:flags vfs:nil]; +} +- (BOOL)openWithFlags:(int)flags vfs:(NSString *)vfsName { +#if SQLITE_VERSION_NUMBER >= 3005000 + if (_db) { + return YES; + } + + int err = sqlite3_open_v2([self sqlitePath], (sqlite3**)&_db, flags, [vfsName UTF8String]); + if(err != SQLITE_OK) { + NSLog(@"error opening!: %d", err); + return NO; + } + + if (_maxBusyRetryTimeInterval > 0.0) { + // set the handler + [self setMaxBusyRetryTimeInterval:_maxBusyRetryTimeInterval]; + } + + return YES; +#else + NSLog(@"openWithFlags requires SQLite 3.5"); + return NO; +#endif +} + + +- (BOOL)close { + + [self clearCachedStatements]; + [self closeOpenResultSets]; + + if (!_db) { + return YES; + } + + int rc; + BOOL retry; + BOOL triedFinalizingOpenStatements = NO; + + do { + retry = NO; + rc = sqlite3_close(_db); + if (SQLITE_BUSY == rc || SQLITE_LOCKED == rc) { + if (!triedFinalizingOpenStatements) { + triedFinalizingOpenStatements = YES; + sqlite3_stmt *pStmt; + while ((pStmt = sqlite3_next_stmt(_db, nil)) !=0) { + NSLog(@"Closing leaked statement"); + sqlite3_finalize(pStmt); + retry = YES; + } + } + } + else if (SQLITE_OK != rc) { + NSLog(@"error closing!: %d", rc); + } + } + while (retry); + + _db = nil; + return YES; +} + +#pragma mark Busy handler routines + +// NOTE: appledoc seems to choke on this function for some reason; +// so when generating documentation, you might want to ignore the +// .m files so that it only documents the public interfaces outlined +// in the .h files. +// +// This is a known appledoc bug that it has problems with C functions +// within a class implementation, but for some reason, only this +// C function causes problems; the rest don't. Anyway, ignoring the .m +// files with appledoc will prevent this problem from occurring. + +static int FMDBDatabaseBusyHandler(void *f, int count) { + FMDatabase *self = (__bridge FMDatabase*)f; + + if (count == 0) { + self->_startBusyRetryTime = [NSDate timeIntervalSinceReferenceDate]; + return 1; + } + + NSTimeInterval delta = [NSDate timeIntervalSinceReferenceDate] - (self->_startBusyRetryTime); + + if (delta < [self maxBusyRetryTimeInterval]) { + int requestedSleepInMillseconds = (int) arc4random_uniform(50) + 50; + int actualSleepInMilliseconds = sqlite3_sleep(requestedSleepInMillseconds); + if (actualSleepInMilliseconds != requestedSleepInMillseconds) { + NSLog(@"WARNING: Requested sleep of %i milliseconds, but SQLite returned %i. Maybe SQLite wasn't built with HAVE_USLEEP=1?", requestedSleepInMillseconds, actualSleepInMilliseconds); + } + return 1; + } + + return 0; +} + +- (void)setMaxBusyRetryTimeInterval:(NSTimeInterval)timeout { + + _maxBusyRetryTimeInterval = timeout; + + if (!_db) { + return; + } + + if (timeout > 0) { + sqlite3_busy_handler(_db, &FMDBDatabaseBusyHandler, (__bridge void *)(self)); + } + else { + // turn it off otherwise + sqlite3_busy_handler(_db, nil, nil); + } +} + +- (NSTimeInterval)maxBusyRetryTimeInterval { + return _maxBusyRetryTimeInterval; +} + + +// we no longer make busyRetryTimeout public +// but for folks who don't bother noticing that the interface to FMDatabase changed, +// we'll still implement the method so they don't get suprise crashes +- (int)busyRetryTimeout { + NSLog(@"%s:%d", __FUNCTION__, __LINE__); + NSLog(@"FMDB: busyRetryTimeout no longer works, please use maxBusyRetryTimeInterval"); + return -1; +} + +- (void)setBusyRetryTimeout:(int)i { +#pragma unused(i) + NSLog(@"%s:%d", __FUNCTION__, __LINE__); + NSLog(@"FMDB: setBusyRetryTimeout does nothing, please use setMaxBusyRetryTimeInterval:"); +} + +#pragma mark Result set functions + +- (BOOL)hasOpenResultSets { + return [_openResultSets count] > 0; +} + +- (void)closeOpenResultSets { + + //Copy the set so we don't get mutation errors + NSSet *openSetCopy = FMDBReturnAutoreleased([_openResultSets copy]); + for (NSValue *rsInWrappedInATastyValueMeal in openSetCopy) { + FMResultSet *rs = (FMResultSet *)[rsInWrappedInATastyValueMeal pointerValue]; + + [rs setParentDB:nil]; + [rs close]; + + [_openResultSets removeObject:rsInWrappedInATastyValueMeal]; + } +} + +- (void)resultSetDidClose:(FMResultSet *)resultSet { + NSValue *setValue = [NSValue valueWithNonretainedObject:resultSet]; + + [_openResultSets removeObject:setValue]; +} + +#pragma mark Cached statements + +- (void)clearCachedStatements { + + for (NSMutableSet *statements in [_cachedStatements objectEnumerator]) { + for (FMStatement *statement in [statements allObjects]) { + [statement close]; + } + } + + [_cachedStatements removeAllObjects]; +} + +- (FMStatement*)cachedStatementForQuery:(NSString*)query { + + NSMutableSet* statements = [_cachedStatements objectForKey:query]; + + return [[statements objectsPassingTest:^BOOL(FMStatement* statement, BOOL *stop) { + + *stop = ![statement inUse]; + return *stop; + + }] anyObject]; +} + + +- (void)setCachedStatement:(FMStatement*)statement forQuery:(NSString*)query { + + query = [query copy]; // in case we got handed in a mutable string... + [statement setQuery:query]; + + NSMutableSet* statements = [_cachedStatements objectForKey:query]; + if (!statements) { + statements = [NSMutableSet set]; + } + + [statements addObject:statement]; + + [_cachedStatements setObject:statements forKey:query]; + + FMDBRelease(query); +} + +#pragma mark Key routines + +- (BOOL)rekey:(NSString*)key { + NSData *keyData = [NSData dataWithBytes:(void *)[key UTF8String] length:(NSUInteger)strlen([key UTF8String])]; + + return [self rekeyWithData:keyData]; +} + +- (BOOL)rekeyWithData:(NSData *)keyData { +#ifdef SQLITE_HAS_CODEC + if (!keyData) { + return NO; + } + + int rc = sqlite3_rekey(_db, [keyData bytes], (int)[keyData length]); + + if (rc != SQLITE_OK) { + NSLog(@"error on rekey: %d", rc); + NSLog(@"%@", [self lastErrorMessage]); + } + + return (rc == SQLITE_OK); +#else +#pragma unused(keyData) + return NO; +#endif +} + +- (BOOL)setKey:(NSString*)key { + NSData *keyData = [NSData dataWithBytes:[key UTF8String] length:(NSUInteger)strlen([key UTF8String])]; + + return [self setKeyWithData:keyData]; +} + +- (BOOL)setKeyWithData:(NSData *)keyData { +#ifdef SQLITE_HAS_CODEC + if (!keyData) { + return NO; + } + + int rc = sqlite3_key(_db, [keyData bytes], (int)[keyData length]); + + return (rc == SQLITE_OK); +#else +#pragma unused(keyData) + return NO; +#endif +} + +#pragma mark Date routines + ++ (NSDateFormatter *)storeableDateFormat:(NSString *)format { + + NSDateFormatter *result = FMDBReturnAutoreleased([[NSDateFormatter alloc] init]); + result.dateFormat = format; + result.timeZone = [NSTimeZone timeZoneForSecondsFromGMT:0]; + result.locale = FMDBReturnAutoreleased([[NSLocale alloc] initWithLocaleIdentifier:@"en_US"]); + return result; +} + + +- (BOOL)hasDateFormatter { + return _dateFormat != nil; +} + +- (void)setDateFormat:(NSDateFormatter *)format { + FMDBAutorelease(_dateFormat); + _dateFormat = FMDBReturnRetained(format); +} + +- (NSDate *)dateFromString:(NSString *)s { + return [_dateFormat dateFromString:s]; +} + +- (NSString *)stringFromDate:(NSDate *)date { + return [_dateFormat stringFromDate:date]; +} + +#pragma mark State of database + +- (BOOL)goodConnection { + + if (!_db) { + return NO; + } + + FMResultSet *rs = [self executeQuery:@"select name from sqlite_master where type='table'"]; + + if (rs) { + [rs close]; + return YES; + } + + return NO; +} + +- (void)warnInUse { + NSLog(@"The FMDatabase %@ is currently in use.", self); + +#ifndef NS_BLOCK_ASSERTIONS + if (_crashOnErrors) { + NSAssert(false, @"The FMDatabase %@ is currently in use.", self); + abort(); + } +#endif +} + +- (BOOL)databaseExists { + + if (!_db) { + + NSLog(@"The FMDatabase %@ is not open.", self); + +#ifndef NS_BLOCK_ASSERTIONS + if (_crashOnErrors) { + NSAssert(false, @"The FMDatabase %@ is not open.", self); + abort(); + } +#endif + + return NO; + } + + return YES; +} + +#pragma mark Error routines + +- (NSString *)lastErrorMessage { + return [NSString stringWithUTF8String:sqlite3_errmsg(_db)]; +} + +- (BOOL)hadError { + int lastErrCode = [self lastErrorCode]; + + return (lastErrCode > SQLITE_OK && lastErrCode < SQLITE_ROW); +} + +- (int)lastErrorCode { + return sqlite3_errcode(_db); +} + +- (int)lastExtendedErrorCode { + return sqlite3_extended_errcode(_db); +} + +- (NSError*)errorWithMessage:(NSString *)message { + NSDictionary* errorMessage = [NSDictionary dictionaryWithObject:message forKey:NSLocalizedDescriptionKey]; + + return [NSError errorWithDomain:@"FMDatabase" code:sqlite3_errcode(_db) userInfo:errorMessage]; +} + +- (NSError*)lastError { + return [self errorWithMessage:[self lastErrorMessage]]; +} + +#pragma mark Update information routines + +- (sqlite_int64)lastInsertRowId { + + if (_isExecutingStatement) { + [self warnInUse]; + return NO; + } + + _isExecutingStatement = YES; + + sqlite_int64 ret = sqlite3_last_insert_rowid(_db); + + _isExecutingStatement = NO; + + return ret; +} + +- (int)changes { + if (_isExecutingStatement) { + [self warnInUse]; + return 0; + } + + _isExecutingStatement = YES; + + int ret = sqlite3_changes(_db); + + _isExecutingStatement = NO; + + return ret; +} + +#pragma mark SQL manipulation + +- (void)bindObject:(id)obj toColumn:(int)idx inStatement:(sqlite3_stmt*)pStmt { + + if ((!obj) || ((NSNull *)obj == [NSNull null])) { + sqlite3_bind_null(pStmt, idx); + } + + // FIXME - someday check the return codes on these binds. + else if ([obj isKindOfClass:[NSData class]]) { + const void *bytes = [obj bytes]; + if (!bytes) { + // it's an empty NSData object, aka [NSData data]. + // Don't pass a NULL pointer, or sqlite will bind a SQL null instead of a blob. + bytes = ""; + } + sqlite3_bind_blob(pStmt, idx, bytes, (int)[obj length], SQLITE_STATIC); + } + else if ([obj isKindOfClass:[NSDate class]]) { + if (self.hasDateFormatter) + sqlite3_bind_text(pStmt, idx, [[self stringFromDate:obj] UTF8String], -1, SQLITE_STATIC); + else + sqlite3_bind_double(pStmt, idx, [obj timeIntervalSince1970]); + } + else if ([obj isKindOfClass:[NSNumber class]]) { + + if (strcmp([obj objCType], @encode(char)) == 0) { + sqlite3_bind_int(pStmt, idx, [obj charValue]); + } + else if (strcmp([obj objCType], @encode(unsigned char)) == 0) { + sqlite3_bind_int(pStmt, idx, [obj unsignedCharValue]); + } + else if (strcmp([obj objCType], @encode(short)) == 0) { + sqlite3_bind_int(pStmt, idx, [obj shortValue]); + } + else if (strcmp([obj objCType], @encode(unsigned short)) == 0) { + sqlite3_bind_int(pStmt, idx, [obj unsignedShortValue]); + } + else if (strcmp([obj objCType], @encode(int)) == 0) { + sqlite3_bind_int(pStmt, idx, [obj intValue]); + } + else if (strcmp([obj objCType], @encode(unsigned int)) == 0) { + sqlite3_bind_int64(pStmt, idx, (long long)[obj unsignedIntValue]); + } + else if (strcmp([obj objCType], @encode(long)) == 0) { + sqlite3_bind_int64(pStmt, idx, [obj longValue]); + } + else if (strcmp([obj objCType], @encode(unsigned long)) == 0) { + sqlite3_bind_int64(pStmt, idx, (long long)[obj unsignedLongValue]); + } + else if (strcmp([obj objCType], @encode(long long)) == 0) { + sqlite3_bind_int64(pStmt, idx, [obj longLongValue]); + } + else if (strcmp([obj objCType], @encode(unsigned long long)) == 0) { + sqlite3_bind_int64(pStmt, idx, (long long)[obj unsignedLongLongValue]); + } + else if (strcmp([obj objCType], @encode(float)) == 0) { + sqlite3_bind_double(pStmt, idx, [obj floatValue]); + } + else if (strcmp([obj objCType], @encode(double)) == 0) { + sqlite3_bind_double(pStmt, idx, [obj doubleValue]); + } + else if (strcmp([obj objCType], @encode(BOOL)) == 0) { + sqlite3_bind_int(pStmt, idx, ([obj boolValue] ? 1 : 0)); + } + else { + sqlite3_bind_text(pStmt, idx, [[obj description] UTF8String], -1, SQLITE_STATIC); + } + } + else { + sqlite3_bind_text(pStmt, idx, [[obj description] UTF8String], -1, SQLITE_STATIC); + } +} + +- (void)extractSQL:(NSString *)sql argumentsList:(va_list)args intoString:(NSMutableString *)cleanedSQL arguments:(NSMutableArray *)arguments { + + NSUInteger length = [sql length]; + unichar last = '\0'; + for (NSUInteger i = 0; i < length; ++i) { + id arg = nil; + unichar current = [sql characterAtIndex:i]; + unichar add = current; + if (last == '%') { + switch (current) { + case '@': + arg = va_arg(args, id); + break; + case 'c': + // warning: second argument to 'va_arg' is of promotable type 'char'; this va_arg has undefined behavior because arguments will be promoted to 'int' + arg = [NSString stringWithFormat:@"%c", va_arg(args, int)]; + break; + case 's': + arg = [NSString stringWithUTF8String:va_arg(args, char*)]; + break; + case 'd': + case 'D': + case 'i': + arg = [NSNumber numberWithInt:va_arg(args, int)]; + break; + case 'u': + case 'U': + arg = [NSNumber numberWithUnsignedInt:va_arg(args, unsigned int)]; + break; + case 'h': + i++; + if (i < length && [sql characterAtIndex:i] == 'i') { + // warning: second argument to 'va_arg' is of promotable type 'short'; this va_arg has undefined behavior because arguments will be promoted to 'int' + arg = [NSNumber numberWithShort:(short)(va_arg(args, int))]; + } + else if (i < length && [sql characterAtIndex:i] == 'u') { + // warning: second argument to 'va_arg' is of promotable type 'unsigned short'; this va_arg has undefined behavior because arguments will be promoted to 'int' + arg = [NSNumber numberWithUnsignedShort:(unsigned short)(va_arg(args, uint))]; + } + else { + i--; + } + break; + case 'q': + i++; + if (i < length && [sql characterAtIndex:i] == 'i') { + arg = [NSNumber numberWithLongLong:va_arg(args, long long)]; + } + else if (i < length && [sql characterAtIndex:i] == 'u') { + arg = [NSNumber numberWithUnsignedLongLong:va_arg(args, unsigned long long)]; + } + else { + i--; + } + break; + case 'f': + arg = [NSNumber numberWithDouble:va_arg(args, double)]; + break; + case 'g': + // warning: second argument to 'va_arg' is of promotable type 'float'; this va_arg has undefined behavior because arguments will be promoted to 'double' + arg = [NSNumber numberWithFloat:(float)(va_arg(args, double))]; + break; + case 'l': + i++; + if (i < length) { + unichar next = [sql characterAtIndex:i]; + if (next == 'l') { + i++; + if (i < length && [sql characterAtIndex:i] == 'd') { + //%lld + arg = [NSNumber numberWithLongLong:va_arg(args, long long)]; + } + else if (i < length && [sql characterAtIndex:i] == 'u') { + //%llu + arg = [NSNumber numberWithUnsignedLongLong:va_arg(args, unsigned long long)]; + } + else { + i--; + } + } + else if (next == 'd') { + //%ld + arg = [NSNumber numberWithLong:va_arg(args, long)]; + } + else if (next == 'u') { + //%lu + arg = [NSNumber numberWithUnsignedLong:va_arg(args, unsigned long)]; + } + else { + i--; + } + } + else { + i--; + } + break; + default: + // something else that we can't interpret. just pass it on through like normal + break; + } + } + else if (current == '%') { + // percent sign; skip this character + add = '\0'; + } + + if (arg != nil) { + [cleanedSQL appendString:@"?"]; + [arguments addObject:arg]; + } + else if (add == (unichar)'@' && last == (unichar) '%') { + [cleanedSQL appendFormat:@"NULL"]; + } + else if (add != '\0') { + [cleanedSQL appendFormat:@"%C", add]; + } + last = current; + } +} + +#pragma mark Execute queries + +- (FMResultSet *)executeQuery:(NSString *)sql withParameterDictionary:(NSDictionary *)arguments { + return [self executeQuery:sql withArgumentsInArray:nil orDictionary:arguments orVAList:nil]; +} + +- (FMResultSet *)executeQuery:(NSString *)sql withArgumentsInArray:(NSArray*)arrayArgs orDictionary:(NSDictionary *)dictionaryArgs orVAList:(va_list)args { + + if (![self databaseExists]) { + return 0x00; + } + + if (_isExecutingStatement) { + [self warnInUse]; + return 0x00; + } + + _isExecutingStatement = YES; + + int rc = 0x00; + sqlite3_stmt *pStmt = 0x00; + FMStatement *statement = 0x00; + FMResultSet *rs = 0x00; + + if (_traceExecution && sql) { + NSLog(@"%@ executeQuery: %@", self, sql); + } + + if (_shouldCacheStatements) { + statement = [self cachedStatementForQuery:sql]; + pStmt = statement ? [statement statement] : 0x00; + [statement reset]; + } + + if (!pStmt) { + + rc = sqlite3_prepare_v2(_db, [sql UTF8String], -1, &pStmt, 0); + + if (SQLITE_OK != rc) { + if (_logsErrors) { + NSLog(@"DB Error: %d \"%@\"", [self lastErrorCode], [self lastErrorMessage]); + NSLog(@"DB Query: %@", sql); + NSLog(@"DB Path: %@", _databasePath); + } + + if (_crashOnErrors) { + NSAssert(false, @"DB Error: %d \"%@\"", [self lastErrorCode], [self lastErrorMessage]); + abort(); + } + + sqlite3_finalize(pStmt); + _isExecutingStatement = NO; + return nil; + } + } + + id obj; + int idx = 0; + int queryCount = sqlite3_bind_parameter_count(pStmt); // pointed out by Dominic Yu (thanks!) + + // If dictionaryArgs is passed in, that means we are using sqlite's named parameter support + if (dictionaryArgs) { + + for (NSString *dictionaryKey in [dictionaryArgs allKeys]) { + + // Prefix the key with a colon. + NSString *parameterName = [[NSString alloc] initWithFormat:@":%@", dictionaryKey]; + + if (_traceExecution) { + NSLog(@"%@ = %@", parameterName, [dictionaryArgs objectForKey:dictionaryKey]); + } + + // Get the index for the parameter name. + int namedIdx = sqlite3_bind_parameter_index(pStmt, [parameterName UTF8String]); + + FMDBRelease(parameterName); + + if (namedIdx > 0) { + // Standard binding from here. + [self bindObject:[dictionaryArgs objectForKey:dictionaryKey] toColumn:namedIdx inStatement:pStmt]; + // increment the binding count, so our check below works out + idx++; + } + else { + NSLog(@"Could not find index for %@", dictionaryKey); + } + } + } + else { + + while (idx < queryCount) { + + if (arrayArgs && idx < (int)[arrayArgs count]) { + obj = [arrayArgs objectAtIndex:(NSUInteger)idx]; + } + else if (args) { + obj = va_arg(args, id); + } + else { + //We ran out of arguments + break; + } + + if (_traceExecution) { + if ([obj isKindOfClass:[NSData class]]) { + NSLog(@"data: %ld bytes", (unsigned long)[(NSData*)obj length]); + } + else { + NSLog(@"obj: %@", obj); + } + } + + idx++; + + [self bindObject:obj toColumn:idx inStatement:pStmt]; + } + } + + if (idx != queryCount) { + NSLog(@"Error: the bind count is not correct for the # of variables (executeQuery)"); + sqlite3_finalize(pStmt); + _isExecutingStatement = NO; + return nil; + } + + FMDBRetain(statement); // to balance the release below + + if (!statement) { + statement = [[FMStatement alloc] init]; + [statement setStatement:pStmt]; + + if (_shouldCacheStatements && sql) { + [self setCachedStatement:statement forQuery:sql]; + } + } + + // the statement gets closed in rs's dealloc or [rs close]; + rs = [FMResultSet resultSetWithStatement:statement usingParentDatabase:self]; + [rs setQuery:sql]; + + NSValue *openResultSet = [NSValue valueWithNonretainedObject:rs]; + [_openResultSets addObject:openResultSet]; + + [statement setUseCount:[statement useCount] + 1]; + + FMDBRelease(statement); + + _isExecutingStatement = NO; + + return rs; +} + +- (FMResultSet *)executeQuery:(NSString*)sql, ... { + va_list args; + va_start(args, sql); + + id result = [self executeQuery:sql withArgumentsInArray:nil orDictionary:nil orVAList:args]; + + va_end(args); + return result; +} + +- (FMResultSet *)executeQueryWithFormat:(NSString*)format, ... { + va_list args; + va_start(args, format); + + NSMutableString *sql = [NSMutableString stringWithCapacity:[format length]]; + NSMutableArray *arguments = [NSMutableArray array]; + [self extractSQL:format argumentsList:args intoString:sql arguments:arguments]; + + va_end(args); + + return [self executeQuery:sql withArgumentsInArray:arguments]; +} + +- (FMResultSet *)executeQuery:(NSString *)sql withArgumentsInArray:(NSArray *)arguments { + return [self executeQuery:sql withArgumentsInArray:arguments orDictionary:nil orVAList:nil]; +} + +- (FMResultSet *)executeQuery:(NSString *)sql values:(NSArray *)values error:(NSError * __autoreleasing *)error { + FMResultSet *rs = [self executeQuery:sql withArgumentsInArray:values orDictionary:nil orVAList:nil]; + if (!rs && error) { + *error = [self lastError]; + } + return rs; +} + +- (FMResultSet *)executeQuery:(NSString*)sql withVAList:(va_list)args { + return [self executeQuery:sql withArgumentsInArray:nil orDictionary:nil orVAList:args]; +} + +#pragma mark Execute updates + +- (BOOL)executeUpdate:(NSString*)sql error:(NSError**)outErr withArgumentsInArray:(NSArray*)arrayArgs orDictionary:(NSDictionary *)dictionaryArgs orVAList:(va_list)args { + + if (![self databaseExists]) { + return NO; + } + + if (_isExecutingStatement) { + [self warnInUse]; + return NO; + } + + _isExecutingStatement = YES; + + int rc = 0x00; + sqlite3_stmt *pStmt = 0x00; + FMStatement *cachedStmt = 0x00; + + if (_traceExecution && sql) { + NSLog(@"%@ executeUpdate: %@", self, sql); + } + + if (_shouldCacheStatements) { + cachedStmt = [self cachedStatementForQuery:sql]; + pStmt = cachedStmt ? [cachedStmt statement] : 0x00; + [cachedStmt reset]; + } + + if (!pStmt) { + rc = sqlite3_prepare_v2(_db, [sql UTF8String], -1, &pStmt, 0); + + if (SQLITE_OK != rc) { + if (_logsErrors) { + NSLog(@"DB Error: %d \"%@\"", [self lastErrorCode], [self lastErrorMessage]); + NSLog(@"DB Query: %@", sql); + NSLog(@"DB Path: %@", _databasePath); + } + + if (_crashOnErrors) { + NSAssert(false, @"DB Error: %d \"%@\"", [self lastErrorCode], [self lastErrorMessage]); + abort(); + } + + if (outErr) { + *outErr = [self errorWithMessage:[NSString stringWithUTF8String:sqlite3_errmsg(_db)]]; + } + + sqlite3_finalize(pStmt); + + _isExecutingStatement = NO; + return NO; + } + } + + id obj; + int idx = 0; + int queryCount = sqlite3_bind_parameter_count(pStmt); + + // If dictionaryArgs is passed in, that means we are using sqlite's named parameter support + if (dictionaryArgs) { + + for (NSString *dictionaryKey in [dictionaryArgs allKeys]) { + + // Prefix the key with a colon. + NSString *parameterName = [[NSString alloc] initWithFormat:@":%@", dictionaryKey]; + + if (_traceExecution) { + NSLog(@"%@ = %@", parameterName, [dictionaryArgs objectForKey:dictionaryKey]); + } + // Get the index for the parameter name. + int namedIdx = sqlite3_bind_parameter_index(pStmt, [parameterName UTF8String]); + + FMDBRelease(parameterName); + + if (namedIdx > 0) { + // Standard binding from here. + [self bindObject:[dictionaryArgs objectForKey:dictionaryKey] toColumn:namedIdx inStatement:pStmt]; + + // increment the binding count, so our check below works out + idx++; + } + else { + NSString *message = [NSString stringWithFormat:@"Could not find index for %@", dictionaryKey]; + + if (_logsErrors) { + NSLog(@"%@", message); + } + if (outErr) { + *outErr = [self errorWithMessage:message]; + } + } + } + } + else { + + while (idx < queryCount) { + + if (arrayArgs && idx < (int)[arrayArgs count]) { + obj = [arrayArgs objectAtIndex:(NSUInteger)idx]; + } + else if (args) { + obj = va_arg(args, id); + } + else { + //We ran out of arguments + break; + } + + if (_traceExecution) { + if ([obj isKindOfClass:[NSData class]]) { + NSLog(@"data: %ld bytes", (unsigned long)[(NSData*)obj length]); + } + else { + NSLog(@"obj: %@", obj); + } + } + + idx++; + + [self bindObject:obj toColumn:idx inStatement:pStmt]; + } + } + + + if (idx != queryCount) { + NSString *message = [NSString stringWithFormat:@"Error: the bind count (%d) is not correct for the # of variables in the query (%d) (%@) (executeUpdate)", idx, queryCount, sql]; + if (_logsErrors) { + NSLog(@"%@", message); + } + if (outErr) { + *outErr = [self errorWithMessage:message]; + } + + sqlite3_finalize(pStmt); + _isExecutingStatement = NO; + return NO; + } + + /* Call sqlite3_step() to run the virtual machine. Since the SQL being + ** executed is not a SELECT statement, we assume no data will be returned. + */ + + rc = sqlite3_step(pStmt); + + if (SQLITE_DONE == rc) { + // all is well, let's return. + } + else if (SQLITE_INTERRUPT == rc) { + if (_logsErrors) { + NSLog(@"Error calling sqlite3_step. Query was interrupted (%d: %s) SQLITE_INTERRUPT", rc, sqlite3_errmsg(_db)); + NSLog(@"DB Query: %@", sql); + } + } + else if (rc == SQLITE_ROW) { + NSString *message = [NSString stringWithFormat:@"A executeUpdate is being called with a query string '%@'", sql]; + if (_logsErrors) { + NSLog(@"%@", message); + NSLog(@"DB Query: %@", sql); + } + if (outErr) { + *outErr = [self errorWithMessage:message]; + } + } + else { + if (outErr) { + *outErr = [self errorWithMessage:[NSString stringWithUTF8String:sqlite3_errmsg(_db)]]; + } + + if (SQLITE_ERROR == rc) { + if (_logsErrors) { + NSLog(@"Error calling sqlite3_step (%d: %s) SQLITE_ERROR", rc, sqlite3_errmsg(_db)); + NSLog(@"DB Query: %@", sql); + } + } + else if (SQLITE_MISUSE == rc) { + // uh oh. + if (_logsErrors) { + NSLog(@"Error calling sqlite3_step (%d: %s) SQLITE_MISUSE", rc, sqlite3_errmsg(_db)); + NSLog(@"DB Query: %@", sql); + } + } + else { + // wtf? + if (_logsErrors) { + NSLog(@"Unknown error calling sqlite3_step (%d: %s) eu", rc, sqlite3_errmsg(_db)); + NSLog(@"DB Query: %@", sql); + } + } + } + + if (_shouldCacheStatements && !cachedStmt) { + cachedStmt = [[FMStatement alloc] init]; + + [cachedStmt setStatement:pStmt]; + + [self setCachedStatement:cachedStmt forQuery:sql]; + + FMDBRelease(cachedStmt); + } + + int closeErrorCode; + + if (cachedStmt) { + [cachedStmt setUseCount:[cachedStmt useCount] + 1]; + closeErrorCode = sqlite3_reset(pStmt); + } + else { + /* Finalize the virtual machine. This releases all memory and other + ** resources allocated by the sqlite3_prepare() call above. + */ + closeErrorCode = sqlite3_finalize(pStmt); + } + + if (closeErrorCode != SQLITE_OK) { + if (_logsErrors) { + NSLog(@"Unknown error finalizing or resetting statement (%d: %s)", closeErrorCode, sqlite3_errmsg(_db)); + NSLog(@"DB Query: %@", sql); + } + } + + _isExecutingStatement = NO; + return (rc == SQLITE_DONE || rc == SQLITE_OK); +} + + +- (BOOL)executeUpdate:(NSString*)sql, ... { + va_list args; + va_start(args, sql); + + BOOL result = [self executeUpdate:sql error:nil withArgumentsInArray:nil orDictionary:nil orVAList:args]; + + va_end(args); + return result; +} + +- (BOOL)executeUpdate:(NSString*)sql withArgumentsInArray:(NSArray *)arguments { + return [self executeUpdate:sql error:nil withArgumentsInArray:arguments orDictionary:nil orVAList:nil]; +} + +- (BOOL)executeUpdate:(NSString*)sql values:(NSArray *)values error:(NSError * __autoreleasing *)error { + return [self executeUpdate:sql error:error withArgumentsInArray:values orDictionary:nil orVAList:nil]; +} + +- (BOOL)executeUpdate:(NSString*)sql withParameterDictionary:(NSDictionary *)arguments { + return [self executeUpdate:sql error:nil withArgumentsInArray:nil orDictionary:arguments orVAList:nil]; +} + +- (BOOL)executeUpdate:(NSString*)sql withVAList:(va_list)args { + return [self executeUpdate:sql error:nil withArgumentsInArray:nil orDictionary:nil orVAList:args]; +} + +- (BOOL)executeUpdateWithFormat:(NSString*)format, ... { + va_list args; + va_start(args, format); + + NSMutableString *sql = [NSMutableString stringWithCapacity:[format length]]; + NSMutableArray *arguments = [NSMutableArray array]; + + [self extractSQL:format argumentsList:args intoString:sql arguments:arguments]; + + va_end(args); + + return [self executeUpdate:sql withArgumentsInArray:arguments]; +} + + +int FMDBExecuteBulkSQLCallback(void *theBlockAsVoid, int columns, char **values, char **names); // shhh clang. +int FMDBExecuteBulkSQLCallback(void *theBlockAsVoid, int columns, char **values, char **names) { + + if (!theBlockAsVoid) { + return SQLITE_OK; + } + + int (^execCallbackBlock)(NSDictionary *resultsDictionary) = (__bridge int (^)(NSDictionary *__strong))(theBlockAsVoid); + + NSMutableDictionary *dictionary = [NSMutableDictionary dictionaryWithCapacity:(NSUInteger)columns]; + + for (NSInteger i = 0; i < columns; i++) { + NSString *key = [NSString stringWithUTF8String:names[i]]; + id value = values[i] ? [NSString stringWithUTF8String:values[i]] : [NSNull null]; + [dictionary setObject:value forKey:key]; + } + + return execCallbackBlock(dictionary); +} + +- (BOOL)executeStatements:(NSString *)sql { + return [self executeStatements:sql withResultBlock:nil]; +} + +- (BOOL)executeStatements:(NSString *)sql withResultBlock:(FMDBExecuteStatementsCallbackBlock)block { + + int rc; + char *errmsg = nil; + + rc = sqlite3_exec([self sqliteHandle], [sql UTF8String], block ? FMDBExecuteBulkSQLCallback : nil, (__bridge void *)(block), &errmsg); + + if (errmsg && [self logsErrors]) { + NSLog(@"Error inserting batch: %s", errmsg); + sqlite3_free(errmsg); + } + + return (rc == SQLITE_OK); +} + +- (BOOL)executeUpdate:(NSString*)sql withErrorAndBindings:(NSError**)outErr, ... { + + va_list args; + va_start(args, outErr); + + BOOL result = [self executeUpdate:sql error:outErr withArgumentsInArray:nil orDictionary:nil orVAList:args]; + + va_end(args); + return result; +} + + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-implementations" +- (BOOL)update:(NSString*)sql withErrorAndBindings:(NSError**)outErr, ... { + va_list args; + va_start(args, outErr); + + BOOL result = [self executeUpdate:sql error:outErr withArgumentsInArray:nil orDictionary:nil orVAList:args]; + + va_end(args); + return result; +} + +#pragma clang diagnostic pop + +#pragma mark Transactions + +- (BOOL)rollback { + BOOL b = [self executeUpdate:@"rollback transaction"]; + + if (b) { + _isInTransaction = NO; + } + + return b; +} + +- (BOOL)commit { + BOOL b = [self executeUpdate:@"commit transaction"]; + + if (b) { + _isInTransaction = NO; + } + + return b; +} + +- (BOOL)beginDeferredTransaction { + + BOOL b = [self executeUpdate:@"begin deferred transaction"]; + if (b) { + _isInTransaction = YES; + } + + return b; +} + +- (BOOL)beginTransaction { + + BOOL b = [self executeUpdate:@"begin exclusive transaction"]; + if (b) { + _isInTransaction = YES; + } + + return b; +} + +- (BOOL)inTransaction { + return _isInTransaction; +} + +- (BOOL)interrupt +{ + if (_db) { + sqlite3_interrupt([self sqliteHandle]); + return YES; + } + return NO; +} + +static NSString *FMDBEscapeSavePointName(NSString *savepointName) { + return [savepointName stringByReplacingOccurrencesOfString:@"'" withString:@"''"]; +} + +- (BOOL)startSavePointWithName:(NSString*)name error:(NSError**)outErr { +#if SQLITE_VERSION_NUMBER >= 3007000 + NSParameterAssert(name); + + NSString *sql = [NSString stringWithFormat:@"savepoint '%@';", FMDBEscapeSavePointName(name)]; + + return [self executeUpdate:sql error:outErr withArgumentsInArray:nil orDictionary:nil orVAList:nil]; +#else + NSString *errorMessage = NSLocalizedString(@"Save point functions require SQLite 3.7", nil); + if (self.logsErrors) NSLog(@"%@", errorMessage); + return NO; +#endif +} + +- (BOOL)releaseSavePointWithName:(NSString*)name error:(NSError**)outErr { +#if SQLITE_VERSION_NUMBER >= 3007000 + NSParameterAssert(name); + + NSString *sql = [NSString stringWithFormat:@"release savepoint '%@';", FMDBEscapeSavePointName(name)]; + + return [self executeUpdate:sql error:outErr withArgumentsInArray:nil orDictionary:nil orVAList:nil]; +#else + NSString *errorMessage = NSLocalizedString(@"Save point functions require SQLite 3.7", nil); + if (self.logsErrors) NSLog(@"%@", errorMessage); + return NO; +#endif +} + +- (BOOL)rollbackToSavePointWithName:(NSString*)name error:(NSError**)outErr { +#if SQLITE_VERSION_NUMBER >= 3007000 + NSParameterAssert(name); + + NSString *sql = [NSString stringWithFormat:@"rollback transaction to savepoint '%@';", FMDBEscapeSavePointName(name)]; + + return [self executeUpdate:sql error:outErr withArgumentsInArray:nil orDictionary:nil orVAList:nil]; +#else + NSString *errorMessage = NSLocalizedString(@"Save point functions require SQLite 3.7", nil); + if (self.logsErrors) NSLog(@"%@", errorMessage); + return NO; +#endif +} + +- (NSError*)inSavePoint:(void (^)(BOOL *rollback))block { +#if SQLITE_VERSION_NUMBER >= 3007000 + static unsigned long savePointIdx = 0; + + NSString *name = [NSString stringWithFormat:@"dbSavePoint%ld", savePointIdx++]; + + BOOL shouldRollback = NO; + + NSError *err = 0x00; + + if (![self startSavePointWithName:name error:&err]) { + return err; + } + + if (block) { + block(&shouldRollback); + } + + if (shouldRollback) { + // We need to rollback and release this savepoint to remove it + [self rollbackToSavePointWithName:name error:&err]; + } + [self releaseSavePointWithName:name error:&err]; + + return err; +#else + NSString *errorMessage = NSLocalizedString(@"Save point functions require SQLite 3.7", nil); + if (self.logsErrors) NSLog(@"%@", errorMessage); + return [NSError errorWithDomain:@"FMDatabase" code:0 userInfo:@{NSLocalizedDescriptionKey : errorMessage}]; +#endif +} + + +#pragma mark Cache statements + +- (BOOL)shouldCacheStatements { + return _shouldCacheStatements; +} + +- (void)setShouldCacheStatements:(BOOL)value { + + _shouldCacheStatements = value; + + if (_shouldCacheStatements && !_cachedStatements) { + [self setCachedStatements:[NSMutableDictionary dictionary]]; + } + + if (!_shouldCacheStatements) { + [self setCachedStatements:nil]; + } +} + +#pragma mark Callback function + +void FMDBBlockSQLiteCallBackFunction(sqlite3_context *context, int argc, sqlite3_value **argv); // -Wmissing-prototypes +void FMDBBlockSQLiteCallBackFunction(sqlite3_context *context, int argc, sqlite3_value **argv) { +#if ! __has_feature(objc_arc) + void (^block)(sqlite3_context *context, int argc, sqlite3_value **argv) = (id)sqlite3_user_data(context); +#else + void (^block)(sqlite3_context *context, int argc, sqlite3_value **argv) = (__bridge id)sqlite3_user_data(context); +#endif + if (block) { + @autoreleasepool { + block(context, argc, argv); + } + } +} + +// deprecated because "arguments" parameter is not maximum argument count, but actual argument count. + +- (void)makeFunctionNamed:(NSString *)name maximumArguments:(int)arguments withBlock:(void (^)(void *context, int argc, void **argv))block { + [self makeFunctionNamed:name arguments:arguments block:block]; +} + +- (void)makeFunctionNamed:(NSString *)name arguments:(int)arguments block:(void (^)(void *context, int argc, void **argv))block { + + if (!_openFunctions) { + _openFunctions = [NSMutableSet new]; + } + + id b = FMDBReturnAutoreleased([block copy]); + + [_openFunctions addObject:b]; + + /* I tried adding custom functions to release the block when the connection is destroyed- but they seemed to never be called, so we use _openFunctions to store the values instead. */ +#if ! __has_feature(objc_arc) + sqlite3_create_function([self sqliteHandle], [name UTF8String], arguments, SQLITE_UTF8, (void*)b, &FMDBBlockSQLiteCallBackFunction, 0x00, 0x00); +#else + sqlite3_create_function([self sqliteHandle], [name UTF8String], arguments, SQLITE_UTF8, (__bridge void*)b, &FMDBBlockSQLiteCallBackFunction, 0x00, 0x00); +#endif +} + +- (SqliteValueType)valueType:(void *)value { + return sqlite3_value_type(value); +} + +- (int)valueInt:(void *)value { + return sqlite3_value_int(value); +} + +- (long long)valueLong:(void *)value { + return sqlite3_value_int64(value); +} + +- (double)valueDouble:(void *)value { + return sqlite3_value_double(value); +} + +- (NSData *)valueData:(void *)value { + const void *bytes = sqlite3_value_blob(value); + int length = sqlite3_value_bytes(value); + return bytes ? [NSData dataWithBytes:bytes length:length] : nil; +} + +- (NSString *)valueString:(void *)value { + const char *cString = (const char *)sqlite3_value_text(value); + return cString ? [NSString stringWithUTF8String:cString] : nil; +} + +- (void)resultNullInContext:(void *)context { + sqlite3_result_null(context); +} + +- (void)resultInt:(int) value context:(void *)context { + sqlite3_result_int(context, value); +} + +- (void)resultLong:(long long)value context:(void *)context { + sqlite3_result_int64(context, value); +} + +- (void)resultDouble:(double)value context:(void *)context { + sqlite3_result_double(context, value); +} + +- (void)resultData:(NSData *)data context:(void *)context { + sqlite3_result_blob(context, data.bytes, (int)data.length, SQLITE_TRANSIENT); +} + +- (void)resultString:(NSString *)value context:(void *)context { + sqlite3_result_text(context, [value UTF8String], -1, SQLITE_TRANSIENT); +} + +- (void)resultError:(NSString *)error context:(void *)context { + sqlite3_result_error(context, [error UTF8String], -1); +} + +- (void)resultErrorCode:(int)errorCode context:(void *)context { + sqlite3_result_error_code(context, errorCode); +} + +- (void)resultErrorNoMemoryInContext:(void *)context { + sqlite3_result_error_nomem(context); +} + +- (void)resultErrorTooBigInContext:(void *)context { + sqlite3_result_error_toobig(context); +} + +@end + + + +@implementation FMStatement + +#if ! __has_feature(objc_arc) +- (void)finalize { + [self close]; + [super finalize]; +} +#endif + +- (void)dealloc { + [self close]; + FMDBRelease(_query); +#if ! __has_feature(objc_arc) + [super dealloc]; +#endif +} + +- (void)close { + if (_statement) { + sqlite3_finalize(_statement); + _statement = 0x00; + } + + _inUse = NO; +} + +- (void)reset { + if (_statement) { + sqlite3_reset(_statement); + } + + _inUse = NO; +} + +- (NSString*)description { + return [NSString stringWithFormat:@"%@ %ld hit(s) for query %@", [super description], _useCount, _query]; +} + +@end + diff --git a/lib/ios/AirMaps/fmdb/FMDatabaseAdditions.h b/lib/ios/AirMaps/fmdb/FMDatabaseAdditions.h new file mode 100644 index 000000000..8ee51c721 --- /dev/null +++ b/lib/ios/AirMaps/fmdb/FMDatabaseAdditions.h @@ -0,0 +1,250 @@ +// +// FMDatabaseAdditions.h +// fmdb +// +// Created by August Mueller on 10/30/05. +// Copyright 2005 Flying Meat Inc.. All rights reserved. +// + +#import +#import "FMDatabase.h" + +NS_ASSUME_NONNULL_BEGIN + +/** Category of additions for `` class. + + ### See also + + - `` + */ + +@interface FMDatabase (FMDatabaseAdditions) + +///---------------------------------------- +/// @name Return results of SQL to variable +///---------------------------------------- + +/** Return `int` value for query + + @param query The SQL query to be performed. + @param ... A list of parameters that will be bound to the `?` placeholders in the SQL query. + + @return `int` value. + + @note This is not available from Swift. + */ + +- (int)intForQuery:(NSString*)query, ...; + +/** Return `long` value for query + + @param query The SQL query to be performed. + @param ... A list of parameters that will be bound to the `?` placeholders in the SQL query. + + @return `long` value. + + @note This is not available from Swift. + */ + +- (long)longForQuery:(NSString*)query, ...; + +/** Return `BOOL` value for query + + @param query The SQL query to be performed. + @param ... A list of parameters that will be bound to the `?` placeholders in the SQL query. + + @return `BOOL` value. + + @note This is not available from Swift. + */ + +- (BOOL)boolForQuery:(NSString*)query, ...; + +/** Return `double` value for query + + @param query The SQL query to be performed. + @param ... A list of parameters that will be bound to the `?` placeholders in the SQL query. + + @return `double` value. + + @note This is not available from Swift. + */ + +- (double)doubleForQuery:(NSString*)query, ...; + +/** Return `NSString` value for query + + @param query The SQL query to be performed. + @param ... A list of parameters that will be bound to the `?` placeholders in the SQL query. + + @return `NSString` value. + + @note This is not available from Swift. + */ + +- (NSString * _Nullable)stringForQuery:(NSString*)query, ...; + +/** Return `NSData` value for query + + @param query The SQL query to be performed. + @param ... A list of parameters that will be bound to the `?` placeholders in the SQL query. + + @return `NSData` value. + + @note This is not available from Swift. + */ + +- (NSData * _Nullable)dataForQuery:(NSString*)query, ...; + +/** Return `NSDate` value for query + + @param query The SQL query to be performed. + @param ... A list of parameters that will be bound to the `?` placeholders in the SQL query. + + @return `NSDate` value. + + @note This is not available from Swift. + */ + +- (NSDate * _Nullable)dateForQuery:(NSString*)query, ...; + + +// Notice that there's no dataNoCopyForQuery:. +// That would be a bad idea, because we close out the result set, and then what +// happens to the data that we just didn't copy? Who knows, not I. + + +///-------------------------------- +/// @name Schema related operations +///-------------------------------- + +/** Does table exist in database? + + @param tableName The name of the table being looked for. + + @return `YES` if table found; `NO` if not found. + */ + +- (BOOL)tableExists:(NSString*)tableName; + +/** The schema of the database. + + This will be the schema for the entire database. For each entity, each row of the result set will include the following fields: + + - `type` - The type of entity (e.g. table, index, view, or trigger) + - `name` - The name of the object + - `tbl_name` - The name of the table to which the object references + - `rootpage` - The page number of the root b-tree page for tables and indices + - `sql` - The SQL that created the entity + + @return `FMResultSet` of schema; `nil` on error. + + @see [SQLite File Format](http://www.sqlite.org/fileformat.html) + */ + +- (FMResultSet *)getSchema; + +/** The schema of the database. + + This will be the schema for a particular table as report by SQLite `PRAGMA`, for example: + + PRAGMA table_info('employees') + + This will report: + + - `cid` - The column ID number + - `name` - The name of the column + - `type` - The data type specified for the column + - `notnull` - whether the field is defined as NOT NULL (i.e. values required) + - `dflt_value` - The default value for the column + - `pk` - Whether the field is part of the primary key of the table + + @param tableName The name of the table for whom the schema will be returned. + + @return `FMResultSet` of schema; `nil` on error. + + @see [table_info](http://www.sqlite.org/pragma.html#pragma_table_info) + */ + +- (FMResultSet*)getTableSchema:(NSString*)tableName; + +/** Test to see if particular column exists for particular table in database + + @param columnName The name of the column. + + @param tableName The name of the table. + + @return `YES` if column exists in table in question; `NO` otherwise. + */ + +- (BOOL)columnExists:(NSString*)columnName inTableWithName:(NSString*)tableName; + +/** Test to see if particular column exists for particular table in database + + @param columnName The name of the column. + + @param tableName The name of the table. + + @return `YES` if column exists in table in question; `NO` otherwise. + + @see columnExists:inTableWithName: + + @warning Deprecated - use `` instead. + */ + +- (BOOL)columnExists:(NSString*)tableName columnName:(NSString*)columnName __deprecated_msg("Use columnExists:inTableWithName: instead"); + + +/** Validate SQL statement + + This validates SQL statement by performing `sqlite3_prepare_v2`, but not returning the results, but instead immediately calling `sqlite3_finalize`. + + @param sql The SQL statement being validated. + + @param error This is a pointer to a `NSError` object that will receive the autoreleased `NSError` object if there was any error. If this is `nil`, no `NSError` result will be returned. + + @return `YES` if validation succeeded without incident; `NO` otherwise. + + */ + +- (BOOL)validateSQL:(NSString*)sql error:(NSError * _Nullable *)error; + + +///----------------------------------- +/// @name Application identifier tasks +///----------------------------------- + +/** Retrieve application ID + + @return The `uint32_t` numeric value of the application ID. + + @see setApplicationID: + */ + +@property (nonatomic) uint32_t applicationID; + +#if TARGET_OS_MAC && !TARGET_OS_IPHONE + +/** Retrieve application ID string + + @see setApplicationIDString: + */ + +@property (nonatomic, retain) NSString *applicationIDString; + +#endif + +///----------------------------------- +/// @name user version identifier tasks +///----------------------------------- + +/** Retrieve user version + + @see setUserVersion: + */ + +@property (nonatomic) uint32_t userVersion; + +@end + +NS_ASSUME_NONNULL_END diff --git a/lib/ios/AirMaps/fmdb/FMDatabaseAdditions.m b/lib/ios/AirMaps/fmdb/FMDatabaseAdditions.m new file mode 100644 index 000000000..208e69e52 --- /dev/null +++ b/lib/ios/AirMaps/fmdb/FMDatabaseAdditions.m @@ -0,0 +1,245 @@ +// +// FMDatabaseAdditions.m +// fmdb +// +// Created by August Mueller on 10/30/05. +// Copyright 2005 Flying Meat Inc.. All rights reserved. +// + +#import "FMDatabase.h" +#import "FMDatabaseAdditions.h" +#import "TargetConditionals.h" + +#if FMDB_SQLITE_STANDALONE +#import +#else +#import +#endif + +@interface FMDatabase (PrivateStuff) +- (FMResultSet *)executeQuery:(NSString *)sql withArgumentsInArray:(NSArray * _Nullable)arrayArgs orDictionary:(NSDictionary * _Nullable)dictionaryArgs orVAList:(va_list)args; +@end + +@implementation FMDatabase (FMDatabaseAdditions) + +#define RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(type, sel) \ +va_list args; \ +va_start(args, query); \ +FMResultSet *resultSet = [self executeQuery:query withArgumentsInArray:0x00 orDictionary:0x00 orVAList:args]; \ +va_end(args); \ +if (![resultSet next]) { return (type)0; } \ +type ret = [resultSet sel:0]; \ +[resultSet close]; \ +[resultSet setParentDB:nil]; \ +return ret; + + +- (NSString *)stringForQuery:(NSString*)query, ... { + RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(NSString *, stringForColumnIndex); +} + +- (int)intForQuery:(NSString*)query, ... { + RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(int, intForColumnIndex); +} + +- (long)longForQuery:(NSString*)query, ... { + RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(long, longForColumnIndex); +} + +- (BOOL)boolForQuery:(NSString*)query, ... { + RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(BOOL, boolForColumnIndex); +} + +- (double)doubleForQuery:(NSString*)query, ... { + RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(double, doubleForColumnIndex); +} + +- (NSData*)dataForQuery:(NSString*)query, ... { + RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(NSData *, dataForColumnIndex); +} + +- (NSDate*)dateForQuery:(NSString*)query, ... { + RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(NSDate *, dateForColumnIndex); +} + + +- (BOOL)tableExists:(NSString*)tableName { + + tableName = [tableName lowercaseString]; + + FMResultSet *rs = [self executeQuery:@"select [sql] from sqlite_master where [type] = 'table' and lower(name) = ?", tableName]; + + //if at least one next exists, table exists + BOOL returnBool = [rs next]; + + //close and free object + [rs close]; + + return returnBool; +} + +/* + get table with list of tables: result colums: type[STRING], name[STRING],tbl_name[STRING],rootpage[INTEGER],sql[STRING] + check if table exist in database (patch from OZLB) +*/ +- (FMResultSet*)getSchema { + + //result colums: type[STRING], name[STRING],tbl_name[STRING],rootpage[INTEGER],sql[STRING] + FMResultSet *rs = [self executeQuery:@"SELECT type, name, tbl_name, rootpage, sql FROM (SELECT * FROM sqlite_master UNION ALL SELECT * FROM sqlite_temp_master) WHERE type != 'meta' AND name NOT LIKE 'sqlite_%' ORDER BY tbl_name, type DESC, name"]; + + return rs; +} + +/* + get table schema: result colums: cid[INTEGER], name,type [STRING], notnull[INTEGER], dflt_value[],pk[INTEGER] +*/ +- (FMResultSet*)getTableSchema:(NSString*)tableName { + + //result colums: cid[INTEGER], name,type [STRING], notnull[INTEGER], dflt_value[],pk[INTEGER] + FMResultSet *rs = [self executeQuery:[NSString stringWithFormat: @"pragma table_info('%@')", tableName]]; + + return rs; +} + +- (BOOL)columnExists:(NSString*)columnName inTableWithName:(NSString*)tableName { + + BOOL returnBool = NO; + + tableName = [tableName lowercaseString]; + columnName = [columnName lowercaseString]; + + FMResultSet *rs = [self getTableSchema:tableName]; + + //check if column is present in table schema + while ([rs next]) { + if ([[[rs stringForColumn:@"name"] lowercaseString] isEqualToString:columnName]) { + returnBool = YES; + break; + } + } + + //If this is not done FMDatabase instance stays out of pool + [rs close]; + + return returnBool; +} + + + +- (uint32_t)applicationID { +#if SQLITE_VERSION_NUMBER >= 3007017 + uint32_t r = 0; + + FMResultSet *rs = [self executeQuery:@"pragma application_id"]; + + if ([rs next]) { + r = (uint32_t)[rs longLongIntForColumnIndex:0]; + } + + [rs close]; + + return r; +#else + NSString *errorMessage = NSLocalizedString(@"Application ID functions require SQLite 3.7.17", nil); + if (self.logsErrors) NSLog(@"%@", errorMessage); + return 0; +#endif +} + +- (void)setApplicationID:(uint32_t)appID { +#if SQLITE_VERSION_NUMBER >= 3007017 + NSString *query = [NSString stringWithFormat:@"pragma application_id=%d", appID]; + FMResultSet *rs = [self executeQuery:query]; + [rs next]; + [rs close]; +#else + NSString *errorMessage = NSLocalizedString(@"Application ID functions require SQLite 3.7.17", nil); + if (self.logsErrors) NSLog(@"%@", errorMessage); +#endif +} + + +#if TARGET_OS_MAC && !TARGET_OS_IPHONE + +- (NSString*)applicationIDString { +#if SQLITE_VERSION_NUMBER >= 3007017 + NSString *s = NSFileTypeForHFSTypeCode([self applicationID]); + + assert([s length] == 6); + + s = [s substringWithRange:NSMakeRange(1, 4)]; + + + return s; +#else + NSString *errorMessage = NSLocalizedString(@"Application ID functions require SQLite 3.7.17", nil); + if (self.logsErrors) NSLog(@"%@", errorMessage); + return nil; +#endif +} + +- (void)setApplicationIDString:(NSString*)s { +#if SQLITE_VERSION_NUMBER >= 3007017 + if ([s length] != 4) { + NSLog(@"setApplicationIDString: string passed is not exactly 4 chars long. (was %ld)", [s length]); + } + + [self setApplicationID:NSHFSTypeCodeFromFileType([NSString stringWithFormat:@"'%@'", s])]; +#else + NSString *errorMessage = NSLocalizedString(@"Application ID functions require SQLite 3.7.17", nil); + if (self.logsErrors) NSLog(@"%@", errorMessage); +#endif +} + +#endif + +- (uint32_t)userVersion { + uint32_t r = 0; + + FMResultSet *rs = [self executeQuery:@"pragma user_version"]; + + if ([rs next]) { + r = (uint32_t)[rs longLongIntForColumnIndex:0]; + } + + [rs close]; + return r; +} + +- (void)setUserVersion:(uint32_t)version { + NSString *query = [NSString stringWithFormat:@"pragma user_version = %d", version]; + FMResultSet *rs = [self executeQuery:query]; + [rs next]; + [rs close]; +} + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-implementations" + +- (BOOL)columnExists:(NSString*)tableName columnName:(NSString*)columnName __attribute__ ((deprecated)) { + return [self columnExists:columnName inTableWithName:tableName]; +} + +#pragma clang diagnostic pop + +- (BOOL)validateSQL:(NSString*)sql error:(NSError**)error { + sqlite3_stmt *pStmt = NULL; + BOOL validationSucceeded = YES; + + int rc = sqlite3_prepare_v2([self sqliteHandle], [sql UTF8String], -1, &pStmt, 0); + if (rc != SQLITE_OK) { + validationSucceeded = NO; + if (error) { + *error = [NSError errorWithDomain:NSCocoaErrorDomain + code:[self lastErrorCode] + userInfo:[NSDictionary dictionaryWithObject:[self lastErrorMessage] + forKey:NSLocalizedDescriptionKey]]; + } + } + + sqlite3_finalize(pStmt); + + return validationSucceeded; +} + +@end diff --git a/lib/ios/AirMaps/fmdb/FMDatabasePool.h b/lib/ios/AirMaps/fmdb/FMDatabasePool.h new file mode 100755 index 000000000..3642f59c5 --- /dev/null +++ b/lib/ios/AirMaps/fmdb/FMDatabasePool.h @@ -0,0 +1,258 @@ +// +// FMDatabasePool.h +// fmdb +// +// Created by August Mueller on 6/22/11. +// Copyright 2011 Flying Meat Inc. All rights reserved. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@class FMDatabase; + +/** Pool of `` objects. + + ### See also + + - `` + - `` + + @warning Before using `FMDatabasePool`, please consider using `` instead. + + If you really really really know what you're doing and `FMDatabasePool` is what + you really really need (ie, you're using a read only database), OK you can use + it. But just be careful not to deadlock! + + For an example on deadlocking, search for: + `ONLY_USE_THE_POOL_IF_YOU_ARE_DOING_READS_OTHERWISE_YOULL_DEADLOCK_USE_FMDATABASEQUEUE_INSTEAD` + in the main.m file. + */ + +@interface FMDatabasePool : NSObject + +/** Database path */ + +@property (atomic, copy, nullable) NSString *path; + +/** Delegate object */ + +@property (atomic, assign, nullable) id delegate; + +/** Maximum number of databases to create */ + +@property (atomic, assign) NSUInteger maximumNumberOfDatabasesToCreate; + +/** Open flags */ + +@property (atomic, readonly) int openFlags; + +/** Custom virtual file system name */ + +@property (atomic, copy, nullable) NSString *vfsName; + + +///--------------------- +/// @name Initialization +///--------------------- + +/** Create pool using path. + + @param aPath The file path of the database. + + @return The `FMDatabasePool` object. `nil` on error. + */ + ++ (instancetype)databasePoolWithPath:(NSString * _Nullable)aPath; + +/** Create pool using file URL. + + @param url The file `NSURL` of the database. + + @return The `FMDatabasePool` object. `nil` on error. + */ + ++ (instancetype)databasePoolWithURL:(NSURL * _Nullable)url; + +/** Create pool using path and specified flags + + @param aPath The file path of the database. + @param openFlags Flags passed to the openWithFlags method of the database. + + @return The `FMDatabasePool` object. `nil` on error. + */ + ++ (instancetype)databasePoolWithPath:(NSString * _Nullable)aPath flags:(int)openFlags; + +/** Create pool using file URL and specified flags + + @param url The file `NSURL` of the database. + @param openFlags Flags passed to the openWithFlags method of the database. + + @return The `FMDatabasePool` object. `nil` on error. + */ + ++ (instancetype)databasePoolWithURL:(NSURL * _Nullable)url flags:(int)openFlags; + +/** Create pool using path. + + @param aPath The file path of the database. + + @return The `FMDatabasePool` object. `nil` on error. + */ + +- (instancetype)initWithPath:(NSString * _Nullable)aPath; + +/** Create pool using file URL. + + @param url The file `NSURL of the database. + + @return The `FMDatabasePool` object. `nil` on error. + */ + +- (instancetype)initWithURL:(NSURL * _Nullable)url; + +/** Create pool using path and specified flags. + + @param aPath The file path of the database. + @param openFlags Flags passed to the openWithFlags method of the database + + @return The `FMDatabasePool` object. `nil` on error. + */ + +- (instancetype)initWithPath:(NSString * _Nullable)aPath flags:(int)openFlags; + +/** Create pool using file URL and specified flags. + + @param url The file `NSURL` of the database. + @param openFlags Flags passed to the openWithFlags method of the database + + @return The `FMDatabasePool` object. `nil` on error. + */ + +- (instancetype)initWithURL:(NSURL * _Nullable)url flags:(int)openFlags; + +/** Create pool using path and specified flags. + + @param aPath The file path of the database. + @param openFlags Flags passed to the openWithFlags method of the database + @param vfsName The name of a custom virtual file system + + @return The `FMDatabasePool` object. `nil` on error. + */ + +- (instancetype)initWithPath:(NSString * _Nullable)aPath flags:(int)openFlags vfs:(NSString * _Nullable)vfsName; + +/** Create pool using file URL and specified flags. + + @param url The file `NSURL` of the database. + @param openFlags Flags passed to the openWithFlags method of the database + @param vfsName The name of a custom virtual file system + + @return The `FMDatabasePool` object. `nil` on error. + */ + +- (instancetype)initWithURL:(NSURL * _Nullable)url flags:(int)openFlags vfs:(NSString * _Nullable)vfsName; + +/** Returns the Class of 'FMDatabase' subclass, that will be used to instantiate database object. + + Subclasses can override this method to return specified Class of 'FMDatabase' subclass. + + @return The Class of 'FMDatabase' subclass, that will be used to instantiate database object. + */ + ++ (Class)databaseClass; + +///------------------------------------------------ +/// @name Keeping track of checked in/out databases +///------------------------------------------------ + +/** Number of checked-in databases in pool + */ + +@property (nonatomic, readonly) NSUInteger countOfCheckedInDatabases; + +/** Number of checked-out databases in pool + */ + +@property (nonatomic, readonly) NSUInteger countOfCheckedOutDatabases; + +/** Total number of databases in pool + */ + +@property (nonatomic, readonly) NSUInteger countOfOpenDatabases; + +/** Release all databases in pool */ + +- (void)releaseAllDatabases; + +///------------------------------------------ +/// @name Perform database operations in pool +///------------------------------------------ + +/** Synchronously perform database operations in pool. + + @param block The code to be run on the `FMDatabasePool` pool. + */ + +- (void)inDatabase:(__attribute__((noescape)) void (^)(FMDatabase *db))block; + +/** Synchronously perform database operations in pool using transaction. + + @param block The code to be run on the `FMDatabasePool` pool. + */ + +- (void)inTransaction:(__attribute__((noescape)) void (^)(FMDatabase *db, BOOL *rollback))block; + +/** Synchronously perform database operations in pool using deferred transaction. + + @param block The code to be run on the `FMDatabasePool` pool. + */ + +- (void)inDeferredTransaction:(__attribute__((noescape)) void (^)(FMDatabase *db, BOOL *rollback))block; + +/** Synchronously perform database operations in pool using save point. + + @param block The code to be run on the `FMDatabasePool` pool. + + @return `NSError` object if error; `nil` if successful. + + @warning You can not nest these, since calling it will pull another database out of the pool and you'll get a deadlock. If you need to nest, use `<[FMDatabase startSavePointWithName:error:]>` instead. +*/ + +- (NSError * _Nullable)inSavePoint:(__attribute__((noescape)) void (^)(FMDatabase *db, BOOL *rollback))block; + +@end + + +/** FMDatabasePool delegate category + + This is a category that defines the protocol for the FMDatabasePool delegate + */ + +@interface NSObject (FMDatabasePoolDelegate) + +/** Asks the delegate whether database should be added to the pool. + + @param pool The `FMDatabasePool` object. + @param database The `FMDatabase` object. + + @return `YES` if it should add database to pool; `NO` if not. + + */ + +- (BOOL)databasePool:(FMDatabasePool*)pool shouldAddDatabaseToPool:(FMDatabase*)database; + +/** Tells the delegate that database was added to the pool. + + @param pool The `FMDatabasePool` object. + @param database The `FMDatabase` object. + + */ + +- (void)databasePool:(FMDatabasePool*)pool didAddDatabase:(FMDatabase*)database; + +@end + +NS_ASSUME_NONNULL_END diff --git a/lib/ios/AirMaps/fmdb/FMDatabasePool.m b/lib/ios/AirMaps/fmdb/FMDatabasePool.m new file mode 100755 index 000000000..41a598589 --- /dev/null +++ b/lib/ios/AirMaps/fmdb/FMDatabasePool.m @@ -0,0 +1,316 @@ +// +// FMDatabasePool.m +// fmdb +// +// Created by August Mueller on 6/22/11. +// Copyright 2011 Flying Meat Inc. All rights reserved. +// + +#if FMDB_SQLITE_STANDALONE +#import +#else +#import +#endif + +#import "FMDatabasePool.h" +#import "FMDatabase.h" + +@interface FMDatabasePool () { + dispatch_queue_t _lockQueue; + + NSMutableArray *_databaseInPool; + NSMutableArray *_databaseOutPool; +} + +- (void)pushDatabaseBackInPool:(FMDatabase*)db; +- (FMDatabase*)db; + +@end + + +@implementation FMDatabasePool +@synthesize path=_path; +@synthesize delegate=_delegate; +@synthesize maximumNumberOfDatabasesToCreate=_maximumNumberOfDatabasesToCreate; +@synthesize openFlags=_openFlags; + + ++ (instancetype)databasePoolWithPath:(NSString *)aPath { + return FMDBReturnAutoreleased([[self alloc] initWithPath:aPath]); +} + ++ (instancetype)databasePoolWithURL:(NSURL *)url { + return FMDBReturnAutoreleased([[self alloc] initWithPath:url.path]); +} + ++ (instancetype)databasePoolWithPath:(NSString *)aPath flags:(int)openFlags { + return FMDBReturnAutoreleased([[self alloc] initWithPath:aPath flags:openFlags]); +} + ++ (instancetype)databasePoolWithURL:(NSURL *)url flags:(int)openFlags { + return FMDBReturnAutoreleased([[self alloc] initWithPath:url.path flags:openFlags]); +} + +- (instancetype)initWithURL:(NSURL *)url flags:(int)openFlags vfs:(NSString *)vfsName { + return [self initWithPath:url.path flags:openFlags vfs:vfsName]; +} + +- (instancetype)initWithPath:(NSString*)aPath flags:(int)openFlags vfs:(NSString *)vfsName { + + self = [super init]; + + if (self != nil) { + _path = [aPath copy]; + _lockQueue = dispatch_queue_create([[NSString stringWithFormat:@"fmdb.%@", self] UTF8String], NULL); + _databaseInPool = FMDBReturnRetained([NSMutableArray array]); + _databaseOutPool = FMDBReturnRetained([NSMutableArray array]); + _openFlags = openFlags; + _vfsName = [vfsName copy]; + } + + return self; +} + +- (instancetype)initWithPath:(NSString *)aPath flags:(int)openFlags { + return [self initWithPath:aPath flags:openFlags vfs:nil]; +} + +- (instancetype)initWithURL:(NSURL *)url flags:(int)openFlags { + return [self initWithPath:url.path flags:openFlags vfs:nil]; +} + +- (instancetype)initWithPath:(NSString*)aPath { + // default flags for sqlite3_open + return [self initWithPath:aPath flags:SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE]; +} + +- (instancetype)initWithURL:(NSURL *)url { + return [self initWithPath:url.path]; +} + +- (instancetype)init { + return [self initWithPath:nil]; +} + ++ (Class)databaseClass { + return [FMDatabase class]; +} + +- (void)dealloc { + + _delegate = 0x00; + FMDBRelease(_path); + FMDBRelease(_databaseInPool); + FMDBRelease(_databaseOutPool); + FMDBRelease(_vfsName); + + if (_lockQueue) { + FMDBDispatchQueueRelease(_lockQueue); + _lockQueue = 0x00; + } +#if ! __has_feature(objc_arc) + [super dealloc]; +#endif +} + + +- (void)executeLocked:(void (^)(void))aBlock { + dispatch_sync(_lockQueue, aBlock); +} + +- (void)pushDatabaseBackInPool:(FMDatabase*)db { + + if (!db) { // db can be null if we set an upper bound on the # of databases to create. + return; + } + + [self executeLocked:^() { + + if ([self->_databaseInPool containsObject:db]) { + [[NSException exceptionWithName:@"Database already in pool" reason:@"The FMDatabase being put back into the pool is already present in the pool" userInfo:nil] raise]; + } + + [self->_databaseInPool addObject:db]; + [self->_databaseOutPool removeObject:db]; + + }]; +} + +- (FMDatabase*)db { + + __block FMDatabase *db; + + + [self executeLocked:^() { + db = [self->_databaseInPool lastObject]; + + BOOL shouldNotifyDelegate = NO; + + if (db) { + [self->_databaseOutPool addObject:db]; + [self->_databaseInPool removeLastObject]; + } + else { + + if (self->_maximumNumberOfDatabasesToCreate) { + NSUInteger currentCount = [self->_databaseOutPool count] + [self->_databaseInPool count]; + + if (currentCount >= self->_maximumNumberOfDatabasesToCreate) { + NSLog(@"Maximum number of databases (%ld) has already been reached!", (long)currentCount); + return; + } + } + + db = [[[self class] databaseClass] databaseWithPath:self->_path]; + shouldNotifyDelegate = YES; + } + + //This ensures that the db is opened before returning +#if SQLITE_VERSION_NUMBER >= 3005000 + BOOL success = [db openWithFlags:self->_openFlags vfs:self->_vfsName]; +#else + BOOL success = [db open]; +#endif + if (success) { + if ([self->_delegate respondsToSelector:@selector(databasePool:shouldAddDatabaseToPool:)] && ![self->_delegate databasePool:self shouldAddDatabaseToPool:db]) { + [db close]; + db = 0x00; + } + else { + //It should not get added in the pool twice if lastObject was found + if (![self->_databaseOutPool containsObject:db]) { + [self->_databaseOutPool addObject:db]; + + if (shouldNotifyDelegate && [self->_delegate respondsToSelector:@selector(databasePool:didAddDatabase:)]) { + [self->_delegate databasePool:self didAddDatabase:db]; + } + } + } + } + else { + NSLog(@"Could not open up the database at path %@", self->_path); + db = 0x00; + } + }]; + + return db; +} + +- (NSUInteger)countOfCheckedInDatabases { + + __block NSUInteger count; + + [self executeLocked:^() { + count = [self->_databaseInPool count]; + }]; + + return count; +} + +- (NSUInteger)countOfCheckedOutDatabases { + + __block NSUInteger count; + + [self executeLocked:^() { + count = [self->_databaseOutPool count]; + }]; + + return count; +} + +- (NSUInteger)countOfOpenDatabases { + __block NSUInteger count; + + [self executeLocked:^() { + count = [self->_databaseOutPool count] + [self->_databaseInPool count]; + }]; + + return count; +} + +- (void)releaseAllDatabases { + [self executeLocked:^() { + [self->_databaseOutPool removeAllObjects]; + [self->_databaseInPool removeAllObjects]; + }]; +} + +- (void)inDatabase:(void (^)(FMDatabase *db))block { + + FMDatabase *db = [self db]; + + block(db); + + [self pushDatabaseBackInPool:db]; +} + +- (void)beginTransaction:(BOOL)useDeferred withBlock:(void (^)(FMDatabase *db, BOOL *rollback))block { + + BOOL shouldRollback = NO; + + FMDatabase *db = [self db]; + + if (useDeferred) { + [db beginDeferredTransaction]; + } + else { + [db beginTransaction]; + } + + + block(db, &shouldRollback); + + if (shouldRollback) { + [db rollback]; + } + else { + [db commit]; + } + + [self pushDatabaseBackInPool:db]; +} + +- (void)inDeferredTransaction:(void (^)(FMDatabase *db, BOOL *rollback))block { + [self beginTransaction:YES withBlock:block]; +} + +- (void)inTransaction:(void (^)(FMDatabase *db, BOOL *rollback))block { + [self beginTransaction:NO withBlock:block]; +} + +- (NSError*)inSavePoint:(void (^)(FMDatabase *db, BOOL *rollback))block { +#if SQLITE_VERSION_NUMBER >= 3007000 + static unsigned long savePointIdx = 0; + + NSString *name = [NSString stringWithFormat:@"savePoint%ld", savePointIdx++]; + + BOOL shouldRollback = NO; + + FMDatabase *db = [self db]; + + NSError *err = 0x00; + + if (![db startSavePointWithName:name error:&err]) { + [self pushDatabaseBackInPool:db]; + return err; + } + + block(db, &shouldRollback); + + if (shouldRollback) { + // We need to rollback and release this savepoint to remove it + [db rollbackToSavePointWithName:name error:&err]; + } + [db releaseSavePointWithName:name error:&err]; + + [self pushDatabaseBackInPool:db]; + + return err; +#else + NSString *errorMessage = NSLocalizedString(@"Save point functions require SQLite 3.7", nil); + if (self.logsErrors) NSLog(@"%@", errorMessage); + return [NSError errorWithDomain:@"FMDatabase" code:0 userInfo:@{NSLocalizedDescriptionKey : errorMessage}]; +#endif +} + +@end diff --git a/lib/ios/AirMaps/fmdb/FMDatabaseQueue.h b/lib/ios/AirMaps/fmdb/FMDatabaseQueue.h new file mode 100755 index 000000000..0a8b93816 --- /dev/null +++ b/lib/ios/AirMaps/fmdb/FMDatabaseQueue.h @@ -0,0 +1,235 @@ +// +// FMDatabaseQueue.h +// fmdb +// +// Created by August Mueller on 6/22/11. +// Copyright 2011 Flying Meat Inc. All rights reserved. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@class FMDatabase; + +/** To perform queries and updates on multiple threads, you'll want to use `FMDatabaseQueue`. + + Using a single instance of `` from multiple threads at once is a bad idea. It has always been OK to make a `` object *per thread*. Just don't share a single instance across threads, and definitely not across multiple threads at the same time. + + Instead, use `FMDatabaseQueue`. Here's how to use it: + + First, make your queue. + + FMDatabaseQueue *queue = [FMDatabaseQueue databaseQueueWithPath:aPath]; + + Then use it like so: + + [queue inDatabase:^(FMDatabase *db) { + [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:1]]; + [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:2]]; + [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:3]]; + + FMResultSet *rs = [db executeQuery:@"select * from foo"]; + while ([rs next]) { + //… + } + }]; + + An easy way to wrap things up in a transaction can be done like this: + + [queue inTransaction:^(FMDatabase *db, BOOL *rollback) { + [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:1]]; + [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:2]]; + [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:3]]; + + if (whoopsSomethingWrongHappened) { + *rollback = YES; + return; + } + // etc… + [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:4]]; + }]; + + `FMDatabaseQueue` will run the blocks on a serialized queue (hence the name of the class). So if you call `FMDatabaseQueue`'s methods from multiple threads at the same time, they will be executed in the order they are received. This way queries and updates won't step on each other's toes, and every one is happy. + + ### See also + + - `` + + @warning Do not instantiate a single `` object and use it across multiple threads. Use `FMDatabaseQueue` instead. + + @warning The calls to `FMDatabaseQueue`'s methods are blocking. So even though you are passing along blocks, they will **not** be run on another thread. + + */ + +@interface FMDatabaseQueue : NSObject +/** Path of database */ + +@property (atomic, retain, nullable) NSString *path; + +/** Open flags */ + +@property (atomic, readonly) int openFlags; + +/** Custom virtual file system name */ + +@property (atomic, copy, nullable) NSString *vfsName; + +///---------------------------------------------------- +/// @name Initialization, opening, and closing of queue +///---------------------------------------------------- + +/** Create queue using path. + + @param aPath The file path of the database. + + @return The `FMDatabaseQueue` object. `nil` on error. + */ + ++ (instancetype)databaseQueueWithPath:(NSString * _Nullable)aPath; + +/** Create queue using file URL. + + @param url The file `NSURL` of the database. + + @return The `FMDatabaseQueue` object. `nil` on error. + */ + ++ (instancetype)databaseQueueWithURL:(NSURL * _Nullable)url; + +/** Create queue using path and specified flags. + + @param aPath The file path of the database. + @param openFlags Flags passed to the openWithFlags method of the database. + + @return The `FMDatabaseQueue` object. `nil` on error. + */ ++ (instancetype)databaseQueueWithPath:(NSString * _Nullable)aPath flags:(int)openFlags; + +/** Create queue using file URL and specified flags. + + @param url The file `NSURL` of the database. + @param openFlags Flags passed to the openWithFlags method of the database. + + @return The `FMDatabaseQueue` object. `nil` on error. + */ ++ (instancetype)databaseQueueWithURL:(NSURL * _Nullable)url flags:(int)openFlags; + +/** Create queue using path. + + @param aPath The file path of the database. + + @return The `FMDatabaseQueue` object. `nil` on error. + */ + +- (instancetype)initWithPath:(NSString * _Nullable)aPath; + +/** Create queue using file URL. + + @param url The file `NSURL of the database. + + @return The `FMDatabaseQueue` object. `nil` on error. + */ + +- (instancetype)initWithURL:(NSURL * _Nullable)url; + +/** Create queue using path and specified flags. + + @param aPath The file path of the database. + @param openFlags Flags passed to the openWithFlags method of the database. + + @return The `FMDatabaseQueue` object. `nil` on error. + */ + +- (instancetype)initWithPath:(NSString * _Nullable)aPath flags:(int)openFlags; + +/** Create queue using file URL and specified flags. + + @param url The file path of the database. + @param openFlags Flags passed to the openWithFlags method of the database. + + @return The `FMDatabaseQueue` object. `nil` on error. + */ + +- (instancetype)initWithURL:(NSURL * _Nullable)url flags:(int)openFlags; + +/** Create queue using path and specified flags. + + @param aPath The file path of the database. + @param openFlags Flags passed to the openWithFlags method of the database + @param vfsName The name of a custom virtual file system + + @return The `FMDatabaseQueue` object. `nil` on error. + */ + +- (instancetype)initWithPath:(NSString * _Nullable)aPath flags:(int)openFlags vfs:(NSString * _Nullable)vfsName; + +/** Create queue using file URL and specified flags. + + @param url The file `NSURL of the database. + @param openFlags Flags passed to the openWithFlags method of the database + @param vfsName The name of a custom virtual file system + + @return The `FMDatabaseQueue` object. `nil` on error. + */ + +- (instancetype)initWithURL:(NSURL * _Nullable)url flags:(int)openFlags vfs:(NSString * _Nullable)vfsName; + +/** Returns the Class of 'FMDatabase' subclass, that will be used to instantiate database object. + + Subclasses can override this method to return specified Class of 'FMDatabase' subclass. + + @return The Class of 'FMDatabase' subclass, that will be used to instantiate database object. + */ + ++ (Class)databaseClass; + +/** Close database used by queue. */ + +- (void)close; + +/** Interupt pending database operation. */ + +- (void)interrupt; + +///----------------------------------------------- +/// @name Dispatching database operations to queue +///----------------------------------------------- + +/** Synchronously perform database operations on queue. + + @param block The code to be run on the queue of `FMDatabaseQueue` + */ + +- (void)inDatabase:(__attribute__((noescape)) void (^)(FMDatabase *db))block; + +/** Synchronously perform database operations on queue, using transactions. + + @param block The code to be run on the queue of `FMDatabaseQueue` + */ + +- (void)inTransaction:(__attribute__((noescape)) void (^)(FMDatabase *db, BOOL *rollback))block; + +/** Synchronously perform database operations on queue, using deferred transactions. + + @param block The code to be run on the queue of `FMDatabaseQueue` + */ + +- (void)inDeferredTransaction:(__attribute__((noescape)) void (^)(FMDatabase *db, BOOL *rollback))block; + +///----------------------------------------------- +/// @name Dispatching database operations to queue +///----------------------------------------------- + +/** Synchronously perform database operations using save point. + + @param block The code to be run on the queue of `FMDatabaseQueue` + */ + +// NOTE: you can not nest these, since calling it will pull another database out of the pool and you'll get a deadlock. +// If you need to nest, use FMDatabase's startSavePointWithName:error: instead. +- (NSError * _Nullable)inSavePoint:(__attribute__((noescape)) void (^)(FMDatabase *db, BOOL *rollback))block; + +@end + +NS_ASSUME_NONNULL_END diff --git a/lib/ios/AirMaps/fmdb/FMDatabaseQueue.m b/lib/ios/AirMaps/fmdb/FMDatabaseQueue.m new file mode 100755 index 000000000..f3f30cf26 --- /dev/null +++ b/lib/ios/AirMaps/fmdb/FMDatabaseQueue.m @@ -0,0 +1,270 @@ +// +// FMDatabaseQueue.m +// fmdb +// +// Created by August Mueller on 6/22/11. +// Copyright 2011 Flying Meat Inc. All rights reserved. +// + +#import "FMDatabaseQueue.h" +#import "FMDatabase.h" + +#if FMDB_SQLITE_STANDALONE +#import +#else +#import +#endif + +/* + + Note: we call [self retain]; before using dispatch_sync, just incase + FMDatabaseQueue is released on another thread and we're in the middle of doing + something in dispatch_sync + + */ + +/* + * A key used to associate the FMDatabaseQueue object with the dispatch_queue_t it uses. + * This in turn is used for deadlock detection by seeing if inDatabase: is called on + * the queue's dispatch queue, which should not happen and causes a deadlock. + */ +static const void * const kDispatchQueueSpecificKey = &kDispatchQueueSpecificKey; + +@interface FMDatabaseQueue () { + dispatch_queue_t _queue; + FMDatabase *_db; +} +@end + +@implementation FMDatabaseQueue + ++ (instancetype)databaseQueueWithPath:(NSString *)aPath { + FMDatabaseQueue *q = [[self alloc] initWithPath:aPath]; + + FMDBAutorelease(q); + + return q; +} + ++ (instancetype)databaseQueueWithURL:(NSURL *)url { + return [self databaseQueueWithPath:url.path]; +} + ++ (instancetype)databaseQueueWithPath:(NSString *)aPath flags:(int)openFlags { + FMDatabaseQueue *q = [[self alloc] initWithPath:aPath flags:openFlags]; + + FMDBAutorelease(q); + + return q; +} + ++ (instancetype)databaseQueueWithURL:(NSURL *)url flags:(int)openFlags { + return [self databaseQueueWithPath:url.path flags:openFlags]; +} + ++ (Class)databaseClass { + return [FMDatabase class]; +} + +- (instancetype)initWithURL:(NSURL *)url flags:(int)openFlags vfs:(NSString *)vfsName { + return [self initWithPath:url.path flags:openFlags vfs:vfsName]; +} + +- (instancetype)initWithPath:(NSString*)aPath flags:(int)openFlags vfs:(NSString *)vfsName { + self = [super init]; + + if (self != nil) { + + _db = [[[self class] databaseClass] databaseWithPath:aPath]; + FMDBRetain(_db); + +#if SQLITE_VERSION_NUMBER >= 3005000 + BOOL success = [_db openWithFlags:openFlags vfs:vfsName]; +#else + BOOL success = [_db open]; +#endif + if (!success) { + NSLog(@"Could not create database queue for path %@", aPath); + FMDBRelease(self); + return 0x00; + } + + _path = FMDBReturnRetained(aPath); + + _queue = dispatch_queue_create([[NSString stringWithFormat:@"fmdb.%@", self] UTF8String], NULL); + dispatch_queue_set_specific(_queue, kDispatchQueueSpecificKey, (__bridge void *)self, NULL); + _openFlags = openFlags; + _vfsName = [vfsName copy]; + } + + return self; +} + +- (instancetype)initWithPath:(NSString *)aPath flags:(int)openFlags { + return [self initWithPath:aPath flags:openFlags vfs:nil]; +} + +- (instancetype)initWithURL:(NSURL *)url flags:(int)openFlags { + return [self initWithPath:url.path flags:openFlags vfs:nil]; +} + +- (instancetype)initWithURL:(NSURL *)url { + return [self initWithPath:url.path]; +} + +- (instancetype)initWithPath:(NSString *)aPath { + // default flags for sqlite3_open + return [self initWithPath:aPath flags:SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE vfs:nil]; +} + +- (instancetype)init { + return [self initWithPath:nil]; +} + + +- (void)dealloc { + FMDBRelease(_db); + FMDBRelease(_path); + FMDBRelease(_vfsName); + + if (_queue) { + FMDBDispatchQueueRelease(_queue); + _queue = 0x00; + } +#if ! __has_feature(objc_arc) + [super dealloc]; +#endif +} + +- (void)close { + FMDBRetain(self); + dispatch_sync(_queue, ^() { + [self->_db close]; + FMDBRelease(_db); + self->_db = 0x00; + }); + FMDBRelease(self); +} + +- (void)interrupt { + [[self database] interrupt]; +} + +- (FMDatabase*)database { + if (!_db) { + _db = FMDBReturnRetained([[[self class] databaseClass] databaseWithPath:_path]); + +#if SQLITE_VERSION_NUMBER >= 3005000 + BOOL success = [_db openWithFlags:_openFlags vfs:_vfsName]; +#else + BOOL success = [_db open]; +#endif + if (!success) { + NSLog(@"FMDatabaseQueue could not reopen database for path %@", _path); + FMDBRelease(_db); + _db = 0x00; + return 0x00; + } + } + + return _db; +} + +- (void)inDatabase:(void (^)(FMDatabase *db))block { +#ifndef NDEBUG + /* Get the currently executing queue (which should probably be nil, but in theory could be another DB queue + * and then check it against self to make sure we're not about to deadlock. */ + FMDatabaseQueue *currentSyncQueue = (__bridge id)dispatch_get_specific(kDispatchQueueSpecificKey); + assert(currentSyncQueue != self && "inDatabase: was called reentrantly on the same queue, which would lead to a deadlock"); +#endif + + FMDBRetain(self); + + dispatch_sync(_queue, ^() { + + FMDatabase *db = [self database]; + block(db); + + if ([db hasOpenResultSets]) { + NSLog(@"Warning: there is at least one open result set around after performing [FMDatabaseQueue inDatabase:]"); + +#if defined(DEBUG) && DEBUG + NSSet *openSetCopy = FMDBReturnAutoreleased([[db valueForKey:@"_openResultSets"] copy]); + for (NSValue *rsInWrappedInATastyValueMeal in openSetCopy) { + FMResultSet *rs = (FMResultSet *)[rsInWrappedInATastyValueMeal pointerValue]; + NSLog(@"query: '%@'", [rs query]); + } +#endif + } + }); + + FMDBRelease(self); +} + +- (void)beginTransaction:(BOOL)useDeferred withBlock:(void (^)(FMDatabase *db, BOOL *rollback))block { + FMDBRetain(self); + dispatch_sync(_queue, ^() { + + BOOL shouldRollback = NO; + + if (useDeferred) { + [[self database] beginDeferredTransaction]; + } + else { + [[self database] beginTransaction]; + } + + block([self database], &shouldRollback); + + if (shouldRollback) { + [[self database] rollback]; + } + else { + [[self database] commit]; + } + }); + + FMDBRelease(self); +} + +- (void)inDeferredTransaction:(void (^)(FMDatabase *db, BOOL *rollback))block { + [self beginTransaction:YES withBlock:block]; +} + +- (void)inTransaction:(void (^)(FMDatabase *db, BOOL *rollback))block { + [self beginTransaction:NO withBlock:block]; +} + +- (NSError*)inSavePoint:(void (^)(FMDatabase *db, BOOL *rollback))block { +#if SQLITE_VERSION_NUMBER >= 3007000 + static unsigned long savePointIdx = 0; + __block NSError *err = 0x00; + FMDBRetain(self); + dispatch_sync(_queue, ^() { + + NSString *name = [NSString stringWithFormat:@"savePoint%ld", savePointIdx++]; + + BOOL shouldRollback = NO; + + if ([[self database] startSavePointWithName:name error:&err]) { + + block([self database], &shouldRollback); + + if (shouldRollback) { + // We need to rollback and release this savepoint to remove it + [[self database] rollbackToSavePointWithName:name error:&err]; + } + [[self database] releaseSavePointWithName:name error:&err]; + + } + }); + FMDBRelease(self); + return err; +#else + NSString *errorMessage = NSLocalizedString(@"Save point functions require SQLite 3.7", nil); + if (self.logsErrors) NSLog(@"%@", errorMessage); + return [NSError errorWithDomain:@"FMDatabase" code:0 userInfo:@{NSLocalizedDescriptionKey : errorMessage}]; +#endif +} + +@end diff --git a/lib/ios/AirMaps/fmdb/FMResultSet.h b/lib/ios/AirMaps/fmdb/FMResultSet.h new file mode 100644 index 000000000..805729109 --- /dev/null +++ b/lib/ios/AirMaps/fmdb/FMResultSet.h @@ -0,0 +1,467 @@ +#import + +NS_ASSUME_NONNULL_BEGIN + +#ifndef __has_feature // Optional. +#define __has_feature(x) 0 // Compatibility with non-clang compilers. +#endif + +#ifndef NS_RETURNS_NOT_RETAINED +#if __has_feature(attribute_ns_returns_not_retained) +#define NS_RETURNS_NOT_RETAINED __attribute__((ns_returns_not_retained)) +#else +#define NS_RETURNS_NOT_RETAINED +#endif +#endif + +@class FMDatabase; +@class FMStatement; + +/** Represents the results of executing a query on an ``. + + ### See also + + - `` + */ + +@interface FMResultSet : NSObject + +@property (nonatomic, retain, nullable) FMDatabase *parentDB; + +///----------------- +/// @name Properties +///----------------- + +/** Executed query */ + +@property (atomic, retain, nullable) NSString *query; + +/** `NSMutableDictionary` mapping column names to numeric index */ + +@property (readonly) NSMutableDictionary *columnNameToIndexMap; + +/** `FMStatement` used by result set. */ + +@property (atomic, retain, nullable) FMStatement *statement; + +///------------------------------------ +/// @name Creating and closing database +///------------------------------------ + +/** Create result set from `` + + @param statement A `` to be performed + + @param aDB A `` to be used + + @return A `FMResultSet` on success; `nil` on failure + */ + ++ (instancetype)resultSetWithStatement:(FMStatement *)statement usingParentDatabase:(FMDatabase*)aDB; + +/** Close result set */ + +- (void)close; + +///--------------------------------------- +/// @name Iterating through the result set +///--------------------------------------- + +/** Retrieve next row for result set. + + You must always invoke `next` or `nextWithError` before attempting to access the values returned in a query, even if you're only expecting one. + + @return `YES` if row successfully retrieved; `NO` if end of result set reached + + @see hasAnotherRow + */ + +- (BOOL)next; + +/** Retrieve next row for result set. + + You must always invoke `next` or `nextWithError` before attempting to access the values returned in a query, even if you're only expecting one. + + @param outErr A 'NSError' object to receive any error object (if any). + + @return 'YES' if row successfully retrieved; 'NO' if end of result set reached + + @see hasAnotherRow + */ + +- (BOOL)nextWithError:(NSError * _Nullable *)outErr; + +/** Did the last call to `` succeed in retrieving another row? + + @return `YES` if the last call to `` succeeded in retrieving another record; `NO` if not. + + @see next + + @warning The `hasAnotherRow` method must follow a call to ``. If the previous database interaction was something other than a call to `next`, then this method may return `NO`, whether there is another row of data or not. + */ + +- (BOOL)hasAnotherRow; + +///--------------------------------------------- +/// @name Retrieving information from result set +///--------------------------------------------- + +/** How many columns in result set + + @return Integer value of the number of columns. + */ + +@property (nonatomic, readonly) int columnCount; + +/** Column index for column name + + @param columnName `NSString` value of the name of the column. + + @return Zero-based index for column. + */ + +- (int)columnIndexForName:(NSString*)columnName; + +/** Column name for column index + + @param columnIdx Zero-based index for column. + + @return columnName `NSString` value of the name of the column. + */ + +- (NSString * _Nullable)columnNameForIndex:(int)columnIdx; + +/** Result set integer value for column. + + @param columnName `NSString` value of the name of the column. + + @return `int` value of the result set's column. + */ + +- (int)intForColumn:(NSString*)columnName; + +/** Result set integer value for column. + + @param columnIdx Zero-based index for column. + + @return `int` value of the result set's column. + */ + +- (int)intForColumnIndex:(int)columnIdx; + +/** Result set `long` value for column. + + @param columnName `NSString` value of the name of the column. + + @return `long` value of the result set's column. + */ + +- (long)longForColumn:(NSString*)columnName; + +/** Result set long value for column. + + @param columnIdx Zero-based index for column. + + @return `long` value of the result set's column. + */ + +- (long)longForColumnIndex:(int)columnIdx; + +/** Result set `long long int` value for column. + + @param columnName `NSString` value of the name of the column. + + @return `long long int` value of the result set's column. + */ + +- (long long int)longLongIntForColumn:(NSString*)columnName; + +/** Result set `long long int` value for column. + + @param columnIdx Zero-based index for column. + + @return `long long int` value of the result set's column. + */ + +- (long long int)longLongIntForColumnIndex:(int)columnIdx; + +/** Result set `unsigned long long int` value for column. + + @param columnName `NSString` value of the name of the column. + + @return `unsigned long long int` value of the result set's column. + */ + +- (unsigned long long int)unsignedLongLongIntForColumn:(NSString*)columnName; + +/** Result set `unsigned long long int` value for column. + + @param columnIdx Zero-based index for column. + + @return `unsigned long long int` value of the result set's column. + */ + +- (unsigned long long int)unsignedLongLongIntForColumnIndex:(int)columnIdx; + +/** Result set `BOOL` value for column. + + @param columnName `NSString` value of the name of the column. + + @return `BOOL` value of the result set's column. + */ + +- (BOOL)boolForColumn:(NSString*)columnName; + +/** Result set `BOOL` value for column. + + @param columnIdx Zero-based index for column. + + @return `BOOL` value of the result set's column. + */ + +- (BOOL)boolForColumnIndex:(int)columnIdx; + +/** Result set `double` value for column. + + @param columnName `NSString` value of the name of the column. + + @return `double` value of the result set's column. + + */ + +- (double)doubleForColumn:(NSString*)columnName; + +/** Result set `double` value for column. + + @param columnIdx Zero-based index for column. + + @return `double` value of the result set's column. + + */ + +- (double)doubleForColumnIndex:(int)columnIdx; + +/** Result set `NSString` value for column. + + @param columnName `NSString` value of the name of the column. + + @return String value of the result set's column. + + */ + +- (NSString * _Nullable)stringForColumn:(NSString*)columnName; + +/** Result set `NSString` value for column. + + @param columnIdx Zero-based index for column. + + @return String value of the result set's column. + */ + +- (NSString * _Nullable)stringForColumnIndex:(int)columnIdx; + +/** Result set `NSDate` value for column. + + @param columnName `NSString` value of the name of the column. + + @return Date value of the result set's column. + */ + +- (NSDate * _Nullable)dateForColumn:(NSString*)columnName; + +/** Result set `NSDate` value for column. + + @param columnIdx Zero-based index for column. + + @return Date value of the result set's column. + + */ + +- (NSDate * _Nullable)dateForColumnIndex:(int)columnIdx; + +/** Result set `NSData` value for column. + + This is useful when storing binary data in table (such as image or the like). + + @param columnName `NSString` value of the name of the column. + + @return Data value of the result set's column. + + */ + +- (NSData * _Nullable)dataForColumn:(NSString*)columnName; + +/** Result set `NSData` value for column. + + @param columnIdx Zero-based index for column. + + @return Data value of the result set's column. + */ + +- (NSData * _Nullable)dataForColumnIndex:(int)columnIdx; + +/** Result set `(const unsigned char *)` value for column. + + @param columnName `NSString` value of the name of the column. + + @return `(const unsigned char *)` value of the result set's column. + */ + +- (const unsigned char * _Nullable)UTF8StringForColumn:(NSString*)columnName; + +- (const unsigned char * _Nullable)UTF8StringForColumnName:(NSString*)columnName __deprecated_msg("Use UTF8StringForColumn instead"); + +/** Result set `(const unsigned char *)` value for column. + + @param columnIdx Zero-based index for column. + + @return `(const unsigned char *)` value of the result set's column. + */ + +- (const unsigned char * _Nullable)UTF8StringForColumnIndex:(int)columnIdx; + +/** Result set object for column. + + @param columnName Name of the column. + + @return Either `NSNumber`, `NSString`, `NSData`, or `NSNull`. If the column was `NULL`, this returns `[NSNull null]` object. + + @see objectForKeyedSubscript: + */ + +- (id _Nullable)objectForColumn:(NSString*)columnName; + +- (id _Nullable)objectForColumnName:(NSString*)columnName __deprecated_msg("Use objectForColumn instead"); + +/** Result set object for column. + + @param columnIdx Zero-based index for column. + + @return Either `NSNumber`, `NSString`, `NSData`, or `NSNull`. If the column was `NULL`, this returns `[NSNull null]` object. + + @see objectAtIndexedSubscript: + */ + +- (id _Nullable)objectForColumnIndex:(int)columnIdx; + +/** Result set object for column. + + This method allows the use of the "boxed" syntax supported in Modern Objective-C. For example, by defining this method, the following syntax is now supported: + + id result = rs[@"employee_name"]; + + This simplified syntax is equivalent to calling: + + id result = [rs objectForKeyedSubscript:@"employee_name"]; + + which is, it turns out, equivalent to calling: + + id result = [rs objectForColumnName:@"employee_name"]; + + @param columnName `NSString` value of the name of the column. + + @return Either `NSNumber`, `NSString`, `NSData`, or `NSNull`. If the column was `NULL`, this returns `[NSNull null]` object. + */ + +- (id _Nullable)objectForKeyedSubscript:(NSString *)columnName; + +/** Result set object for column. + + This method allows the use of the "boxed" syntax supported in Modern Objective-C. For example, by defining this method, the following syntax is now supported: + + id result = rs[0]; + + This simplified syntax is equivalent to calling: + + id result = [rs objectForKeyedSubscript:0]; + + which is, it turns out, equivalent to calling: + + id result = [rs objectForColumnName:0]; + + @param columnIdx Zero-based index for column. + + @return Either `NSNumber`, `NSString`, `NSData`, or `NSNull`. If the column was `NULL`, this returns `[NSNull null]` object. + */ + +- (id _Nullable)objectAtIndexedSubscript:(int)columnIdx; + +/** Result set `NSData` value for column. + + @param columnName `NSString` value of the name of the column. + + @return Data value of the result set's column. + + @warning If you are going to use this data after you iterate over the next row, or after you close the +result set, make sure to make a copy of the data first (or just use ``/``) +If you don't, you're going to be in a world of hurt when you try and use the data. + + */ + +- (NSData * _Nullable)dataNoCopyForColumn:(NSString *)columnName NS_RETURNS_NOT_RETAINED; + +/** Result set `NSData` value for column. + + @param columnIdx Zero-based index for column. + + @return Data value of the result set's column. + + @warning If you are going to use this data after you iterate over the next row, or after you close the + result set, make sure to make a copy of the data first (or just use ``/``) + If you don't, you're going to be in a world of hurt when you try and use the data. + + */ + +- (NSData * _Nullable)dataNoCopyForColumnIndex:(int)columnIdx NS_RETURNS_NOT_RETAINED; + +/** Is the column `NULL`? + + @param columnIdx Zero-based index for column. + + @return `YES` if column is `NULL`; `NO` if not `NULL`. + */ + +- (BOOL)columnIndexIsNull:(int)columnIdx; + +/** Is the column `NULL`? + + @param columnName `NSString` value of the name of the column. + + @return `YES` if column is `NULL`; `NO` if not `NULL`. + */ + +- (BOOL)columnIsNull:(NSString*)columnName; + + +/** Returns a dictionary of the row results mapped to case sensitive keys of the column names. + + @warning The keys to the dictionary are case sensitive of the column names. + */ + +@property (nonatomic, readonly, nullable) NSDictionary *resultDictionary; + +/** Returns a dictionary of the row results + + @see resultDictionary + + @warning **Deprecated**: Please use `` instead. Also, beware that `` is case sensitive! + */ + +- (NSDictionary * _Nullable)resultDict __deprecated_msg("Use resultDictionary instead"); + +///----------------------------- +/// @name Key value coding magic +///----------------------------- + +/** Performs `setValue` to yield support for key value observing. + + @param object The object for which the values will be set. This is the key-value-coding compliant object that you might, for example, observe. + + */ + +- (void)kvcMagic:(id)object; + + +@end + +NS_ASSUME_NONNULL_END diff --git a/lib/ios/AirMaps/fmdb/FMResultSet.m b/lib/ios/AirMaps/fmdb/FMResultSet.m new file mode 100644 index 000000000..2231e4761 --- /dev/null +++ b/lib/ios/AirMaps/fmdb/FMResultSet.m @@ -0,0 +1,432 @@ +#import "FMResultSet.h" +#import "FMDatabase.h" +#import "unistd.h" + +#if FMDB_SQLITE_STANDALONE +#import +#else +#import +#endif + +@interface FMDatabase () +- (void)resultSetDidClose:(FMResultSet *)resultSet; +@end + +@interface FMResultSet () { + NSMutableDictionary *_columnNameToIndexMap; +} +@end + +@implementation FMResultSet + ++ (instancetype)resultSetWithStatement:(FMStatement *)statement usingParentDatabase:(FMDatabase*)aDB { + + FMResultSet *rs = [[FMResultSet alloc] init]; + + [rs setStatement:statement]; + [rs setParentDB:aDB]; + + NSParameterAssert(![statement inUse]); + [statement setInUse:YES]; // weak reference + + return FMDBReturnAutoreleased(rs); +} + +#if ! __has_feature(objc_arc) +- (void)finalize { + [self close]; + [super finalize]; +} +#endif + +- (void)dealloc { + [self close]; + + FMDBRelease(_query); + _query = nil; + + FMDBRelease(_columnNameToIndexMap); + _columnNameToIndexMap = nil; + +#if ! __has_feature(objc_arc) + [super dealloc]; +#endif +} + +- (void)close { + [_statement reset]; + FMDBRelease(_statement); + _statement = nil; + + // we don't need this anymore... (i think) + //[_parentDB setInUse:NO]; + [_parentDB resultSetDidClose:self]; + _parentDB = nil; +} + +- (int)columnCount { + return sqlite3_column_count([_statement statement]); +} + +- (NSMutableDictionary *)columnNameToIndexMap { + if (!_columnNameToIndexMap) { + int columnCount = sqlite3_column_count([_statement statement]); + _columnNameToIndexMap = [[NSMutableDictionary alloc] initWithCapacity:(NSUInteger)columnCount]; + int columnIdx = 0; + for (columnIdx = 0; columnIdx < columnCount; columnIdx++) { + [_columnNameToIndexMap setObject:[NSNumber numberWithInt:columnIdx] + forKey:[[NSString stringWithUTF8String:sqlite3_column_name([_statement statement], columnIdx)] lowercaseString]]; + } + } + return _columnNameToIndexMap; +} + +- (void)kvcMagic:(id)object { + + int columnCount = sqlite3_column_count([_statement statement]); + + int columnIdx = 0; + for (columnIdx = 0; columnIdx < columnCount; columnIdx++) { + + const char *c = (const char *)sqlite3_column_text([_statement statement], columnIdx); + + // check for a null row + if (c) { + NSString *s = [NSString stringWithUTF8String:c]; + + [object setValue:s forKey:[NSString stringWithUTF8String:sqlite3_column_name([_statement statement], columnIdx)]]; + } + } +} + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-implementations" + +- (NSDictionary *)resultDict { + + NSUInteger num_cols = (NSUInteger)sqlite3_data_count([_statement statement]); + + if (num_cols > 0) { + NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithCapacity:num_cols]; + + NSEnumerator *columnNames = [[self columnNameToIndexMap] keyEnumerator]; + NSString *columnName = nil; + while ((columnName = [columnNames nextObject])) { + id objectValue = [self objectForColumnName:columnName]; + [dict setObject:objectValue forKey:columnName]; + } + + return FMDBReturnAutoreleased([dict copy]); + } + else { + NSLog(@"Warning: There seem to be no columns in this set."); + } + + return nil; +} + +#pragma clang diagnostic pop + +- (NSDictionary*)resultDictionary { + + NSUInteger num_cols = (NSUInteger)sqlite3_data_count([_statement statement]); + + if (num_cols > 0) { + NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithCapacity:num_cols]; + + int columnCount = sqlite3_column_count([_statement statement]); + + int columnIdx = 0; + for (columnIdx = 0; columnIdx < columnCount; columnIdx++) { + + NSString *columnName = [NSString stringWithUTF8String:sqlite3_column_name([_statement statement], columnIdx)]; + id objectValue = [self objectForColumnIndex:columnIdx]; + [dict setObject:objectValue forKey:columnName]; + } + + return dict; + } + else { + NSLog(@"Warning: There seem to be no columns in this set."); + } + + return nil; +} + + + + +- (BOOL)next { + return [self nextWithError:nil]; +} + +- (BOOL)nextWithError:(NSError **)outErr { + + int rc = sqlite3_step([_statement statement]); + + if (SQLITE_BUSY == rc || SQLITE_LOCKED == rc) { + NSLog(@"%s:%d Database busy (%@)", __FUNCTION__, __LINE__, [_parentDB databasePath]); + NSLog(@"Database busy"); + if (outErr) { + *outErr = [_parentDB lastError]; + } + } + else if (SQLITE_DONE == rc || SQLITE_ROW == rc) { + // all is well, let's return. + } + else if (SQLITE_ERROR == rc) { + NSLog(@"Error calling sqlite3_step (%d: %s) rs", rc, sqlite3_errmsg([_parentDB sqliteHandle])); + if (outErr) { + *outErr = [_parentDB lastError]; + } + } + else if (SQLITE_MISUSE == rc) { + // uh oh. + NSLog(@"Error calling sqlite3_step (%d: %s) rs", rc, sqlite3_errmsg([_parentDB sqliteHandle])); + if (outErr) { + if (_parentDB) { + *outErr = [_parentDB lastError]; + } + else { + // If 'next' or 'nextWithError' is called after the result set is closed, + // we need to return the appropriate error. + NSDictionary* errorMessage = [NSDictionary dictionaryWithObject:@"parentDB does not exist" forKey:NSLocalizedDescriptionKey]; + *outErr = [NSError errorWithDomain:@"FMDatabase" code:SQLITE_MISUSE userInfo:errorMessage]; + } + + } + } + else { + // wtf? + NSLog(@"Unknown error calling sqlite3_step (%d: %s) rs", rc, sqlite3_errmsg([_parentDB sqliteHandle])); + if (outErr) { + *outErr = [_parentDB lastError]; + } + } + + + if (rc != SQLITE_ROW) { + [self close]; + } + + return (rc == SQLITE_ROW); +} + +- (BOOL)hasAnotherRow { + return sqlite3_errcode([_parentDB sqliteHandle]) == SQLITE_ROW; +} + +- (int)columnIndexForName:(NSString*)columnName { + columnName = [columnName lowercaseString]; + + NSNumber *n = [[self columnNameToIndexMap] objectForKey:columnName]; + + if (n != nil) { + return [n intValue]; + } + + NSLog(@"Warning: I could not find the column named '%@'.", columnName); + + return -1; +} + +- (int)intForColumn:(NSString*)columnName { + return [self intForColumnIndex:[self columnIndexForName:columnName]]; +} + +- (int)intForColumnIndex:(int)columnIdx { + return sqlite3_column_int([_statement statement], columnIdx); +} + +- (long)longForColumn:(NSString*)columnName { + return [self longForColumnIndex:[self columnIndexForName:columnName]]; +} + +- (long)longForColumnIndex:(int)columnIdx { + return (long)sqlite3_column_int64([_statement statement], columnIdx); +} + +- (long long int)longLongIntForColumn:(NSString*)columnName { + return [self longLongIntForColumnIndex:[self columnIndexForName:columnName]]; +} + +- (long long int)longLongIntForColumnIndex:(int)columnIdx { + return sqlite3_column_int64([_statement statement], columnIdx); +} + +- (unsigned long long int)unsignedLongLongIntForColumn:(NSString*)columnName { + return [self unsignedLongLongIntForColumnIndex:[self columnIndexForName:columnName]]; +} + +- (unsigned long long int)unsignedLongLongIntForColumnIndex:(int)columnIdx { + return (unsigned long long int)[self longLongIntForColumnIndex:columnIdx]; +} + +- (BOOL)boolForColumn:(NSString*)columnName { + return [self boolForColumnIndex:[self columnIndexForName:columnName]]; +} + +- (BOOL)boolForColumnIndex:(int)columnIdx { + return ([self intForColumnIndex:columnIdx] != 0); +} + +- (double)doubleForColumn:(NSString*)columnName { + return [self doubleForColumnIndex:[self columnIndexForName:columnName]]; +} + +- (double)doubleForColumnIndex:(int)columnIdx { + return sqlite3_column_double([_statement statement], columnIdx); +} + +- (NSString *)stringForColumnIndex:(int)columnIdx { + + if (sqlite3_column_type([_statement statement], columnIdx) == SQLITE_NULL || (columnIdx < 0) || columnIdx >= sqlite3_column_count([_statement statement])) { + return nil; + } + + const char *c = (const char *)sqlite3_column_text([_statement statement], columnIdx); + + if (!c) { + // null row. + return nil; + } + + return [NSString stringWithUTF8String:c]; +} + +- (NSString*)stringForColumn:(NSString*)columnName { + return [self stringForColumnIndex:[self columnIndexForName:columnName]]; +} + +- (NSDate*)dateForColumn:(NSString*)columnName { + return [self dateForColumnIndex:[self columnIndexForName:columnName]]; +} + +- (NSDate*)dateForColumnIndex:(int)columnIdx { + + if (sqlite3_column_type([_statement statement], columnIdx) == SQLITE_NULL || (columnIdx < 0) || columnIdx >= sqlite3_column_count([_statement statement])) { + return nil; + } + + return [_parentDB hasDateFormatter] ? [_parentDB dateFromString:[self stringForColumnIndex:columnIdx]] : [NSDate dateWithTimeIntervalSince1970:[self doubleForColumnIndex:columnIdx]]; +} + + +- (NSData*)dataForColumn:(NSString*)columnName { + return [self dataForColumnIndex:[self columnIndexForName:columnName]]; +} + +- (NSData*)dataForColumnIndex:(int)columnIdx { + + if (sqlite3_column_type([_statement statement], columnIdx) == SQLITE_NULL || (columnIdx < 0) || columnIdx >= sqlite3_column_count([_statement statement])) { + return nil; + } + + const char *dataBuffer = sqlite3_column_blob([_statement statement], columnIdx); + int dataSize = sqlite3_column_bytes([_statement statement], columnIdx); + + if (dataBuffer == NULL) { + return nil; + } + + return [NSData dataWithBytes:(const void *)dataBuffer length:(NSUInteger)dataSize]; +} + + +- (NSData*)dataNoCopyForColumn:(NSString*)columnName { + return [self dataNoCopyForColumnIndex:[self columnIndexForName:columnName]]; +} + +- (NSData*)dataNoCopyForColumnIndex:(int)columnIdx { + + if (sqlite3_column_type([_statement statement], columnIdx) == SQLITE_NULL || (columnIdx < 0) || columnIdx >= sqlite3_column_count([_statement statement])) { + return nil; + } + + const char *dataBuffer = sqlite3_column_blob([_statement statement], columnIdx); + int dataSize = sqlite3_column_bytes([_statement statement], columnIdx); + + NSData *data = [NSData dataWithBytesNoCopy:(void *)dataBuffer length:(NSUInteger)dataSize freeWhenDone:NO]; + + return data; +} + + +- (BOOL)columnIndexIsNull:(int)columnIdx { + return sqlite3_column_type([_statement statement], columnIdx) == SQLITE_NULL; +} + +- (BOOL)columnIsNull:(NSString*)columnName { + return [self columnIndexIsNull:[self columnIndexForName:columnName]]; +} + +- (const unsigned char *)UTF8StringForColumnIndex:(int)columnIdx { + + if (sqlite3_column_type([_statement statement], columnIdx) == SQLITE_NULL || (columnIdx < 0) || columnIdx >= sqlite3_column_count([_statement statement])) { + return nil; + } + + return sqlite3_column_text([_statement statement], columnIdx); +} + +- (const unsigned char *)UTF8StringForColumn:(NSString*)columnName { + return [self UTF8StringForColumnIndex:[self columnIndexForName:columnName]]; +} + +- (const unsigned char *)UTF8StringForColumnName:(NSString*)columnName { + return [self UTF8StringForColumn:columnName]; +} + +- (id)objectForColumnIndex:(int)columnIdx { + if (columnIdx < 0 || columnIdx >= sqlite3_column_count([_statement statement])) { + return nil; + } + + int columnType = sqlite3_column_type([_statement statement], columnIdx); + + id returnValue = nil; + + if (columnType == SQLITE_INTEGER) { + returnValue = [NSNumber numberWithLongLong:[self longLongIntForColumnIndex:columnIdx]]; + } + else if (columnType == SQLITE_FLOAT) { + returnValue = [NSNumber numberWithDouble:[self doubleForColumnIndex:columnIdx]]; + } + else if (columnType == SQLITE_BLOB) { + returnValue = [self dataForColumnIndex:columnIdx]; + } + else { + //default to a string for everything else + returnValue = [self stringForColumnIndex:columnIdx]; + } + + if (returnValue == nil) { + returnValue = [NSNull null]; + } + + return returnValue; +} + +- (id)objectForColumnName:(NSString*)columnName { + return [self objectForColumn:columnName]; +} + +- (id)objectForColumn:(NSString*)columnName { + return [self objectForColumnIndex:[self columnIndexForName:columnName]]; +} + +// returns autoreleased NSString containing the name of the column in the result set +- (NSString*)columnNameForIndex:(int)columnIdx { + return [NSString stringWithUTF8String: sqlite3_column_name([_statement statement], columnIdx)]; +} + +- (id)objectAtIndexedSubscript:(int)columnIdx { + return [self objectForColumnIndex:columnIdx]; +} + +- (id)objectForKeyedSubscript:(NSString *)columnName { + return [self objectForColumn:columnName]; +} + + +@end From c3b380272ba7cfa93d430a58028984a88fed0990 Mon Sep 17 00:00:00 2001 From: Dan Tamas Date: Thu, 19 Jul 2018 14:27:56 +0200 Subject: [PATCH 0482/1148] Revert "Added MBTiles support for iOS and Android (#2208)" (#2387) This reverts commit 2d760e19b111ba2721ca8f6dfde9e4339939ff1f. --- README.md | 33 - example/examples/MbTileOverlay.js | 91 - index.d.ts | 11 +- index.js | 16 +- .../android/react/maps/AirMapMbTile.java | 150 -- .../react/maps/AirMapMbTileManager.java | 56 - .../airbnb/android/react/maps/AirMapView.java | 165 +- .../android/react/maps/MapsPackage.java | 2 - lib/components/MapMbTile.js | 71 - lib/components/MapView.js | 63 +- lib/ios/AirMaps.xcodeproj/project.pbxproj | 50 - lib/ios/AirMaps/AIRMap.m | 41 +- lib/ios/AirMaps/AIRMapManager.m | 77 +- lib/ios/AirMaps/AIRMapMbTile.h | 47 - lib/ios/AirMaps/AIRMapMbTile.m | 68 - lib/ios/AirMaps/AIRMapMbTileManager.h | 14 - lib/ios/AirMaps/AIRMapMbTileManager.m | 40 - lib/ios/AirMaps/AIRMapMbTileOverlay.h | 15 - lib/ios/AirMaps/AIRMapMbTileOverlay.m | 45 - lib/ios/AirMaps/fmdb/FMDB.h | 10 - lib/ios/AirMaps/fmdb/FMDatabase.h | 1360 -------------- lib/ios/AirMaps/fmdb/FMDatabase.m | 1596 ----------------- lib/ios/AirMaps/fmdb/FMDatabaseAdditions.h | 250 --- lib/ios/AirMaps/fmdb/FMDatabaseAdditions.m | 245 --- lib/ios/AirMaps/fmdb/FMDatabasePool.h | 258 --- lib/ios/AirMaps/fmdb/FMDatabasePool.m | 316 ---- lib/ios/AirMaps/fmdb/FMDatabaseQueue.h | 235 --- lib/ios/AirMaps/fmdb/FMDatabaseQueue.m | 270 --- lib/ios/AirMaps/fmdb/FMResultSet.h | 467 ----- lib/ios/AirMaps/fmdb/FMResultSet.m | 432 ----- 30 files changed, 270 insertions(+), 6224 deletions(-) delete mode 100644 example/examples/MbTileOverlay.js mode change 100755 => 100644 index.d.ts mode change 100755 => 100644 index.js delete mode 100644 lib/android/src/main/java/com/airbnb/android/react/maps/AirMapMbTile.java delete mode 100644 lib/android/src/main/java/com/airbnb/android/react/maps/AirMapMbTileManager.java mode change 100755 => 100644 lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java mode change 100755 => 100644 lib/android/src/main/java/com/airbnb/android/react/maps/MapsPackage.java delete mode 100644 lib/components/MapMbTile.js mode change 100755 => 100644 lib/components/MapView.js mode change 100755 => 100644 lib/ios/AirMaps/AIRMap.m mode change 100755 => 100644 lib/ios/AirMaps/AIRMapManager.m delete mode 100644 lib/ios/AirMaps/AIRMapMbTile.h delete mode 100644 lib/ios/AirMaps/AIRMapMbTile.m delete mode 100644 lib/ios/AirMaps/AIRMapMbTileManager.h delete mode 100644 lib/ios/AirMaps/AIRMapMbTileManager.m delete mode 100644 lib/ios/AirMaps/AIRMapMbTileOverlay.h delete mode 100644 lib/ios/AirMaps/AIRMapMbTileOverlay.m delete mode 100644 lib/ios/AirMaps/fmdb/FMDB.h delete mode 100644 lib/ios/AirMaps/fmdb/FMDatabase.h delete mode 100644 lib/ios/AirMaps/fmdb/FMDatabase.m delete mode 100644 lib/ios/AirMaps/fmdb/FMDatabaseAdditions.h delete mode 100644 lib/ios/AirMaps/fmdb/FMDatabaseAdditions.m delete mode 100755 lib/ios/AirMaps/fmdb/FMDatabasePool.h delete mode 100755 lib/ios/AirMaps/fmdb/FMDatabasePool.m delete mode 100755 lib/ios/AirMaps/fmdb/FMDatabaseQueue.h delete mode 100755 lib/ios/AirMaps/fmdb/FMDatabaseQueue.m delete mode 100644 lib/ios/AirMaps/fmdb/FMResultSet.h delete mode 100644 lib/ios/AirMaps/fmdb/FMResultSet.m diff --git a/README.md b/README.md index c5f02e97a..e6e08cf7f 100644 --- a/README.md +++ b/README.md @@ -221,39 +221,6 @@ For Android: LocalTile is still just overlay over original map tiles. It means t See [OSM Wiki](https://wiki.openstreetmap.org/wiki/Category:Tile_downloading) for how to download tiles for offline usage. - -#### Tile Overlay using MbTile - -Tiles can be stored locally in a MBTiles database on the device using xyz tiling scheme. The locally stored tiles can be displayed as a tile overlay. This can be used for displaying maps offline. Manging many tiles in a database is especially useful if larger areas are covered by an offline map. Keeping all the files locally and "raw" on the device most likely results in bad performance as well as troublesome datahandling. Please make sure that your database follows the MBTiles [specifications](https://github.com/mapbox/mbtiles-spec). This only works with tiles stored in the [xyz scheme](https://gist.github.com/tmcw/4954720) as used by Google, OSM, MapBox, ... Make sure to include the ending .mbtiles when you pass your pathTemplate. - -```jsx -import MapView from 'react-native-maps'; - - - - -``` - -For Android: LocalTile is still just overlay over original map tiles. It means that if device is online, underlying tiles will be still downloaded. If original tiles download/display is not desirable set mapType to 'none'. For example: -``` - -``` - ### Customizing the map style Create the json object, or download a generated one from the [google style generator](https://mapstyle.withgoogle.com/). diff --git a/example/examples/MbTileOverlay.js b/example/examples/MbTileOverlay.js deleted file mode 100644 index cfb185147..000000000 --- a/example/examples/MbTileOverlay.js +++ /dev/null @@ -1,91 +0,0 @@ -import React, { Component } from 'react'; -import { - StyleSheet, - View, - Dimensions, - TouchableOpacity, - Text, - Platform, -} from 'react-native'; -import MapView from 'react-native-maps'; - -const { width, height } = Dimensions.get('window'); - -const ASPECT_RATIO = width / height; -const LATITUDE = 23.736906; -const LONGITUDE = 90.397768; -const LATITUDE_DELTA = 0.022; -const LONGITUDE_DELTA = LATITUDE_DELTA * ASPECT_RATIO; - - -type Props = {}; -export default class App extends Component { - constructor(props) { - super(props); - - this.state = { - offlineMap: false, - }; - } - - _toggleOfflineMap = () => { - this.setState({ - offlineMap: !this.state.offlineMap, - }); - } - - render() { - return ( - - - {this.state.offlineMap ? - : null} - - this._toggleOfflineMap()} - > - {this.state.offlineMap ? 'Switch to Online Map' : 'Switch to Offline Map'} - - - ); - } -} - -const styles = StyleSheet.create({ - container: { - ...StyleSheet.absoluteFillObject, - alignItems: 'center', - }, - button: { - position: 'absolute', - bottom: 20, - backgroundColor: 'lightblue', - zIndex: 999999, - height: 50, - width: width / 2, - borderRadius: width / 2, - justifyContent: 'center', - alignItems: 'center', - }, - map: { - ...StyleSheet.absoluteFillObject, - }, -}); diff --git a/index.d.ts b/index.d.ts old mode 100755 new mode 100644 index f380d3c15..83d4f2fa3 --- a/index.d.ts +++ b/index.d.ts @@ -366,7 +366,7 @@ declare module "react-native-maps" { } // ======================================================================= - // UrlTile, LocalTile & MbTile + // UrlTile & LocalTile // ======================================================================= export interface MapUrlTileProps extends ViewProperties { @@ -387,15 +387,6 @@ declare module "react-native-maps" { export class LocalTile extends React.Component { } - export interface MapMbTileProps extends ViewProperties { - pathTemplate: string; - tileSize: number; - zIndex?: number; - } - - export class MbTile extends React.Component { - } - // ======================================================================= // Overlay // ======================================================================= diff --git a/index.js b/index.js old mode 100755 new mode 100644 index 841cd16cd..acc1f7553 --- a/index.js +++ b/index.js @@ -1,17 +1,23 @@ -import MapView from './lib/components/MapView'; +import MapView, { Animated, MAP_TYPES, ProviderPropType } from './lib/components/MapView'; +import Marker from './lib/components/MapMarker.js'; +import Overlay from './lib/components/MapOverlay.js'; -export { default as Marker } from './lib/components/MapMarker.js'; export { default as Polyline } from './lib/components/MapPolyline.js'; export { default as Polygon } from './lib/components/MapPolygon.js'; export { default as Circle } from './lib/components/MapCircle.js'; export { default as UrlTile } from './lib/components/MapUrlTile.js'; export { default as LocalTile } from './lib/components/MapLocalTile.js'; -export { default as MbTile } from './lib/components/MapMbTile.js'; -export { default as Overlay } from './lib/components/MapOverlay.js'; export { default as Callout } from './lib/components/MapCallout.js'; export { default as AnimatedRegion } from './lib/components/AnimatedRegion.js'; -export { Animated, ProviderPropType, MAP_TYPES } from './lib/components/MapView.js'; + +export { Marker, Overlay }; +export { Animated, MAP_TYPES, ProviderPropType }; + export const PROVIDER_GOOGLE = MapView.PROVIDER_GOOGLE; export const PROVIDER_DEFAULT = MapView.PROVIDER_DEFAULT; +export const MarkerAnimated = Marker.Animated; +export const OverlayAnimated = Overlay.Animated; + export default MapView; + diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapMbTile.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapMbTile.java deleted file mode 100644 index 0c948adef..000000000 --- a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapMbTile.java +++ /dev/null @@ -1,150 +0,0 @@ -package com.airbnb.android.react.maps; - -import android.content.Context; - -import com.google.android.gms.maps.GoogleMap; -import com.google.android.gms.maps.model.Tile; -import com.google.android.gms.maps.model.TileOverlay; -import com.google.android.gms.maps.model.TileOverlayOptions; -import com.google.android.gms.maps.model.TileProvider; - -import java.io.File; - -import android.os.Environment; -import android.database.sqlite.SQLiteDatabase; -import android.database.sqlite.SQLiteCantOpenDatabaseException; -import android.database.sqlite.SQLiteDatabaseCorruptException; -import android.database.sqlite.SQLiteDatabaseLockedException; -import android.database.Cursor; - -/** - * Created by Christoph Lambio on 30/03/2018. - * Based on AirMapLocalTileManager.java - * Copyright (c) zavadpe - */ - -public class AirMapMbTile extends AirMapFeature { - - class AIRMapMbTileProvider implements TileProvider { - private static final int BUFFER_SIZE = 16 * 1024; - private int tileSize; - private String pathTemplate; - - - public AIRMapMbTileProvider(int tileSizet, String pathTemplate) { - this.tileSize = tileSizet; - this.pathTemplate = pathTemplate; - } - - @Override - public Tile getTile(int x, int y, int zoom) { - byte[] image = readTileImage(x, y, zoom); - return image == null ? TileProvider.NO_TILE : new Tile(this.tileSize, this.tileSize, image); - } - - public void setPathTemplate(String pathTemplate) { - this.pathTemplate = pathTemplate; - } - - public void setTileSize(int tileSize) { - this.tileSize = tileSize; - } - - private byte[] readTileImage(int x, int y, int zoom) { - String rawQuery = "SELECT * FROM map INNER JOIN images ON map.tile_id = images.tile_id WHERE map.zoom_level = {z} AND map.tile_column = {x} AND map.tile_row = {y}"; - byte[] tile = null; - try { - SQLiteDatabase offlineDataDatabase = SQLiteDatabase.openDatabase(this.pathTemplate, null, SQLiteDatabase.OPEN_READONLY); - String query = rawQuery.replace("{x}", Integer.toString(x)) - .replace("{y}", Integer.toString(y)) - .replace("{z}", Integer.toString(zoom)); - Cursor cursor = offlineDataDatabase.rawQuery(query, null); - if (cursor.moveToFirst()) { - tile = cursor.getBlob(5); - } - cursor.close(); - offlineDataDatabase.close(); - } catch (SQLiteCantOpenDatabaseException e) { - e.printStackTrace(); - throw e; - } catch (SQLiteDatabaseCorruptException e) { - e.printStackTrace(); - throw e; - } catch (SQLiteDatabaseLockedException e) { - e.printStackTrace(); - throw e; - } catch (Exception e) { - e.printStackTrace(); - throw e; - } finally { - return tile; - } - } - } - - private TileOverlayOptions tileOverlayOptions; - private TileOverlay tileOverlay; - private AirMapMbTile.AIRMapMbTileProvider tileProvider; - - private String pathTemplate; - private float tileSize; - private float zIndex; - - public AirMapMbTile(Context context) { - super(context); - } - - public void setPathTemplate(String pathTemplate) { - this.pathTemplate = pathTemplate; - if (tileProvider != null) { - tileProvider.setPathTemplate(pathTemplate); - } - if (tileOverlay != null) { - tileOverlay.clearTileCache(); - } - } - - public void setZIndex(float zIndex) { - this.zIndex = zIndex; - if (tileOverlay != null) { - tileOverlay.setZIndex(zIndex); - } - } - - public void setTileSize(float tileSize) { - this.tileSize = tileSize; - if (tileProvider != null) { - tileProvider.setTileSize((int)tileSize); - } - } - - public TileOverlayOptions getTileOverlayOptions() { - if (tileOverlayOptions == null) { - tileOverlayOptions = createTileOverlayOptions(); - } - return tileOverlayOptions; - } - - private TileOverlayOptions createTileOverlayOptions() { - TileOverlayOptions options = new TileOverlayOptions(); - options.zIndex(zIndex); - this.tileProvider = new AirMapMbTile.AIRMapMbTileProvider((int)this.tileSize, this.pathTemplate); - options.tileProvider(this.tileProvider); - return options; - } - - @Override - public Object getFeature() { - return tileOverlay; - } - - @Override - public void addToMap(GoogleMap map) { - this.tileOverlay = map.addTileOverlay(getTileOverlayOptions()); - } - - @Override - public void removeFromMap(GoogleMap map) { - tileOverlay.remove(); - } -} diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapMbTileManager.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapMbTileManager.java deleted file mode 100644 index cb3e2e549..000000000 --- a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapMbTileManager.java +++ /dev/null @@ -1,56 +0,0 @@ -package com.airbnb.android.react.maps; - -import android.content.Context; -import android.os.Build; -import android.util.DisplayMetrics; -import android.view.WindowManager; - -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.uimanager.ThemedReactContext; -import com.facebook.react.uimanager.ViewGroupManager; -import com.facebook.react.uimanager.annotations.ReactProp; - -/** - * Created by Christoph Lambio on 30/03/2018. - * Based on AirMapLocalTileManager.java - * Copyright (c) zavadpe - */ -public class AirMapMbTileManager extends ViewGroupManager { - private DisplayMetrics metrics; - - public AirMapMbTileManager(ReactApplicationContext reactContext) { - super(); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { - metrics = new DisplayMetrics(); - ((WindowManager) reactContext.getSystemService(Context.WINDOW_SERVICE)) - .getDefaultDisplay() - .getRealMetrics(metrics); - } else { - metrics = reactContext.getResources().getDisplayMetrics(); - } - } - - @Override - public String getName() { - return "AIRMapMbTile"; - } - - @Override - public AirMapMbTile createViewInstance(ThemedReactContext context) { - return new AirMapMbTile(context); - } - - @ReactProp(name = "pathTemplate") - public void setPathTemplate(AirMapMbTile view, String pathTemplate) { view.setPathTemplate(pathTemplate); } - - @ReactProp(name = "tileSize", defaultFloat = 256f) - public void setTileSize(AirMapMbTile view, float tileSize) { - view.setTileSize(tileSize); - } - - @ReactProp(name = "zIndex", defaultFloat = -1.0f) - public void setZIndex(AirMapMbTile view, float zIndex) { - view.setZIndex(zIndex); - } - -} \ No newline at end of file diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java old mode 100755 new mode 100644 index 9dd751e12..5882f8cab --- a/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java @@ -8,7 +8,6 @@ import android.graphics.Point; import android.graphics.PorterDuff; import android.os.Build; -import android.os.Handler; import android.support.v4.view.GestureDetectorCompat; import android.support.v4.view.MotionEventCompat; import android.view.GestureDetector; @@ -18,12 +17,15 @@ import android.widget.ImageView; import android.widget.ProgressBar; import android.widget.RelativeLayout; +import android.location.Location; import com.facebook.react.bridge.LifecycleEventListener; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReadableArray; import com.facebook.react.bridge.ReadableMap; +import com.facebook.react.bridge.WritableArray; import com.facebook.react.bridge.WritableMap; +import com.facebook.react.bridge.WritableNativeArray; import com.facebook.react.bridge.WritableNativeMap; import com.facebook.react.uimanager.ThemedReactContext; import com.facebook.react.uimanager.UIManagerModule; @@ -35,25 +37,37 @@ import com.google.android.gms.maps.MapView; import com.google.android.gms.maps.OnMapReadyCallback; import com.google.android.gms.maps.Projection; +import com.google.android.gms.maps.model.BitmapDescriptorFactory; import com.google.android.gms.maps.model.CameraPosition; import com.google.android.gms.maps.model.LatLng; import com.google.android.gms.maps.model.LatLngBounds; import com.google.android.gms.maps.model.Marker; +import com.google.android.gms.maps.model.MarkerOptions; +import com.google.android.gms.maps.model.PointOfInterest; import com.google.android.gms.maps.model.Polygon; import com.google.android.gms.maps.model.Polyline; -import com.google.android.gms.maps.model.VisibleRegion; +import com.google.maps.android.data.kml.KmlContainer; +import com.google.maps.android.data.kml.KmlLayer; +import com.google.maps.android.data.kml.KmlPlacemark; +import com.google.maps.android.data.kml.KmlStyle; +import org.xmlpull.v1.XmlPullParserException; + +import java.io.IOException; +import java.io.InputStream; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.concurrent.ExecutionException; import static android.support.v4.content.PermissionChecker.checkSelfPermission; public class AirMapView extends MapView implements GoogleMap.InfoWindowAdapter, - GoogleMap.OnMarkerDragListener, OnMapReadyCallback { + GoogleMap.OnMarkerDragListener, OnMapReadyCallback, GoogleMap.OnPoiClickListener { public GoogleMap map; + private KmlLayer kmlLayer; private ProgressBar mapLoadingProgressBar; private RelativeLayout mapLoadingLayout; private ImageView cacheImageView; @@ -165,6 +179,7 @@ public void onMapReady(final GoogleMap map) { this.map = map; this.map.setInfoWindowAdapter(this); this.map.setOnMarkerDragListener(this); + this.map.setOnPoiClickListener(this); manager.pushEvent(context, this, "onMapReady", new WritableNativeMap()); @@ -196,7 +211,7 @@ public void onMyLocationChange(Location location){ @Override public boolean onMarkerClick(Marker marker) { WritableMap event; - AirMapMarker airMapMarker = markerMap.get(marker); + AirMapMarker airMapMarker = getMarkerMap(marker); event = makeClickEventData(marker.getPosition()); event.putString("action", "marker-press"); @@ -206,7 +221,7 @@ public boolean onMarkerClick(Marker marker) { event = makeClickEventData(marker.getPosition()); event.putString("action", "marker-press"); event.putString("id", airMapMarker.getIdentifier()); - manager.pushEvent(context, markerMap.get(marker), "onPress", event); + manager.pushEvent(context, airMapMarker, "onPress", event); // Return false to open the callout info window and center on the marker // https://developers.google.com/android/reference/com/google/android/gms/maps/GoogleMap @@ -249,7 +264,7 @@ public void onInfoWindowClick(Marker marker) { event = makeClickEventData(marker.getPosition()); event.putString("action", "callout-press"); - AirMapMarker markerView = markerMap.get(marker); + AirMapMarker markerView = getMarkerMap(marker); manager.pushEvent(context, markerView, "onCalloutPress", event); event = makeClickEventData(marker.getPosition()); @@ -528,10 +543,6 @@ public void addFeature(View child, int index) { AirMapLocalTile localTileView = (AirMapLocalTile) child; localTileView.addToMap(map); features.add(index, localTileView); - } else if (child instanceof AirMapMbTile) { - AirMapMbTile mbTileView = (AirMapMbTile) child; - mbTileView.addToMap(map); - features.add(index, mbTileView); } else if (child instanceof AirMapOverlay) { AirMapOverlay overlayView = (AirMapOverlay) child; overlayView.addToMap(map); @@ -752,13 +763,13 @@ public void setMapBoundaries(ReadableMap northEast, ReadableMap southWest) { @Override public View getInfoWindow(Marker marker) { - AirMapMarker markerView = markerMap.get(marker); + AirMapMarker markerView = getMarkerMap(marker); return markerView.getCallout(); } @Override public View getInfoContents(Marker marker) { - AirMapMarker markerView = markerMap.get(marker); + AirMapMarker markerView = getMarkerMap(marker); return markerView.getInfoContents(); } @@ -787,7 +798,7 @@ public void onMarkerDragStart(Marker marker) { WritableMap event = makeClickEventData(marker.getPosition()); manager.pushEvent(context, this, "onMarkerDragStart", event); - AirMapMarker markerView = markerMap.get(marker); + AirMapMarker markerView = getMarkerMap(marker); event = makeClickEventData(marker.getPosition()); manager.pushEvent(context, markerView, "onDragStart", event); } @@ -797,7 +808,7 @@ public void onMarkerDrag(Marker marker) { WritableMap event = makeClickEventData(marker.getPosition()); manager.pushEvent(context, this, "onMarkerDrag", event); - AirMapMarker markerView = markerMap.get(marker); + AirMapMarker markerView = getMarkerMap(marker); event = makeClickEventData(marker.getPosition()); manager.pushEvent(context, markerView, "onDrag", event); } @@ -807,11 +818,21 @@ public void onMarkerDragEnd(Marker marker) { WritableMap event = makeClickEventData(marker.getPosition()); manager.pushEvent(context, this, "onMarkerDragEnd", event); - AirMapMarker markerView = markerMap.get(marker); + AirMapMarker markerView = getMarkerMap(marker); event = makeClickEventData(marker.getPosition()); manager.pushEvent(context, markerView, "onDragEnd", event); } + @Override + public void onPoiClick(PointOfInterest poi) { + WritableMap event = makeClickEventData(poi.latLng); + + event.putString("placeId", poi.placeId); + event.putString("name", poi.name); + + manager.pushEvent(context, this, "onPoiClick", event); + } + private ProgressBar getMapLoadingProgressBar() { if (this.mapLoadingProgressBar == null) { this.mapLoadingProgressBar = new ProgressBar(getContext()); @@ -904,4 +925,118 @@ public void onPanDrag(MotionEvent ev) { WritableMap event = makeClickEventData(coords); manager.pushEvent(context, this, "onPanDrag", event); } + + public void setKmlSrc(String kmlSrc) { + try { + InputStream kmlStream = new FileUtil(context).execute(kmlSrc).get(); + + if (kmlStream == null) { + return; + } + + kmlLayer = new KmlLayer(map, kmlStream, context); + kmlLayer.addLayerToMap(); + + WritableMap pointers = new WritableNativeMap(); + WritableArray markers = new WritableNativeArray(); + + if (kmlLayer.getContainers() == null) { + manager.pushEvent(context, this, "onKmlReady", pointers); + return; + } + + //Retrieve a nested container within the first container + KmlContainer container = kmlLayer.getContainers().iterator().next(); + if (container == null || container.getContainers() == null) { + manager.pushEvent(context, this, "onKmlReady", pointers); + return; + } + + + if (container.getContainers().iterator().hasNext()) { + container = container.getContainers().iterator().next(); + } + + Integer index = 0; + for (KmlPlacemark placemark : container.getPlacemarks()) { + MarkerOptions options = new MarkerOptions(); + + if (placemark.getInlineStyle() != null) { + options = placemark.getMarkerOptions(); + } else { + options.icon(BitmapDescriptorFactory.defaultMarker()); + } + + LatLng latLng = ((LatLng) placemark.getGeometry().getGeometryObject()); + String title = ""; + String snippet = ""; + + if (placemark.hasProperty("name")) { + title = placemark.getProperty("name"); + } + + if (placemark.hasProperty("description")) { + snippet = placemark.getProperty("description"); + } + + options.position(latLng); + options.title(title); + options.snippet(snippet); + + AirMapMarker marker = new AirMapMarker(context, options); + + if (placemark.getInlineStyle() != null + && placemark.getInlineStyle().getIconUrl() != null) { + marker.setImage(placemark.getInlineStyle().getIconUrl()); + } else if (container.getStyle(placemark.getStyleId()) != null) { + KmlStyle style = container.getStyle(placemark.getStyleId()); + marker.setImage(style.getIconUrl()); + } + + String identifier = title + " - " + index; + + marker.setIdentifier(identifier); + + addFeature(marker, index++); + + WritableMap loadedMarker = makeClickEventData(latLng); + loadedMarker.putString("id", identifier); + loadedMarker.putString("title", title); + loadedMarker.putString("description", snippet); + + markers.pushMap(loadedMarker); + } + + pointers.putArray("markers", markers); + + manager.pushEvent(context, this, "onKmlReady", pointers); + + } catch (XmlPullParserException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } catch (InterruptedException e) { + e.printStackTrace(); + } catch (ExecutionException e) { + e.printStackTrace(); + } + } + + private AirMapMarker getMarkerMap(Marker marker) { + AirMapMarker airMarker = markerMap.get(marker); + + if (airMarker != null) { + return airMarker; + } + + for (Map.Entry entryMarker : markerMap.entrySet()) { + if (entryMarker.getKey().getPosition().equals(marker.getPosition()) + && entryMarker.getKey().getTitle().equals(marker.getTitle())) { + airMarker = entryMarker.getValue(); + break; + } + } + + return airMarker; + } } diff --git a/lib/android/src/main/java/com/airbnb/android/react/maps/MapsPackage.java b/lib/android/src/main/java/com/airbnb/android/react/maps/MapsPackage.java old mode 100755 new mode 100644 index e1d385021..45364b3be --- a/lib/android/src/main/java/com/airbnb/android/react/maps/MapsPackage.java +++ b/lib/android/src/main/java/com/airbnb/android/react/maps/MapsPackage.java @@ -40,7 +40,6 @@ public List createViewManagers(ReactApplicationContext reactContext AirMapLiteManager mapLiteManager = new AirMapLiteManager(reactContext); AirMapUrlTileManager urlTileManager = new AirMapUrlTileManager(reactContext); AirMapLocalTileManager localTileManager = new AirMapLocalTileManager(reactContext); - AirMapMbTileManager mbTileManager = new AirMapMbTileManager(reactContext); AirMapOverlayManager overlayManager = new AirMapOverlayManager(reactContext); return Arrays.asList( @@ -53,7 +52,6 @@ public List createViewManagers(ReactApplicationContext reactContext mapLiteManager, urlTileManager, localTileManager, - mbTileManager, overlayManager ); } diff --git a/lib/components/MapMbTile.js b/lib/components/MapMbTile.js deleted file mode 100644 index d439d2781..000000000 --- a/lib/components/MapMbTile.js +++ /dev/null @@ -1,71 +0,0 @@ -// -// MapMbTile.js -// AirMaps -// -// Created by Christoph Lambio on 27/03/2018. -// Based on AIRMapLocalTileManager.h -// - -import PropTypes from 'prop-types'; -import React from 'react'; - -import { - ViewPropTypes, - View, -} from 'react-native'; - -import decorateMapComponent, { - USES_DEFAULT_IMPLEMENTATION, - SUPPORTED, -} from './decorateMapComponent'; - -// if ViewPropTypes is not defined fall back to View.propType (to support RN < 0.44) -const viewPropTypes = ViewPropTypes || View.propTypes; - -const propTypes = { - ...viewPropTypes, - - /** - * The path template of the MBTiles database tile source. - * The patterns {x} {y} {z} will be replaced at runtime, - * for example, /storage/emulated/0/tiles/{z}/{x}/{y}.png. - */ - pathTemplate: PropTypes.string.isRequired, - - /** - * The order in which this tile overlay is drawn with respect to other overlays. An overlay - * with a larger z-index is drawn over overlays with smaller z-indices. The order of overlays - * with the same z-index is arbitrary. The default zIndex is -1. - * - * @platform android - */ - zIndex: PropTypes.number, - - /** - * Size of tile images. - */ - tileSize: PropTypes.number, -}; - -class MapMbTile extends React.Component { - render() { - const AIRMapMbTile = this.getAirComponent(); - return ( - - ); - } -} - -MapMbTile.propTypes = propTypes; - -export default decorateMapComponent(MapMbTile, { - componentType: 'MbTile', - providers: { - google: { - ios: SUPPORTED, - android: USES_DEFAULT_IMPLEMENTATION, - }, - }, -}); diff --git a/lib/components/MapView.js b/lib/components/MapView.js old mode 100755 new mode 100644 index e88651afb..50c4d2657 --- a/lib/components/MapView.js +++ b/lib/components/MapView.js @@ -19,7 +19,6 @@ import MapCallout from './MapCallout'; import MapOverlay from './MapOverlay'; import MapUrlTile from './MapUrlTile'; import MapLocalTile from './MapLocalTile'; -import MapMbTile from './MapMbTile'; import AnimatedRegion from './AnimatedRegion'; import { contextTypes as childContextTypes, @@ -359,6 +358,11 @@ const propTypes = { */ onMapReady: PropTypes.func, + /** + * Callback that is called once the kml is fully loaded. + */ + onKmlReady: PropTypes.func, + /** * Callback that is called continuously when the user is dragging the map. */ @@ -379,11 +383,21 @@ const propTypes = { */ onLongPress: PropTypes.func, + /** + * Callback that is called when the underlying map figures our users current location. + */ + onUserLocationChange: PropTypes.func, + /** * Callback that is called when user makes a "drag" somewhere on the map */ onPanDrag: PropTypes.func, + /** + * Callback that is called when user click on a POI + */ + onPoiClick: PropTypes.func, + /** * Callback that is called when a marker on the map is tapped by the user. */ @@ -436,6 +450,11 @@ const propTypes = { */ maxZoomLevel: PropTypes.number, + /** + * Url KML Source + */ + kmlSrc: PropTypes.string, + }; class MapView extends React.Component { @@ -659,18 +678,7 @@ class MapView extends React.Component { if (Platform.OS === 'android') { return NativeModules.AirMapModule.pointForCoordinate(this._getHandle(), coordinate); } else if (Platform.OS === 'ios') { - return new Promise((resolve, reject) => { - this._runCommand('pointForCoordinate', [ - coordinate, - (err, snapshot) => { - if (err) { - reject(err); - } else { - resolve(snapshot); - } - }, - ]); - }); + return this._runCommand('pointForCoordinate', [coordinate]); } return Promise.reject('pointForCoordinate not supported on this platform'); } @@ -684,24 +692,13 @@ class MapView extends React.Component { * * @return Promise Promise with the coordinate ({ latitude: Number, longitude: Number }) */ - coordinateFromPoint(point) { + coordinateForPoint(point) { if (Platform.OS === 'android') { - return NativeModules.AirMapModule.coordinateFromPoint(this._getHandle(), point); + return NativeModules.AirMapModule.coordinateForPoint(this._getHandle(), point); } else if (Platform.OS === 'ios') { - return new Promise((resolve, reject) => { - this._runCommand('coordinateFromPoint', [ - point, - (err, snapshot) => { - if (err) { - reject(err); - } else { - resolve(snapshot); - } - }, - ]); - }); + return this._runCommand('coordinateForPoint', [point]); } - return Promise.reject('coordinateFromPoint not supported on this platform'); + return Promise.reject('coordinateForPoint not supported on this platform'); } _uiManagerCommand(name) { @@ -719,19 +716,17 @@ class MapView extends React.Component { _runCommand(name, args) { switch (Platform.OS) { case 'android': - NativeModules.UIManager.dispatchViewManagerCommand( + return NativeModules.UIManager.dispatchViewManagerCommand( this._getHandle(), this._uiManagerCommand(name), args ); - break; case 'ios': - this._mapManagerCommand(name)(this._getHandle(), ...args); - break; + return this._mapManagerCommand(name)(this._getHandle(), ...args); default: - break; + return Promise.reject(`Invalid platform was passed: ${Platform.OS}`); } } @@ -795,6 +790,7 @@ const nativeComponent = Component => requireNativeComponent(Component, MapView, nativeOnly: { onChange: true, onMapReady: true, + onKmlReady: true, handlePanDrag: true, }, }); @@ -836,7 +832,6 @@ MapView.Polygon = MapPolygon; MapView.Circle = MapCircle; MapView.UrlTile = MapUrlTile; MapView.LocalTile = MapLocalTile; -MapView.MbTile = MapMbTile; MapView.Overlay = MapOverlay; MapView.Callout = MapCallout; Object.assign(MapView, ProviderConstants); diff --git a/lib/ios/AirMaps.xcodeproj/project.pbxproj b/lib/ios/AirMaps.xcodeproj/project.pbxproj index 1ddaacdb1..7e2468f62 100644 --- a/lib/ios/AirMaps.xcodeproj/project.pbxproj +++ b/lib/ios/AirMaps.xcodeproj/project.pbxproj @@ -47,9 +47,6 @@ 9B9498DA2017EFB800158761 /* AIRGoogleMapPolygon.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B9498C62017EFB800158761 /* AIRGoogleMapPolygon.m */; }; 9B9498DB2017EFB800158761 /* AIRGoogleMapMarker.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B9498C72017EFB800158761 /* AIRGoogleMapMarker.m */; }; 9B9498DC2017EFB800158761 /* AIRGoogleMapPolygonManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B9498C92017EFB800158761 /* AIRGoogleMapPolygonManager.m */; }; - BD9BE2902087408600A3E492 /* AIRMapMbTile.m in Sources */ = {isa = PBXBuildFile; fileRef = BD9BE28C2087408500A3E492 /* AIRMapMbTile.m */; }; - BD9BE2912087408600A3E492 /* AIRMapMbTileManager.m in Sources */ = {isa = PBXBuildFile; fileRef = BD9BE28D2087408600A3E492 /* AIRMapMbTileManager.m */; }; - BD9BE2922087408600A3E492 /* AIRMapMbTileOverlay.m in Sources */ = {isa = PBXBuildFile; fileRef = BD9BE28F2087408600A3E492 /* AIRMapMbTileOverlay.m */; }; B5EA3BA92098E22B000E7AFD /* AIRDummyView.m in Sources */ = {isa = PBXBuildFile; fileRef = B5EA3BA72098E22B000E7AFD /* AIRDummyView.m */; }; DA6C26381C9E2AFE0035349F /* AIRMapUrlTile.m in Sources */ = {isa = PBXBuildFile; fileRef = DA6C26371C9E2AFE0035349F /* AIRMapUrlTile.m */; }; DA6C263E1C9E324A0035349F /* AIRMapUrlTileManager.m in Sources */ = {isa = PBXBuildFile; fileRef = DA6C263D1C9E324A0035349F /* AIRMapUrlTileManager.m */; }; @@ -148,23 +145,6 @@ 9B9498C72017EFB800158761 /* AIRGoogleMapMarker.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AIRGoogleMapMarker.m; path = AirGoogleMaps/AIRGoogleMapMarker.m; sourceTree = ""; }; 9B9498C82017EFB800158761 /* AIRGoogleMapUrlTile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AIRGoogleMapUrlTile.h; path = AirGoogleMaps/AIRGoogleMapUrlTile.h; sourceTree = ""; }; 9B9498C92017EFB800158761 /* AIRGoogleMapPolygonManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AIRGoogleMapPolygonManager.m; path = AirGoogleMaps/AIRGoogleMapPolygonManager.m; sourceTree = ""; }; - BD9BE28A2087408500A3E492 /* AIRMapMbTileManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRMapMbTileManager.h; sourceTree = ""; }; - BD9BE28B2087408500A3E492 /* AIRMapMbTile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRMapMbTile.h; sourceTree = ""; }; - BD9BE28C2087408500A3E492 /* AIRMapMbTile.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRMapMbTile.m; sourceTree = ""; }; - BD9BE28D2087408600A3E492 /* AIRMapMbTileManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRMapMbTileManager.m; sourceTree = ""; }; - BD9BE28E2087408600A3E492 /* AIRMapMbTileOverlay.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRMapMbTileOverlay.h; sourceTree = ""; }; - BD9BE28F2087408600A3E492 /* AIRMapMbTileOverlay.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRMapMbTileOverlay.m; sourceTree = ""; }; - BD9BE2942087408F00A3E492 /* FMDatabase.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FMDatabase.h; sourceTree = ""; }; - BD9BE2952087408F00A3E492 /* FMDatabase.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FMDatabase.m; sourceTree = ""; }; - BD9BE2962087408F00A3E492 /* FMDatabaseAdditions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FMDatabaseAdditions.h; sourceTree = ""; }; - BD9BE2972087408F00A3E492 /* FMDatabaseAdditions.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FMDatabaseAdditions.m; sourceTree = ""; }; - BD9BE2982087408F00A3E492 /* FMDatabasePool.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FMDatabasePool.h; sourceTree = ""; }; - BD9BE2992087408F00A3E492 /* FMDatabasePool.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FMDatabasePool.m; sourceTree = ""; }; - BD9BE29A2087408F00A3E492 /* FMDatabaseQueue.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FMDatabaseQueue.h; sourceTree = ""; }; - BD9BE29B2087408F00A3E492 /* FMDatabaseQueue.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FMDatabaseQueue.m; sourceTree = ""; }; - BD9BE29C2087408F00A3E492 /* FMDB.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FMDB.h; sourceTree = ""; }; - BD9BE29D2087408F00A3E492 /* FMResultSet.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FMResultSet.h; sourceTree = ""; }; - BD9BE29E2087408F00A3E492 /* FMResultSet.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FMResultSet.m; sourceTree = ""; }; B5EA3BA72098E22B000E7AFD /* AIRDummyView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AIRDummyView.m; path = AirGoogleMaps/AIRDummyView.m; sourceTree = ""; }; B5EA3BA82098E22B000E7AFD /* AIRDummyView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AIRDummyView.h; path = AirGoogleMaps/AIRDummyView.h; sourceTree = ""; }; DA6C26361C9E2AFE0035349F /* AIRMapUrlTile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRMapUrlTile.h; sourceTree = ""; }; @@ -187,7 +167,6 @@ 11FA5C481C4A1296003AC2EE = { isa = PBXGroup; children = ( - BD9BE2932087408F00A3E492 /* fmdb */, 9B9498A32017EF9D00158761 /* AirGoogleMaps */, 62AEC4D31FD5A0AA003225E0 /* AIRMapLocalTileOverlay.m */, 11FA5C531C4A1296003AC2EE /* AirMaps */, @@ -206,12 +185,6 @@ 11FA5C531C4A1296003AC2EE /* AirMaps */ = { isa = PBXGroup; children = ( - BD9BE28B2087408500A3E492 /* AIRMapMbTile.h */, - BD9BE28C2087408500A3E492 /* AIRMapMbTile.m */, - BD9BE28A2087408500A3E492 /* AIRMapMbTileManager.h */, - BD9BE28D2087408600A3E492 /* AIRMapMbTileManager.m */, - BD9BE28E2087408600A3E492 /* AIRMapMbTileOverlay.h */, - BD9BE28F2087408600A3E492 /* AIRMapMbTileOverlay.m */, 1125B2BD1C4AD3DA007D0023 /* AIRMap.h */, 1125B2BE1C4AD3DA007D0023 /* AIRMap.m */, 1125B2BF1C4AD3DA007D0023 /* AIRMapCallout.h */, @@ -307,25 +280,6 @@ name = AirGoogleMaps; sourceTree = ""; }; - BD9BE2932087408F00A3E492 /* fmdb */ = { - isa = PBXGroup; - children = ( - BD9BE2942087408F00A3E492 /* FMDatabase.h */, - BD9BE2952087408F00A3E492 /* FMDatabase.m */, - BD9BE2962087408F00A3E492 /* FMDatabaseAdditions.h */, - BD9BE2972087408F00A3E492 /* FMDatabaseAdditions.m */, - BD9BE2982087408F00A3E492 /* FMDatabasePool.h */, - BD9BE2992087408F00A3E492 /* FMDatabasePool.m */, - BD9BE29A2087408F00A3E492 /* FMDatabaseQueue.h */, - BD9BE29B2087408F00A3E492 /* FMDatabaseQueue.m */, - BD9BE29C2087408F00A3E492 /* FMDB.h */, - BD9BE29D2087408F00A3E492 /* FMResultSet.h */, - BD9BE29E2087408F00A3E492 /* FMResultSet.m */, - ); - name = fmdb; - path = AirMaps/fmdb; - sourceTree = ""; - }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -385,7 +339,6 @@ 62AEC4D41FD5A0AA003225E0 /* AIRMapLocalTileOverlay.m in Sources */, 9B9498DC2017EFB800158761 /* AIRGoogleMapPolygonManager.m in Sources */, 1125B2E31C4AD3DA007D0023 /* AIRMapPolygon.m in Sources */, - BD9BE2922087408600A3E492 /* AIRMapMbTileOverlay.m in Sources */, 1125B2E41C4AD3DA007D0023 /* AIRMapPolygonManager.m in Sources */, 9B9498CB2017EFB800158761 /* AIRGoogleMapURLTileManager.m in Sources */, 1125B2DB1C4AD3DA007D0023 /* AIRMapCallout.m in Sources */, @@ -399,8 +352,6 @@ 9B9498D72017EFB800158761 /* AIRGoogleMapManager.m in Sources */, 19DABC7F1E7C9D3C00F41150 /* RCTConvert+AirMap.m in Sources */, 1125B2E51C4AD3DA007D0023 /* AIRMapPolyline.m in Sources */, - BD9BE2902087408600A3E492 /* AIRMapMbTile.m in Sources */, - 9B9498D82017EFB800158761 /* DummyView.m in Sources */, 9B9498D52017EFB800158761 /* AIRGoogleMapPolyline.m in Sources */, 9B9498CF2017EFB800158761 /* AIRGMSPolyline.m in Sources */, 9B9498D42017EFB800158761 /* RCTConvert+GMSMapViewType.m in Sources */, @@ -415,7 +366,6 @@ 1125B2DF1C4AD3DA007D0023 /* AIRMapCoordinate.m in Sources */, 9B9498D62017EFB800158761 /* AIRGoogleMapCircleManager.m in Sources */, 1125B2F21C4AD445007D0023 /* SMCalloutView.m in Sources */, - BD9BE2912087408600A3E492 /* AIRMapMbTileManager.m in Sources */, 2163AA501FEAEDD100BBEC95 /* AIRMapPolylineRenderer.m in Sources */, 9B9498D02017EFB800158761 /* AIRGoogleMapPolylineManager.m in Sources */, 1125B2E11C4AD3DA007D0023 /* AIRMapMarker.m in Sources */, diff --git a/lib/ios/AirMaps/AIRMap.m b/lib/ios/AirMaps/AIRMap.m old mode 100755 new mode 100644 index 8ce4bb411..1e3e76193 --- a/lib/ios/AirMaps/AIRMap.m +++ b/lib/ios/AirMaps/AIRMap.m @@ -18,7 +18,7 @@ #import #import "AIRMapUrlTile.h" #import "AIRMapLocalTile.h" -#import "AIRMapMbTile.h" +#import "AIRMapOverlay.h" const CLLocationDegrees AIRMapDefaultSpan = 0.005; const NSTimeInterval AIRMapRegionChangeObserveInterval = 0.1; @@ -116,6 +116,7 @@ - (void)insertReactSubview:(id)subview atIndex:(NSInteger)atIndex ((AIRMapPolygon *)subview).map = self; [self addOverlay:(id)subview]; } else if ([subview isKindOfClass:[AIRMapCircle class]]) { + ((AIRMapCircle *)subview).map = self; [self addOverlay:(id)subview]; } else if ([subview isKindOfClass:[AIRMapUrlTile class]]) { ((AIRMapUrlTile *)subview).map = self; @@ -123,8 +124,8 @@ - (void)insertReactSubview:(id)subview atIndex:(NSInteger)atIndex } else if ([subview isKindOfClass:[AIRMapLocalTile class]]) { ((AIRMapLocalTile *)subview).map = self; [self addOverlay:(id)subview]; - } else if ([subview isKindOfClass:[AIRMapMbTile class]]) { - ((AIRMapMbTile *)subview).map = self; + } else if ([subview isKindOfClass:[AIRMapOverlay class]]) { + ((AIRMapOverlay *)subview).map = self; [self addOverlay:(id)subview]; } else { NSArray> *childSubviews = [subview reactSubviews]; @@ -153,7 +154,7 @@ - (void)removeReactSubview:(id)subview { [self removeOverlay:(id ) subview]; } else if ([subview isKindOfClass:[AIRMapLocalTile class]]) { [self removeOverlay:(id ) subview]; - } else if ([subview isKindOfClass:[AIRMapMbTile class]]) { + } else if ([subview isKindOfClass:[AIRMapOverlay class]]) { [self removeOverlay:(id ) subview]; } else { NSArray> *childSubviews = [subview reactSubviews]; @@ -316,38 +317,6 @@ - (void)setLoadingIndicatorColor:(UIColor *)loadingIndicatorColor { self.activityIndicatorView.color = loadingIndicatorColor; } -RCT_EXPORT_METHOD(pointForCoordinate:(NSDictionary *)coordinate resolver: (RCTPromiseResolveBlock)resolve - rejecter:(RCTPromiseRejectBlock)reject) -{ - CGPoint touchPoint = [self convertCoordinate: - CLLocationCoordinate2DMake( - [coordinate[@"lat"] doubleValue], - [coordinate[@"lng"] doubleValue] - ) - toPointToView:self]; - - resolve(@{ - @"x": @(touchPoint.x), - @"y": @(touchPoint.y), - }); -} - -RCT_EXPORT_METHOD(coordinateForPoint:(NSDictionary *)point resolver: (RCTPromiseResolveBlock)resolve - rejecter:(RCTPromiseRejectBlock)reject) -{ - CLLocationCoordinate2D coordinate = [self convertPoint: - CGPointMake( - [point[@"x"] doubleValue], - [point[@"y"] doubleValue] - ) - toCoordinateFromView:self]; - - resolve(@{ - @"lat": @(coordinate.latitude), - @"lng": @(coordinate.longitude), - }); -} - // Include properties of MKMapView which are only available on iOS 9+ // and check if their selector is available before calling super method. diff --git a/lib/ios/AirMaps/AIRMapManager.m b/lib/ios/AirMaps/AIRMapManager.m old mode 100755 new mode 100644 index 26e29a38b..da1efc08e --- a/lib/ios/AirMaps/AIRMapManager.m +++ b/lib/ios/AirMaps/AIRMapManager.m @@ -24,9 +24,9 @@ #import "SMCalloutView.h" #import "AIRMapUrlTile.h" #import "AIRMapLocalTile.h" -#import "AIRMapMbTile.h" #import "AIRMapSnapshot.h" #import "RCTConvert+AirMap.h" +#import "AIRMapOverlay.h" #import @@ -75,6 +75,7 @@ - (UIView *)view RCT_EXPORT_VIEW_PROPERTY(showsScale, BOOL) RCT_EXPORT_VIEW_PROPERTY(showsTraffic, BOOL) RCT_EXPORT_VIEW_PROPERTY(zoomEnabled, BOOL) +RCT_EXPORT_VIEW_PROPERTY(kmlSrc, NSString) RCT_EXPORT_VIEW_PROPERTY(rotateEnabled, BOOL) RCT_EXPORT_VIEW_PROPERTY(scrollEnabled, BOOL) RCT_EXPORT_VIEW_PROPERTY(pitchEnabled, BOOL) @@ -340,6 +341,58 @@ - (UIView *)view }]; } +RCT_EXPORT_METHOD(pointForCoordinate:(nonnull NSNumber *)reactTag + coordinate: (NSDictionary *)coordinate + resolver: (RCTPromiseResolveBlock)resolve + rejecter:(RCTPromiseRejectBlock)reject) +{ + [self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary *viewRegistry) { + id view = viewRegistry[reactTag]; + AIRMap *mapView = (AIRMap *)view; + if (![view isKindOfClass:[AIRMap class]]) { + reject(@"Invalid argument", [NSString stringWithFormat:@"Invalid view returned from registry, expecting AIRMap, got: %@", view], NULL); + } else { + CGPoint touchPoint = [mapView convertCoordinate: + CLLocationCoordinate2DMake( + [coordinate[@"lat"] doubleValue], + [coordinate[@"lng"] doubleValue] + ) + toPointToView:mapView]; + + resolve(@{ + @"x": @(touchPoint.x), + @"y": @(touchPoint.y), + }); + } + }]; +} + +RCT_EXPORT_METHOD(coordinateForPoint:(nonnull NSNumber *)reactTag + point:(NSDictionary *)point + resolver: (RCTPromiseResolveBlock)resolve + rejecter:(RCTPromiseRejectBlock)reject) +{ + [self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary *viewRegistry) { + id view = viewRegistry[reactTag]; + AIRMap *mapView = (AIRMap *)view; + if (![view isKindOfClass:[AIRMap class]]) { + reject(@"Invalid argument", [NSString stringWithFormat:@"Invalid view returned from registry, expecting AIRMap, got: %@", view], NULL); + } else { + CLLocationCoordinate2D coordinate = [mapView convertPoint: + CGPointMake( + [point[@"x"] doubleValue], + [point[@"y"] doubleValue] + ) + toCoordinateFromView:mapView]; + + resolve(@{ + @"lat": @(coordinate.latitude), + @"lng": @(coordinate.longitude), + }); + } + }]; +} + #pragma mark Take Snapshot - (void)takeMapSnapshot:(AIRMap *)mapView snapshotter:(MKMapSnapshotter *) snapshotter @@ -481,6 +534,24 @@ - (void)handleMapTap:(UITapGestureRecognizer *)recognizer { } } } + + if ([overlay isKindOfClass:[AIRMapOverlay class]]) { + AIRMapOverlay *imageOverlay = (AIRMapOverlay*) overlay; + if (MKMapRectContainsPoint(imageOverlay.boundingMapRect, mapPoint)) { + if (imageOverlay.onPress) { + id event = @{ + @"action": @"image-overlay-press", + @"name": imageOverlay.name ?: @"unknown", + @"coordinate": @{ + @"latitude": @(imageOverlay.coordinate.latitude), + @"longitude": @(imageOverlay.coordinate.longitude) + } + }; + imageOverlay.onPress(event); + } + } + } + } if (nearestDistance <= maxMeters) { @@ -562,8 +633,8 @@ - (MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id -#import -#import - -#import -#import -#import "AIRMapCoordinate.h" -#import "AIRMap.h" -#import "RCTConvert+AirMap.h" - -#import -#import -#import - -#import -#import -#import "AIRMapCoordinate.h" -#import "AIRMap.h" -#import "RCTConvert+AirMap.h" - -@interface AIRMapMbTile : MKAnnotationView - -@property (nonatomic, weak) AIRMap *map; - -@property (nonatomic, strong) MKTileOverlay *tileOverlay; -@property (nonatomic, strong) MKTileOverlayRenderer *renderer; - -@property (nonatomic, copy) NSString *pathTemplate; -@property (nonatomic, assign) CGFloat tileSize; - -#pragma mark MKOverlay protocol - -@property(nonatomic, readonly) CLLocationCoordinate2D coordinate; -@property(nonatomic, readonly) MKMapRect boundingMapRect; -- (BOOL)canReplaceMapContent; - -@end - diff --git a/lib/ios/AirMaps/AIRMapMbTile.m b/lib/ios/AirMaps/AIRMapMbTile.m deleted file mode 100644 index d63f44d1d..000000000 --- a/lib/ios/AirMaps/AIRMapMbTile.m +++ /dev/null @@ -1,68 +0,0 @@ -// -// AIRMapMbTile.m -// AirMaps -// -// Created by Christoph Lambio on 28/03/2018. -// Based on AIRMapLocalTile.m -// Copyright (c) 2017 Christopher. All rights reserved. -// - -#import "AIRMapMbTile.h" -#import -#import "AIRMapMbTileOverlay.h" - -@implementation AIRMapMbTile { - BOOL _pathTemplateSet; - BOOL _tileSizeSet; -} - -- (void)setPathTemplate:(NSString *)pathTemplate{ - _pathTemplate = pathTemplate; - _pathTemplateSet = YES; - [self createTileOverlayAndRendererIfPossible]; - [self update]; -} - -- (void)setTileSize:(CGFloat)tileSize{ - _tileSize = tileSize; - _tileSizeSet = YES; - [self createTileOverlayAndRendererIfPossible]; - [self update]; -} - -- (void) createTileOverlayAndRendererIfPossible -{ - if (!_pathTemplateSet || !_tileSizeSet) return; - self.tileOverlay = [[AIRMapMbTileOverlay alloc] initWithURLTemplate:self.pathTemplate]; - self.tileOverlay.canReplaceMapContent = YES; - self.tileOverlay.tileSize = CGSizeMake(_tileSize, _tileSize); - self.renderer = [[MKTileOverlayRenderer alloc] initWithTileOverlay:self.tileOverlay]; -} - -- (void) update -{ - if (!_renderer) return; - - if (_map == nil) return; - [_map removeOverlay:self]; - [_map addOverlay:self level:MKOverlayLevelAboveLabels]; -} - -#pragma mark MKOverlay implementation - -- (CLLocationCoordinate2D) coordinate -{ - return self.tileOverlay.coordinate; -} - -- (MKMapRect) boundingMapRect -{ - return self.tileOverlay.boundingMapRect; -} - -- (BOOL)canReplaceMapContent -{ - return self.tileOverlay.canReplaceMapContent; -} - -@end diff --git a/lib/ios/AirMaps/AIRMapMbTileManager.h b/lib/ios/AirMaps/AIRMapMbTileManager.h deleted file mode 100644 index 2a81982e8..000000000 --- a/lib/ios/AirMaps/AIRMapMbTileManager.h +++ /dev/null @@ -1,14 +0,0 @@ -// -// AIRMapMbTileManager.h -// AirMaps -// -// Created by Christoph Lambio on 27/03/2018. -// Based on AIRMapLocalTileManager.h -// Copyright (c) 2017 Christopher. All rights reserved. -// - -#import - -@interface AIRMapMbTileManager : RCTViewManager - -@end diff --git a/lib/ios/AirMaps/AIRMapMbTileManager.m b/lib/ios/AirMaps/AIRMapMbTileManager.m deleted file mode 100644 index 5d815e608..000000000 --- a/lib/ios/AirMaps/AIRMapMbTileManager.m +++ /dev/null @@ -1,40 +0,0 @@ -// -// AIRMapMbTileManager.m -// AirMaps -// -// Created by Christoph Lambio on 27/03/2018. -// Based on AIRMapLocalTileManager.m -// Copyright (c) 2017 Christopher. All rights reserved. -// - -#import -#import -#import -#import -#import -#import -#import "AIRMapMarker.h" -#import "AIRMapMbTile.h" - -#import "AIRMapMbTileManager.h" - -@interface AIRMapMbTileManager() - -@end - -@implementation AIRMapMbTileManager - - -RCT_EXPORT_MODULE() - -- (UIView *)view -{ - AIRMapMbTile *tile = [AIRMapMbTile new]; - return tile; -} - -RCT_EXPORT_VIEW_PROPERTY(pathTemplate, NSString) -RCT_EXPORT_VIEW_PROPERTY(tileSize, CGFloat) - -@end - diff --git a/lib/ios/AirMaps/AIRMapMbTileOverlay.h b/lib/ios/AirMaps/AIRMapMbTileOverlay.h deleted file mode 100644 index 18b5d4791..000000000 --- a/lib/ios/AirMaps/AIRMapMbTileOverlay.h +++ /dev/null @@ -1,15 +0,0 @@ -// -// AIRMapMbTileOverlay.h -// Pods -// -// Created by Christoph Lambio on 28/03/2018. -// Based on AIRMapLocalTileOverlay.h -// Copyright by (c) by Peter Zavadsky on. -// - -#import - -@interface AIRMapMbTileOverlay : MKTileOverlay - -@end - diff --git a/lib/ios/AirMaps/AIRMapMbTileOverlay.m b/lib/ios/AirMaps/AIRMapMbTileOverlay.m deleted file mode 100644 index 1eb6906b5..000000000 --- a/lib/ios/AirMaps/AIRMapMbTileOverlay.m +++ /dev/null @@ -1,45 +0,0 @@ -// -// AIRMapMbTileOverlay.m -// Pods-AirMapsExplorer -// -// Created by Christoph Lambio on 28/03/2018 -// Based on AIRMapLocalTileOverlay.m -// Copyright (c) by Peter Zavadsky. -// - -#import "AIRMapMbTileOverlay.h" -#import "FMDatabase.h" - -@interface AIRMapMbTileOverlay () - -@end - -@implementation AIRMapMbTileOverlay - - --(void)loadTileAtPath:(MKTileOverlayPath)path result:(void (^)(NSData *, NSError *))result { - NSFileManager *fileManager = [NSFileManager defaultManager]; - if ([fileManager fileExistsAtPath:self.URLTemplate]) { - FMDatabase *offlineDataDatabase = [FMDatabase databaseWithPath:self.URLTemplate]; - [offlineDataDatabase open]; - NSMutableString *query = [NSMutableString stringWithString: @"SELECT * FROM map INNER JOIN images ON map.tile_id = images.tile_id WHERE map.zoom_level = {z} AND map.tile_column = {x} AND map.tile_row = {y};"]; - [query replaceCharactersInRange: [query rangeOfString: @"{z}"] withString:[NSString stringWithFormat:@"%li", path.z]]; - [query replaceCharactersInRange: [query rangeOfString: @"{x}"] withString:[NSString stringWithFormat:@"%li", path.x]]; - [query replaceCharactersInRange: [query rangeOfString: @"{y}"] withString:[NSString stringWithFormat:@"%li", path.y]]; - FMResultSet *databaseResult = [offlineDataDatabase executeQuery:query]; - if ([databaseResult next]) { - NSData *tile = [databaseResult dataForColumn:@"tile_data"]; - [offlineDataDatabase close]; - result(tile,nil); - } else { - [offlineDataDatabase close]; - result(nil,nil); - } - } else { - NSLog(@"Database not found. Wrong path."); - } -} - - -@end - diff --git a/lib/ios/AirMaps/fmdb/FMDB.h b/lib/ios/AirMaps/fmdb/FMDB.h deleted file mode 100644 index 1ff546504..000000000 --- a/lib/ios/AirMaps/fmdb/FMDB.h +++ /dev/null @@ -1,10 +0,0 @@ -#import - -FOUNDATION_EXPORT double FMDBVersionNumber; -FOUNDATION_EXPORT const unsigned char FMDBVersionString[]; - -#import "FMDatabase.h" -#import "FMResultSet.h" -#import "FMDatabaseAdditions.h" -#import "FMDatabaseQueue.h" -#import "FMDatabasePool.h" diff --git a/lib/ios/AirMaps/fmdb/FMDatabase.h b/lib/ios/AirMaps/fmdb/FMDatabase.h deleted file mode 100644 index b779d542e..000000000 --- a/lib/ios/AirMaps/fmdb/FMDatabase.h +++ /dev/null @@ -1,1360 +0,0 @@ -#import -#import "FMResultSet.h" -#import "FMDatabasePool.h" - -NS_ASSUME_NONNULL_BEGIN - -#if ! __has_feature(objc_arc) - #define FMDBAutorelease(__v) ([__v autorelease]); - #define FMDBReturnAutoreleased FMDBAutorelease - - #define FMDBRetain(__v) ([__v retain]); - #define FMDBReturnRetained FMDBRetain - - #define FMDBRelease(__v) ([__v release]); - - #define FMDBDispatchQueueRelease(__v) (dispatch_release(__v)); -#else - // -fobjc-arc - #define FMDBAutorelease(__v) - #define FMDBReturnAutoreleased(__v) (__v) - - #define FMDBRetain(__v) - #define FMDBReturnRetained(__v) (__v) - - #define FMDBRelease(__v) - -// If OS_OBJECT_USE_OBJC=1, then the dispatch objects will be treated like ObjC objects -// and will participate in ARC. -// See the section on "Dispatch Queues and Automatic Reference Counting" in "Grand Central Dispatch (GCD) Reference" for details. - #if OS_OBJECT_USE_OBJC - #define FMDBDispatchQueueRelease(__v) - #else - #define FMDBDispatchQueueRelease(__v) (dispatch_release(__v)); - #endif -#endif - -#if !__has_feature(objc_instancetype) - #define instancetype id -#endif - - -typedef int(^FMDBExecuteStatementsCallbackBlock)(NSDictionary *resultsDictionary); - - -/** A SQLite ([http://sqlite.org/](http://sqlite.org/)) Objective-C wrapper. - - ### Usage - The three main classes in FMDB are: - - - `FMDatabase` - Represents a single SQLite database. Used for executing SQL statements. - - `` - Represents the results of executing a query on an `FMDatabase`. - - `` - If you want to perform queries and updates on multiple threads, you'll want to use this class. - - ### See also - - - `` - A pool of `FMDatabase` objects. - - `` - A wrapper for `sqlite_stmt`. - - ### External links - - - [FMDB on GitHub](https://github.com/ccgus/fmdb) including introductory documentation - - [SQLite web site](http://sqlite.org/) - - [FMDB mailing list](http://groups.google.com/group/fmdb) - - [SQLite FAQ](http://www.sqlite.org/faq.html) - - @warning Do not instantiate a single `FMDatabase` object and use it across multiple threads. Instead, use ``. - - */ - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wobjc-interface-ivars" - - -@interface FMDatabase : NSObject - -///----------------- -/// @name Properties -///----------------- - -/** Whether should trace execution */ - -@property (atomic, assign) BOOL traceExecution; - -/** Whether checked out or not */ - -@property (atomic, assign) BOOL checkedOut; - -/** Crash on errors */ - -@property (atomic, assign) BOOL crashOnErrors; - -/** Logs errors */ - -@property (atomic, assign) BOOL logsErrors; - -/** Dictionary of cached statements */ - -@property (atomic, retain, nullable) NSMutableDictionary *cachedStatements; - -///--------------------- -/// @name Initialization -///--------------------- - -/** Create a `FMDatabase` object. - - An `FMDatabase` is created with a path to a SQLite database file. This path can be one of these three: - - 1. A file system path. The file does not have to exist on disk. If it does not exist, it is created for you. - 2. An empty string (`@""`). An empty database is created at a temporary location. This database is deleted with the `FMDatabase` connection is closed. - 3. `nil`. An in-memory database is created. This database will be destroyed with the `FMDatabase` connection is closed. - - For example, to create/open a database in your Mac OS X `tmp` folder: - - FMDatabase *db = [FMDatabase databaseWithPath:@"/tmp/tmp.db"]; - - Or, in iOS, you might open a database in the app's `Documents` directory: - - NSString *docsPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0]; - NSString *dbPath = [docsPath stringByAppendingPathComponent:@"test.db"]; - FMDatabase *db = [FMDatabase databaseWithPath:dbPath]; - - (For more information on temporary and in-memory databases, read the sqlite documentation on the subject: [http://www.sqlite.org/inmemorydb.html](http://www.sqlite.org/inmemorydb.html)) - - @param inPath Path of database file - - @return `FMDatabase` object if successful; `nil` if failure. - - */ - -+ (instancetype)databaseWithPath:(NSString * _Nullable)inPath; - -/** Create a `FMDatabase` object. - - An `FMDatabase` is created with a path to a SQLite database file. This path can be one of these three: - - 1. A file system URL. The file does not have to exist on disk. If it does not exist, it is created for you. - 2. `nil`. An in-memory database is created. This database will be destroyed with the `FMDatabase` connection is closed. - - For example, to create/open a database in your Mac OS X `tmp` folder: - - FMDatabase *db = [FMDatabase databaseWithPath:@"/tmp/tmp.db"]; - - Or, in iOS, you might open a database in the app's `Documents` directory: - - NSString *docsPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0]; - NSString *dbPath = [docsPath stringByAppendingPathComponent:@"test.db"]; - FMDatabase *db = [FMDatabase databaseWithPath:dbPath]; - - (For more information on temporary and in-memory databases, read the sqlite documentation on the subject: [http://www.sqlite.org/inmemorydb.html](http://www.sqlite.org/inmemorydb.html)) - - @param url The local file URL (not remote URL) of database file - - @return `FMDatabase` object if successful; `nil` if failure. - - */ - -+ (instancetype)databaseWithURL:(NSURL * _Nullable)url; - -/** Initialize a `FMDatabase` object. - - An `FMDatabase` is created with a path to a SQLite database file. This path can be one of these three: - - 1. A file system path. The file does not have to exist on disk. If it does not exist, it is created for you. - 2. An empty string (`@""`). An empty database is created at a temporary location. This database is deleted with the `FMDatabase` connection is closed. - 3. `nil`. An in-memory database is created. This database will be destroyed with the `FMDatabase` connection is closed. - - For example, to create/open a database in your Mac OS X `tmp` folder: - - FMDatabase *db = [FMDatabase databaseWithPath:@"/tmp/tmp.db"]; - - Or, in iOS, you might open a database in the app's `Documents` directory: - - NSString *docsPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0]; - NSString *dbPath = [docsPath stringByAppendingPathComponent:@"test.db"]; - FMDatabase *db = [FMDatabase databaseWithPath:dbPath]; - - (For more information on temporary and in-memory databases, read the sqlite documentation on the subject: [http://www.sqlite.org/inmemorydb.html](http://www.sqlite.org/inmemorydb.html)) - - @param path Path of database file. - - @return `FMDatabase` object if successful; `nil` if failure. - - */ - -- (instancetype)initWithPath:(NSString * _Nullable)path; - -/** Initialize a `FMDatabase` object. - - An `FMDatabase` is created with a local file URL to a SQLite database file. This path can be one of these three: - - 1. A file system URL. The file does not have to exist on disk. If it does not exist, it is created for you. - 2. `nil`. An in-memory database is created. This database will be destroyed with the `FMDatabase` connection is closed. - - For example, to create/open a database in your Mac OS X `tmp` folder: - - FMDatabase *db = [FMDatabase databaseWithPath:@"/tmp/tmp.db"]; - - Or, in iOS, you might open a database in the app's `Documents` directory: - - NSString *docsPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0]; - NSString *dbPath = [docsPath stringByAppendingPathComponent:@"test.db"]; - FMDatabase *db = [FMDatabase databaseWithPath:dbPath]; - - (For more information on temporary and in-memory databases, read the sqlite documentation on the subject: [http://www.sqlite.org/inmemorydb.html](http://www.sqlite.org/inmemorydb.html)) - - @param url The file `NSURL` of database file. - - @return `FMDatabase` object if successful; `nil` if failure. - - */ - -- (instancetype)initWithURL:(NSURL * _Nullable)url; - -///----------------------------------- -/// @name Opening and closing database -///----------------------------------- - -/** Opening a new database connection - - The database is opened for reading and writing, and is created if it does not already exist. - - @return `YES` if successful, `NO` on error. - - @see [sqlite3_open()](http://sqlite.org/c3ref/open.html) - @see openWithFlags: - @see close - */ - -- (BOOL)open; - -/** Opening a new database connection with flags and an optional virtual file system (VFS) - - @param flags one of the following three values, optionally combined with the `SQLITE_OPEN_NOMUTEX`, `SQLITE_OPEN_FULLMUTEX`, `SQLITE_OPEN_SHAREDCACHE`, `SQLITE_OPEN_PRIVATECACHE`, and/or `SQLITE_OPEN_URI` flags: - - `SQLITE_OPEN_READONLY` - - The database is opened in read-only mode. If the database does not already exist, an error is returned. - - `SQLITE_OPEN_READWRITE` - - The database is opened for reading and writing if possible, or reading only if the file is write protected by the operating system. In either case the database must already exist, otherwise an error is returned. - - `SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE` - - The database is opened for reading and writing, and is created if it does not already exist. This is the behavior that is always used for `open` method. - - @return `YES` if successful, `NO` on error. - - @see [sqlite3_open_v2()](http://sqlite.org/c3ref/open.html) - @see open - @see close - */ - -- (BOOL)openWithFlags:(int)flags; - -/** Opening a new database connection with flags and an optional virtual file system (VFS) - - @param flags one of the following three values, optionally combined with the `SQLITE_OPEN_NOMUTEX`, `SQLITE_OPEN_FULLMUTEX`, `SQLITE_OPEN_SHAREDCACHE`, `SQLITE_OPEN_PRIVATECACHE`, and/or `SQLITE_OPEN_URI` flags: - - `SQLITE_OPEN_READONLY` - - The database is opened in read-only mode. If the database does not already exist, an error is returned. - - `SQLITE_OPEN_READWRITE` - - The database is opened for reading and writing if possible, or reading only if the file is write protected by the operating system. In either case the database must already exist, otherwise an error is returned. - - `SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE` - - The database is opened for reading and writing, and is created if it does not already exist. This is the behavior that is always used for `open` method. - - @param vfsName If vfs is given the value is passed to the vfs parameter of sqlite3_open_v2. - - @return `YES` if successful, `NO` on error. - - @see [sqlite3_open_v2()](http://sqlite.org/c3ref/open.html) - @see open - @see close - */ - -- (BOOL)openWithFlags:(int)flags vfs:(NSString * _Nullable)vfsName; - -/** Closing a database connection - - @return `YES` if success, `NO` on error. - - @see [sqlite3_close()](http://sqlite.org/c3ref/close.html) - @see open - @see openWithFlags: - */ - -- (BOOL)close; - -/** Test to see if we have a good connection to the database. - - This will confirm whether: - - - is database open - - if open, it will try a simple SELECT statement and confirm that it succeeds. - - @return `YES` if everything succeeds, `NO` on failure. - */ - -@property (nonatomic, readonly) BOOL goodConnection; - - -///---------------------- -/// @name Perform updates -///---------------------- - -/** Execute single update statement - - This method executes a single SQL update statement (i.e. any SQL that does not return results, such as `UPDATE`, `INSERT`, or `DELETE`. This method employs [`sqlite3_prepare_v2`](http://sqlite.org/c3ref/prepare.html), [`sqlite3_bind`](http://sqlite.org/c3ref/bind_blob.html) to bind values to `?` placeholders in the SQL with the optional list of parameters, and [`sqlite_step`](http://sqlite.org/c3ref/step.html) to perform the update. - - The optional values provided to this method should be objects (e.g. `NSString`, `NSNumber`, `NSNull`, `NSDate`, and `NSData` objects), not fundamental data types (e.g. `int`, `long`, `NSInteger`, etc.). This method automatically handles the aforementioned object types, and all other object types will be interpreted as text values using the object's `description` method. - - @param sql The SQL to be performed, with optional `?` placeholders. - - @param outErr A reference to the `NSError` pointer to be updated with an auto released `NSError` object if an error if an error occurs. If `nil`, no `NSError` object will be returned. - - @param ... Optional parameters to bind to `?` placeholders in the SQL statement. These should be Objective-C objects (e.g. `NSString`, `NSNumber`, etc.), not fundamental C data types (e.g. `int`, `char *`, etc.). - - @return `YES` upon success; `NO` upon failure. If failed, you can call ``, ``, or `` for diagnostic information regarding the failure. - - @see lastError - @see lastErrorCode - @see lastErrorMessage - @see [`sqlite3_bind`](http://sqlite.org/c3ref/bind_blob.html) - */ - -- (BOOL)executeUpdate:(NSString*)sql withErrorAndBindings:(NSError * _Nullable *)outErr, ...; - -/** Execute single update statement - - @see executeUpdate:withErrorAndBindings: - - @warning **Deprecated**: Please use `` instead. - */ - -- (BOOL)update:(NSString*)sql withErrorAndBindings:(NSError * _Nullable*)outErr, ... __deprecated_msg("Use executeUpdate:withErrorAndBindings: instead");; - -/** Execute single update statement - - This method executes a single SQL update statement (i.e. any SQL that does not return results, such as `UPDATE`, `INSERT`, or `DELETE`. This method employs [`sqlite3_prepare_v2`](http://sqlite.org/c3ref/prepare.html), [`sqlite3_bind`](http://sqlite.org/c3ref/bind_blob.html) to bind values to `?` placeholders in the SQL with the optional list of parameters, and [`sqlite_step`](http://sqlite.org/c3ref/step.html) to perform the update. - - The optional values provided to this method should be objects (e.g. `NSString`, `NSNumber`, `NSNull`, `NSDate`, and `NSData` objects), not fundamental data types (e.g. `int`, `long`, `NSInteger`, etc.). This method automatically handles the aforementioned object types, and all other object types will be interpreted as text values using the object's `description` method. - - @param sql The SQL to be performed, with optional `?` placeholders. - - @param ... Optional parameters to bind to `?` placeholders in the SQL statement. These should be Objective-C objects (e.g. `NSString`, `NSNumber`, etc.), not fundamental C data types (e.g. `int`, `char *`, etc.). - - @return `YES` upon success; `NO` upon failure. If failed, you can call ``, ``, or `` for diagnostic information regarding the failure. - - @see lastError - @see lastErrorCode - @see lastErrorMessage - @see [`sqlite3_bind`](http://sqlite.org/c3ref/bind_blob.html) - - @note This technique supports the use of `?` placeholders in the SQL, automatically binding any supplied value parameters to those placeholders. This approach is more robust than techniques that entail using `stringWithFormat` to manually build SQL statements, which can be problematic if the values happened to include any characters that needed to be quoted. - - @note You cannot use this method from Swift due to incompatibilities between Swift and Objective-C variadic implementations. Consider using `` instead. - */ - -- (BOOL)executeUpdate:(NSString*)sql, ...; - -/** Execute single update statement - - This method executes a single SQL update statement (i.e. any SQL that does not return results, such as `UPDATE`, `INSERT`, or `DELETE`. This method employs [`sqlite3_prepare_v2`](http://sqlite.org/c3ref/prepare.html) and [`sqlite_step`](http://sqlite.org/c3ref/step.html) to perform the update. Unlike the other `executeUpdate` methods, this uses printf-style formatters (e.g. `%s`, `%d`, etc.) to build the SQL. Do not use `?` placeholders in the SQL if you use this method. - - @param format The SQL to be performed, with `printf`-style escape sequences. - - @param ... Optional parameters to bind to use in conjunction with the `printf`-style escape sequences in the SQL statement. - - @return `YES` upon success; `NO` upon failure. If failed, you can call ``, ``, or `` for diagnostic information regarding the failure. - - @see executeUpdate: - @see lastError - @see lastErrorCode - @see lastErrorMessage - - @note This method does not technically perform a traditional printf-style replacement. What this method actually does is replace the printf-style percent sequences with a SQLite `?` placeholder, and then bind values to that placeholder. Thus the following command - - [db executeUpdateWithFormat:@"INSERT INTO test (name) VALUES (%@)", @"Gus"]; - - is actually replacing the `%@` with `?` placeholder, and then performing something equivalent to `` - - [db executeUpdate:@"INSERT INTO test (name) VALUES (?)", @"Gus"]; - - There are two reasons why this distinction is important. First, the printf-style escape sequences can only be used where it is permissible to use a SQLite `?` placeholder. You can use it only for values in SQL statements, but not for table names or column names or any other non-value context. This method also cannot be used in conjunction with `pragma` statements and the like. Second, note the lack of quotation marks in the SQL. The `VALUES` clause was _not_ `VALUES ('%@')` (like you might have to do if you built a SQL statement using `NSString` method `stringWithFormat`), but rather simply `VALUES (%@)`. - */ - -- (BOOL)executeUpdateWithFormat:(NSString *)format, ... NS_FORMAT_FUNCTION(1,2); - -/** Execute single update statement - - This method executes a single SQL update statement (i.e. any SQL that does not return results, such as `UPDATE`, `INSERT`, or `DELETE`. This method employs [`sqlite3_prepare_v2`](http://sqlite.org/c3ref/prepare.html) and [`sqlite3_bind`](http://sqlite.org/c3ref/bind_blob.html) binding any `?` placeholders in the SQL with the optional list of parameters. - - The optional values provided to this method should be objects (e.g. `NSString`, `NSNumber`, `NSNull`, `NSDate`, and `NSData` objects), not fundamental data types (e.g. `int`, `long`, `NSInteger`, etc.). This method automatically handles the aforementioned object types, and all other object types will be interpreted as text values using the object's `description` method. - - @param sql The SQL to be performed, with optional `?` placeholders. - - @param arguments A `NSArray` of objects to be used when binding values to the `?` placeholders in the SQL statement. - - @return `YES` upon success; `NO` upon failure. If failed, you can call ``, ``, or `` for diagnostic information regarding the failure. - - @see executeUpdate:values:error: - @see lastError - @see lastErrorCode - @see lastErrorMessage - */ - -- (BOOL)executeUpdate:(NSString*)sql withArgumentsInArray:(NSArray *)arguments; - -/** Execute single update statement - - This method executes a single SQL update statement (i.e. any SQL that does not return results, such as `UPDATE`, `INSERT`, or `DELETE`. This method employs [`sqlite3_prepare_v2`](http://sqlite.org/c3ref/prepare.html) and [`sqlite3_bind`](http://sqlite.org/c3ref/bind_blob.html) binding any `?` placeholders in the SQL with the optional list of parameters. - - The optional values provided to this method should be objects (e.g. `NSString`, `NSNumber`, `NSNull`, `NSDate`, and `NSData` objects), not fundamental data types (e.g. `int`, `long`, `NSInteger`, etc.). This method automatically handles the aforementioned object types, and all other object types will be interpreted as text values using the object's `description` method. - - This is similar to ``, except that this also accepts a pointer to a `NSError` pointer, so that errors can be returned. - - In Swift, this throws errors, as if it were defined as follows: - - `func executeUpdate(sql: String, values: [Any]?) throws -> Bool` - - @param sql The SQL to be performed, with optional `?` placeholders. - - @param values A `NSArray` of objects to be used when binding values to the `?` placeholders in the SQL statement. - - @param error A `NSError` object to receive any error object (if any). - - @return `YES` upon success; `NO` upon failure. If failed, you can call ``, ``, or `` for diagnostic information regarding the failure. - - @see lastError - @see lastErrorCode - @see lastErrorMessage - - */ - -- (BOOL)executeUpdate:(NSString*)sql values:(NSArray * _Nullable)values error:(NSError * _Nullable __autoreleasing *)error; - -/** Execute single update statement - - This method executes a single SQL update statement (i.e. any SQL that does not return results, such as `UPDATE`, `INSERT`, or `DELETE`. This method employs [`sqlite3_prepare_v2`](http://sqlite.org/c3ref/prepare.html) and [`sqlite_step`](http://sqlite.org/c3ref/step.html) to perform the update. Unlike the other `executeUpdate` methods, this uses printf-style formatters (e.g. `%s`, `%d`, etc.) to build the SQL. - - The optional values provided to this method should be objects (e.g. `NSString`, `NSNumber`, `NSNull`, `NSDate`, and `NSData` objects), not fundamental data types (e.g. `int`, `long`, `NSInteger`, etc.). This method automatically handles the aforementioned object types, and all other object types will be interpreted as text values using the object's `description` method. - - @param sql The SQL to be performed, with optional `?` placeholders. - - @param arguments A `NSDictionary` of objects keyed by column names that will be used when binding values to the `?` placeholders in the SQL statement. - - @return `YES` upon success; `NO` upon failure. If failed, you can call ``, ``, or `` for diagnostic information regarding the failure. - - @see lastError - @see lastErrorCode - @see lastErrorMessage -*/ - -- (BOOL)executeUpdate:(NSString*)sql withParameterDictionary:(NSDictionary *)arguments; - - -/** Execute single update statement - - This method executes a single SQL update statement (i.e. any SQL that does not return results, such as `UPDATE`, `INSERT`, or `DELETE`. This method employs [`sqlite3_prepare_v2`](http://sqlite.org/c3ref/prepare.html) and [`sqlite_step`](http://sqlite.org/c3ref/step.html) to perform the update. Unlike the other `executeUpdate` methods, this uses printf-style formatters (e.g. `%s`, `%d`, etc.) to build the SQL. - - The optional values provided to this method should be objects (e.g. `NSString`, `NSNumber`, `NSNull`, `NSDate`, and `NSData` objects), not fundamental data types (e.g. `int`, `long`, `NSInteger`, etc.). This method automatically handles the aforementioned object types, and all other object types will be interpreted as text values using the object's `description` method. - - @param sql The SQL to be performed, with optional `?` placeholders. - - @param args A `va_list` of arguments. - - @return `YES` upon success; `NO` upon failure. If failed, you can call ``, ``, or `` for diagnostic information regarding the failure. - - @see lastError - @see lastErrorCode - @see lastErrorMessage - */ - -- (BOOL)executeUpdate:(NSString*)sql withVAList: (va_list)args; - -/** Execute multiple SQL statements - - This executes a series of SQL statements that are combined in a single string (e.g. the SQL generated by the `sqlite3` command line `.dump` command). This accepts no value parameters, but rather simply expects a single string with multiple SQL statements, each terminated with a semicolon. This uses `sqlite3_exec`. - - @param sql The SQL to be performed - - @return `YES` upon success; `NO` upon failure. If failed, you can call ``, ``, or `` for diagnostic information regarding the failure. - - @see executeStatements:withResultBlock: - @see [sqlite3_exec()](http://sqlite.org/c3ref/exec.html) - - */ - -- (BOOL)executeStatements:(NSString *)sql; - -/** Execute multiple SQL statements with callback handler - - This executes a series of SQL statements that are combined in a single string (e.g. the SQL generated by the `sqlite3` command line `.dump` command). This accepts no value parameters, but rather simply expects a single string with multiple SQL statements, each terminated with a semicolon. This uses `sqlite3_exec`. - - @param sql The SQL to be performed. - @param block A block that will be called for any result sets returned by any SQL statements. - Note, if you supply this block, it must return integer value, zero upon success (this would be a good opportunity to use SQLITE_OK), - non-zero value upon failure (which will stop the bulk execution of the SQL). If a statement returns values, the block will be called with the results from the query in NSDictionary *resultsDictionary. - This may be `nil` if you don't care to receive any results. - - @return `YES` upon success; `NO` upon failure. If failed, you can call ``, - ``, or `` for diagnostic information regarding the failure. - - @see executeStatements: - @see [sqlite3_exec()](http://sqlite.org/c3ref/exec.html) - - */ - -- (BOOL)executeStatements:(NSString *)sql withResultBlock:(__attribute__((noescape)) FMDBExecuteStatementsCallbackBlock _Nullable)block; - -/** Last insert rowid - - Each entry in an SQLite table has a unique 64-bit signed integer key called the "rowid". The rowid is always available as an undeclared column named `ROWID`, `OID`, or `_ROWID_` as long as those names are not also used by explicitly declared columns. If the table has a column of type `INTEGER PRIMARY KEY` then that column is another alias for the rowid. - - This routine returns the rowid of the most recent successful `INSERT` into the database from the database connection in the first argument. As of SQLite version 3.7.7, this routines records the last insert rowid of both ordinary tables and virtual tables. If no successful `INSERT`s have ever occurred on that database connection, zero is returned. - - @return The rowid of the last inserted row. - - @see [sqlite3_last_insert_rowid()](http://sqlite.org/c3ref/last_insert_rowid.html) - - */ - -@property (nonatomic, readonly) int64_t lastInsertRowId; - -/** The number of rows changed by prior SQL statement. - - This function returns the number of database rows that were changed or inserted or deleted by the most recently completed SQL statement on the database connection specified by the first parameter. Only changes that are directly specified by the INSERT, UPDATE, or DELETE statement are counted. - - @return The number of rows changed by prior SQL statement. - - @see [sqlite3_changes()](http://sqlite.org/c3ref/changes.html) - - */ - -@property (nonatomic, readonly) int changes; - - -///------------------------- -/// @name Retrieving results -///------------------------- - -/** Execute select statement - - Executing queries returns an `` object if successful, and `nil` upon failure. Like executing updates, there is a variant that accepts an `NSError **` parameter. Otherwise you should use the `` and `` methods to determine why a query failed. - - In order to iterate through the results of your query, you use a `while()` loop. You also need to "step" (via `<[FMResultSet next]>`) from one record to the other. - - This method employs [`sqlite3_bind`](http://sqlite.org/c3ref/bind_blob.html) for any optional value parameters. This properly escapes any characters that need escape sequences (e.g. quotation marks), which eliminates simple SQL errors as well as protects against SQL injection attacks. This method natively handles `NSString`, `NSNumber`, `NSNull`, `NSDate`, and `NSData` objects. All other object types will be interpreted as text values using the object's `description` method. - - @param sql The SELECT statement to be performed, with optional `?` placeholders. - - @param ... Optional parameters to bind to `?` placeholders in the SQL statement. These should be Objective-C objects (e.g. `NSString`, `NSNumber`, etc.), not fundamental C data types (e.g. `int`, `char *`, etc.). - - @return A `` for the result set upon success; `nil` upon failure. If failed, you can call ``, ``, or `` for diagnostic information regarding the failure. - - @see FMResultSet - @see [`FMResultSet next`](<[FMResultSet next]>) - @see [`sqlite3_bind`](http://sqlite.org/c3ref/bind_blob.html) - - @note You cannot use this method from Swift due to incompatibilities between Swift and Objective-C variadic implementations. Consider using `` instead. - */ - -- (FMResultSet * _Nullable)executeQuery:(NSString*)sql, ...; - -/** Execute select statement - - Executing queries returns an `` object if successful, and `nil` upon failure. Like executing updates, there is a variant that accepts an `NSError **` parameter. Otherwise you should use the `` and `` methods to determine why a query failed. - - In order to iterate through the results of your query, you use a `while()` loop. You also need to "step" (via `<[FMResultSet next]>`) from one record to the other. - - @param format The SQL to be performed, with `printf`-style escape sequences. - - @param ... Optional parameters to bind to use in conjunction with the `printf`-style escape sequences in the SQL statement. - - @return A `` for the result set upon success; `nil` upon failure. If failed, you can call ``, ``, or `` for diagnostic information regarding the failure. - - @see executeQuery: - @see FMResultSet - @see [`FMResultSet next`](<[FMResultSet next]>) - - @note This method does not technically perform a traditional printf-style replacement. What this method actually does is replace the printf-style percent sequences with a SQLite `?` placeholder, and then bind values to that placeholder. Thus the following command - - [db executeQueryWithFormat:@"SELECT * FROM test WHERE name=%@", @"Gus"]; - - is actually replacing the `%@` with `?` placeholder, and then performing something equivalent to `` - - [db executeQuery:@"SELECT * FROM test WHERE name=?", @"Gus"]; - - There are two reasons why this distinction is important. First, the printf-style escape sequences can only be used where it is permissible to use a SQLite `?` placeholder. You can use it only for values in SQL statements, but not for table names or column names or any other non-value context. This method also cannot be used in conjunction with `pragma` statements and the like. Second, note the lack of quotation marks in the SQL. The `WHERE` clause was _not_ `WHERE name='%@'` (like you might have to do if you built a SQL statement using `NSString` method `stringWithFormat`), but rather simply `WHERE name=%@`. - - */ - -- (FMResultSet * _Nullable)executeQueryWithFormat:(NSString*)format, ... NS_FORMAT_FUNCTION(1,2); - -/** Execute select statement - - Executing queries returns an `` object if successful, and `nil` upon failure. Like executing updates, there is a variant that accepts an `NSError **` parameter. Otherwise you should use the `` and `` methods to determine why a query failed. - - In order to iterate through the results of your query, you use a `while()` loop. You also need to "step" (via `<[FMResultSet next]>`) from one record to the other. - - @param sql The SELECT statement to be performed, with optional `?` placeholders. - - @param arguments A `NSArray` of objects to be used when binding values to the `?` placeholders in the SQL statement. - - @return A `` for the result set upon success; `nil` upon failure. If failed, you can call ``, ``, or `` for diagnostic information regarding the failure. - - @see -executeQuery:values:error: - @see FMResultSet - @see [`FMResultSet next`](<[FMResultSet next]>) - */ - -- (FMResultSet * _Nullable)executeQuery:(NSString *)sql withArgumentsInArray:(NSArray *)arguments; - -/** Execute select statement - - Executing queries returns an `` object if successful, and `nil` upon failure. Like executing updates, there is a variant that accepts an `NSError **` parameter. Otherwise you should use the `` and `` methods to determine why a query failed. - - In order to iterate through the results of your query, you use a `while()` loop. You also need to "step" (via `<[FMResultSet next]>`) from one record to the other. - - This is similar to ``, except that this also accepts a pointer to a `NSError` pointer, so that errors can be returned. - - In Swift, this throws errors, as if it were defined as follows: - - `func executeQuery(sql: String, values: [Any]?) throws -> FMResultSet!` - - @param sql The SELECT statement to be performed, with optional `?` placeholders. - - @param values A `NSArray` of objects to be used when binding values to the `?` placeholders in the SQL statement. - - @param error A `NSError` object to receive any error object (if any). - - @return A `` for the result set upon success; `nil` upon failure. If failed, you can call ``, ``, or `` for diagnostic information regarding the failure. - - @see FMResultSet - @see [`FMResultSet next`](<[FMResultSet next]>) - - @note When called from Swift, only use the first two parameters, `sql` and `values`. This but throws the error. - - */ - -- (FMResultSet * _Nullable)executeQuery:(NSString *)sql values:(NSArray * _Nullable)values error:(NSError * _Nullable __autoreleasing *)error; - -/** Execute select statement - - Executing queries returns an `` object if successful, and `nil` upon failure. Like executing updates, there is a variant that accepts an `NSError **` parameter. Otherwise you should use the `` and `` methods to determine why a query failed. - - In order to iterate through the results of your query, you use a `while()` loop. You also need to "step" (via `<[FMResultSet next]>`) from one record to the other. - - @param sql The SELECT statement to be performed, with optional `?` placeholders. - - @param arguments A `NSDictionary` of objects keyed by column names that will be used when binding values to the `?` placeholders in the SQL statement. - - @return A `` for the result set upon success; `nil` upon failure. If failed, you can call ``, ``, or `` for diagnostic information regarding the failure. - - @see FMResultSet - @see [`FMResultSet next`](<[FMResultSet next]>) - */ - -- (FMResultSet * _Nullable)executeQuery:(NSString *)sql withParameterDictionary:(NSDictionary * _Nullable)arguments; - - -// Documentation forthcoming. -- (FMResultSet * _Nullable)executeQuery:(NSString *)sql withVAList:(va_list)args; - -///------------------- -/// @name Transactions -///------------------- - -/** Begin a transaction - - @return `YES` on success; `NO` on failure. If failed, you can call ``, ``, or `` for diagnostic information regarding the failure. - - @see commit - @see rollback - @see beginDeferredTransaction - @see isInTransaction - */ - -- (BOOL)beginTransaction; - -/** Begin a deferred transaction - - @return `YES` on success; `NO` on failure. If failed, you can call ``, ``, or `` for diagnostic information regarding the failure. - - @see commit - @see rollback - @see beginTransaction - @see isInTransaction - */ - -- (BOOL)beginDeferredTransaction; - -/** Commit a transaction - - Commit a transaction that was initiated with either `` or with ``. - - @return `YES` on success; `NO` on failure. If failed, you can call ``, ``, or `` for diagnostic information regarding the failure. - - @see beginTransaction - @see beginDeferredTransaction - @see rollback - @see isInTransaction - */ - -- (BOOL)commit; - -/** Rollback a transaction - - Rollback a transaction that was initiated with either `` or with ``. - - @return `YES` on success; `NO` on failure. If failed, you can call ``, ``, or `` for diagnostic information regarding the failure. - - @see beginTransaction - @see beginDeferredTransaction - @see commit - @see isInTransaction - */ - -- (BOOL)rollback; - -/** Identify whether currently in a transaction or not - - @see beginTransaction - @see beginDeferredTransaction - @see commit - @see rollback - */ - -@property (nonatomic, readonly) BOOL isInTransaction; - -- (BOOL)inTransaction __deprecated_msg("Use isInTransaction property instead"); - - -///---------------------------------------- -/// @name Cached statements and result sets -///---------------------------------------- - -/** Clear cached statements */ - -- (void)clearCachedStatements; - -/** Close all open result sets */ - -- (void)closeOpenResultSets; - -/** Whether database has any open result sets - - @return `YES` if there are open result sets; `NO` if not. - */ - -@property (nonatomic, readonly) BOOL hasOpenResultSets; - -/** Whether should cache statements or not - */ - -@property (nonatomic) BOOL shouldCacheStatements; - -/** Interupt pending database operation - - This method causes any pending database operation to abort and return at its earliest opportunity - - @return `YES` on success; `NO` on failure. If failed, you can call ``, ``, or `` for diagnostic information regarding the failure. - - */ - -- (BOOL)interrupt; - -///------------------------- -/// @name Encryption methods -///------------------------- - -/** Set encryption key. - - @param key The key to be used. - - @return `YES` if success, `NO` on error. - - @see https://www.zetetic.net/sqlcipher/ - - @warning You need to have purchased the sqlite encryption extensions for this method to work. - */ - -- (BOOL)setKey:(NSString*)key; - -/** Reset encryption key - - @param key The key to be used. - - @return `YES` if success, `NO` on error. - - @see https://www.zetetic.net/sqlcipher/ - - @warning You need to have purchased the sqlite encryption extensions for this method to work. - */ - -- (BOOL)rekey:(NSString*)key; - -/** Set encryption key using `keyData`. - - @param keyData The `NSData` to be used. - - @return `YES` if success, `NO` on error. - - @see https://www.zetetic.net/sqlcipher/ - - @warning You need to have purchased the sqlite encryption extensions for this method to work. - */ - -- (BOOL)setKeyWithData:(NSData *)keyData; - -/** Reset encryption key using `keyData`. - - @param keyData The `NSData` to be used. - - @return `YES` if success, `NO` on error. - - @see https://www.zetetic.net/sqlcipher/ - - @warning You need to have purchased the sqlite encryption extensions for this method to work. - */ - -- (BOOL)rekeyWithData:(NSData *)keyData; - - -///------------------------------ -/// @name General inquiry methods -///------------------------------ - -/** The path of the database file - */ - -@property (nonatomic, readonly, nullable) NSString *databasePath; - -/** The file URL of the database file. - */ - -@property (nonatomic, readonly, nullable) NSURL *databaseURL; - -/** The underlying SQLite handle - - @return The `sqlite3` pointer. - - */ - -@property (nonatomic, readonly) void *sqliteHandle; - - -///----------------------------- -/// @name Retrieving error codes -///----------------------------- - -/** Last error message - - Returns the English-language text that describes the most recent failed SQLite API call associated with a database connection. If a prior API call failed but the most recent API call succeeded, this return value is undefined. - - @return `NSString` of the last error message. - - @see [sqlite3_errmsg()](http://sqlite.org/c3ref/errcode.html) - @see lastErrorCode - @see lastError - - */ - -- (NSString*)lastErrorMessage; - -/** Last error code - - Returns the numeric result code or extended result code for the most recent failed SQLite API call associated with a database connection. If a prior API call failed but the most recent API call succeeded, this return value is undefined. - - @return Integer value of the last error code. - - @see [sqlite3_errcode()](http://sqlite.org/c3ref/errcode.html) - @see lastErrorMessage - @see lastError - - */ - -- (int)lastErrorCode; - -/** Last extended error code - - Returns the numeric extended result code for the most recent failed SQLite API call associated with a database connection. If a prior API call failed but the most recent API call succeeded, this return value is undefined. - - @return Integer value of the last extended error code. - - @see [sqlite3_errcode()](http://sqlite.org/c3ref/errcode.html) - @see [2. Primary Result Codes versus Extended Result Codes](http://sqlite.org/rescode.html#primary_result_codes_versus_extended_result_codes) - @see [5. Extended Result Code List](http://sqlite.org/rescode.html#extrc) - @see lastErrorMessage - @see lastError - - */ - -- (int)lastExtendedErrorCode; - -/** Had error - - @return `YES` if there was an error, `NO` if no error. - - @see lastError - @see lastErrorCode - @see lastErrorMessage - - */ - -- (BOOL)hadError; - -/** Last error - - @return `NSError` representing the last error. - - @see lastErrorCode - @see lastErrorMessage - - */ - -- (NSError *)lastError; - - -// description forthcoming -@property (nonatomic) NSTimeInterval maxBusyRetryTimeInterval; - - -///------------------ -/// @name Save points -///------------------ - -/** Start save point - - @param name Name of save point. - - @param outErr A `NSError` object to receive any error object (if any). - - @return `YES` on success; `NO` on failure. If failed, you can call ``, ``, or `` for diagnostic information regarding the failure. - - @see releaseSavePointWithName:error: - @see rollbackToSavePointWithName:error: - */ - -- (BOOL)startSavePointWithName:(NSString*)name error:(NSError * _Nullable *)outErr; - -/** Release save point - - @param name Name of save point. - - @param outErr A `NSError` object to receive any error object (if any). - - @return `YES` on success; `NO` on failure. If failed, you can call ``, ``, or `` for diagnostic information regarding the failure. - - @see startSavePointWithName:error: - @see rollbackToSavePointWithName:error: - - */ - -- (BOOL)releaseSavePointWithName:(NSString*)name error:(NSError * _Nullable *)outErr; - -/** Roll back to save point - - @param name Name of save point. - @param outErr A `NSError` object to receive any error object (if any). - - @return `YES` on success; `NO` on failure. If failed, you can call ``, ``, or `` for diagnostic information regarding the failure. - - @see startSavePointWithName:error: - @see releaseSavePointWithName:error: - - */ - -- (BOOL)rollbackToSavePointWithName:(NSString*)name error:(NSError * _Nullable *)outErr; - -/** Start save point - - @param block Block of code to perform from within save point. - - @return The NSError corresponding to the error, if any. If no error, returns `nil`. - - @see startSavePointWithName:error: - @see releaseSavePointWithName:error: - @see rollbackToSavePointWithName:error: - - */ - -- (NSError * _Nullable)inSavePoint:(__attribute__((noescape)) void (^)(BOOL *rollback))block; - -///---------------------------- -/// @name SQLite library status -///---------------------------- - -/** Test to see if the library is threadsafe - - @return `NO` if and only if SQLite was compiled with mutexing code omitted due to the SQLITE_THREADSAFE compile-time option being set to 0. - - @see [sqlite3_threadsafe()](http://sqlite.org/c3ref/threadsafe.html) - */ - -+ (BOOL)isSQLiteThreadSafe; - -/** Run-time library version numbers - - @return The sqlite library version string. - - @see [sqlite3_libversion()](http://sqlite.org/c3ref/libversion.html) - */ - -+ (NSString*)sqliteLibVersion; - - -+ (NSString*)FMDBUserVersion; - -+ (SInt32)FMDBVersion; - - -///------------------------ -/// @name Make SQL function -///------------------------ - -/** Adds SQL functions or aggregates or to redefine the behavior of existing SQL functions or aggregates. - - For example: - - [db makeFunctionNamed:@"RemoveDiacritics" arguments:1 block:^(void *context, int argc, void **argv) { - SqliteValueType type = [self.db valueType:argv[0]]; - if (type == SqliteValueTypeNull) { - [self.db resultNullInContext:context]; - return; - } - if (type != SqliteValueTypeText) { - [self.db resultError:@"Expected text" context:context]; - return; - } - NSString *string = [self.db valueString:argv[0]]; - NSString *result = [string stringByFoldingWithOptions:NSDiacriticInsensitiveSearch locale:nil]; - [self.db resultString:result context:context]; - }]; - - FMResultSet *rs = [db executeQuery:@"SELECT * FROM employees WHERE RemoveDiacritics(first_name) LIKE 'jose'"]; - NSAssert(rs, @"Error %@", [db lastErrorMessage]); - - @param name Name of function. - - @param arguments Maximum number of parameters. - - @param block The block of code for the function. - - @see [sqlite3_create_function()](http://sqlite.org/c3ref/create_function.html) - */ - -- (void)makeFunctionNamed:(NSString *)name arguments:(int)arguments block:(void (^)(void *context, int argc, void * _Nonnull * _Nonnull argv))block; - -- (void)makeFunctionNamed:(NSString *)name maximumArguments:(int)count withBlock:(void (^)(void *context, int argc, void * _Nonnull * _Nonnull argv))block __deprecated_msg("Use makeFunctionNamed:arguments:block:"); - -typedef NS_ENUM(int, SqliteValueType) { - SqliteValueTypeInteger = 1, - SqliteValueTypeFloat = 2, - SqliteValueTypeText = 3, - SqliteValueTypeBlob = 4, - SqliteValueTypeNull = 5 -}; - -- (SqliteValueType)valueType:(void *)argv; - -/** - Get integer value of parameter in custom function. - - @param value The argument whose value to return. - @return The integer value. - - @see makeFunctionNamed:arguments:block: - */ -- (int)valueInt:(void *)value; - -/** - Get long value of parameter in custom function. - - @param value The argument whose value to return. - @return The long value. - - @see makeFunctionNamed:arguments:block: - */ -- (long long)valueLong:(void *)value; - -/** - Get double value of parameter in custom function. - - @param value The argument whose value to return. - @return The double value. - - @see makeFunctionNamed:arguments:block: - */ -- (double)valueDouble:(void *)value; - -/** - Get `NSData` value of parameter in custom function. - - @param value The argument whose value to return. - @return The data object. - - @see makeFunctionNamed:arguments:block: - */ -- (NSData * _Nullable)valueData:(void *)value; - -/** - Get string value of parameter in custom function. - - @param value The argument whose value to return. - @return The string value. - - @see makeFunctionNamed:arguments:block: - */ -- (NSString * _Nullable)valueString:(void *)value; - -/** - Return null value from custom function. - - @param context The context to which the null value will be returned. - - @see makeFunctionNamed:arguments:block: - */ -- (void)resultNullInContext:(void *)context NS_SWIFT_NAME(resultNull(context:)); - -/** - Return integer value from custom function. - - @param value The integer value to be returned. - @param context The context to which the value will be returned. - - @see makeFunctionNamed:arguments:block: - */ -- (void)resultInt:(int) value context:(void *)context; - -/** - Return long value from custom function. - - @param value The long value to be returned. - @param context The context to which the value will be returned. - - @see makeFunctionNamed:arguments:block: - */ -- (void)resultLong:(long long)value context:(void *)context; - -/** - Return double value from custom function. - - @param value The double value to be returned. - @param context The context to which the value will be returned. - - @see makeFunctionNamed:arguments:block: - */ -- (void)resultDouble:(double)value context:(void *)context; - -/** - Return `NSData` object from custom function. - - @param data The `NSData` object to be returned. - @param context The context to which the value will be returned. - - @see makeFunctionNamed:arguments:block: - */ -- (void)resultData:(NSData *)data context:(void *)context; - -/** - Return string value from custom function. - - @param value The string value to be returned. - @param context The context to which the value will be returned. - - @see makeFunctionNamed:arguments:block: - */ -- (void)resultString:(NSString *)value context:(void *)context; - -/** - Return error string from custom function. - - @param error The error string to be returned. - @param context The context to which the error will be returned. - - @see makeFunctionNamed:arguments:block: - */ -- (void)resultError:(NSString *)error context:(void *)context; - -/** - Return error code from custom function. - - @param errorCode The integer error code to be returned. - @param context The context to which the error will be returned. - - @see makeFunctionNamed:arguments:block: - */ -- (void)resultErrorCode:(int)errorCode context:(void *)context; - -/** - Report memory error in custom function. - - @param context The context to which the error will be returned. - - @see makeFunctionNamed:arguments:block: - */ -- (void)resultErrorNoMemoryInContext:(void *)context NS_SWIFT_NAME(resultErrorNoMemory(context:)); - -/** - Report that string or BLOB is too long to represent in custom function. - - @param context The context to which the error will be returned. - - @see makeFunctionNamed:arguments:block: - */ -- (void)resultErrorTooBigInContext:(void *)context NS_SWIFT_NAME(resultErrorTooBig(context:)); - -///--------------------- -/// @name Date formatter -///--------------------- - -/** Generate an `NSDateFormatter` that won't be broken by permutations of timezones or locales. - - Use this method to generate values to set the dateFormat property. - - Example: - - myDB.dateFormat = [FMDatabase storeableDateFormat:@"yyyy-MM-dd HH:mm:ss"]; - - @param format A valid NSDateFormatter format string. - - @return A `NSDateFormatter` that can be used for converting dates to strings and vice versa. - - @see hasDateFormatter - @see setDateFormat: - @see dateFromString: - @see stringFromDate: - @see storeableDateFormat: - - @warning Note that `NSDateFormatter` is not thread-safe, so the formatter generated by this method should be assigned to only one FMDB instance and should not be used for other purposes. - - */ - -+ (NSDateFormatter *)storeableDateFormat:(NSString *)format; - -/** Test whether the database has a date formatter assigned. - - @return `YES` if there is a date formatter; `NO` if not. - - @see hasDateFormatter - @see setDateFormat: - @see dateFromString: - @see stringFromDate: - @see storeableDateFormat: - */ - -- (BOOL)hasDateFormatter; - -/** Set to a date formatter to use string dates with sqlite instead of the default UNIX timestamps. - - @param format Set to nil to use UNIX timestamps. Defaults to nil. Should be set using a formatter generated using FMDatabase::storeableDateFormat. - - @see hasDateFormatter - @see setDateFormat: - @see dateFromString: - @see stringFromDate: - @see storeableDateFormat: - - @warning Note there is no direct getter for the `NSDateFormatter`, and you should not use the formatter you pass to FMDB for other purposes, as `NSDateFormatter` is not thread-safe. - */ - -- (void)setDateFormat:(NSDateFormatter *)format; - -/** Convert the supplied NSString to NSDate, using the current database formatter. - - @param s `NSString` to convert to `NSDate`. - - @return The `NSDate` object; or `nil` if no formatter is set. - - @see hasDateFormatter - @see setDateFormat: - @see dateFromString: - @see stringFromDate: - @see storeableDateFormat: - */ - -- (NSDate * _Nullable)dateFromString:(NSString *)s; - -/** Convert the supplied NSDate to NSString, using the current database formatter. - - @param date `NSDate` of date to convert to `NSString`. - - @return The `NSString` representation of the date; `nil` if no formatter is set. - - @see hasDateFormatter - @see setDateFormat: - @see dateFromString: - @see stringFromDate: - @see storeableDateFormat: - */ - -- (NSString *)stringFromDate:(NSDate *)date; - -@end - - -/** Objective-C wrapper for `sqlite3_stmt` - - This is a wrapper for a SQLite `sqlite3_stmt`. Generally when using FMDB you will not need to interact directly with `FMStatement`, but rather with `` and `` only. - - ### See also - - - `` - - `` - - [`sqlite3_stmt`](http://www.sqlite.org/c3ref/stmt.html) - */ - -@interface FMStatement : NSObject { - void *_statement; - NSString *_query; - long _useCount; - BOOL _inUse; -} - -///----------------- -/// @name Properties -///----------------- - -/** Usage count */ - -@property (atomic, assign) long useCount; - -/** SQL statement */ - -@property (atomic, retain) NSString *query; - -/** SQLite sqlite3_stmt - - @see [`sqlite3_stmt`](http://www.sqlite.org/c3ref/stmt.html) - */ - -@property (atomic, assign) void *statement; - -/** Indication of whether the statement is in use */ - -@property (atomic, assign) BOOL inUse; - -///---------------------------- -/// @name Closing and Resetting -///---------------------------- - -/** Close statement */ - -- (void)close; - -/** Reset statement */ - -- (void)reset; - -@end - -#pragma clang diagnostic pop - -NS_ASSUME_NONNULL_END diff --git a/lib/ios/AirMaps/fmdb/FMDatabase.m b/lib/ios/AirMaps/fmdb/FMDatabase.m deleted file mode 100644 index 493e772ea..000000000 --- a/lib/ios/AirMaps/fmdb/FMDatabase.m +++ /dev/null @@ -1,1596 +0,0 @@ -#import "FMDatabase.h" -#import "unistd.h" -#import - -#if FMDB_SQLITE_STANDALONE -#import -#else -#import -#endif - -@interface FMDatabase () { - void* _db; - BOOL _isExecutingStatement; - NSTimeInterval _startBusyRetryTime; - - NSMutableSet *_openResultSets; - NSMutableSet *_openFunctions; - - NSDateFormatter *_dateFormat; -} - -NS_ASSUME_NONNULL_BEGIN - -- (FMResultSet * _Nullable)executeQuery:(NSString *)sql withArgumentsInArray:(NSArray * _Nullable)arrayArgs orDictionary:(NSDictionary * _Nullable)dictionaryArgs orVAList:(va_list)args; -- (BOOL)executeUpdate:(NSString *)sql error:(NSError * _Nullable *)outErr withArgumentsInArray:(NSArray * _Nullable)arrayArgs orDictionary:(NSDictionary * _Nullable)dictionaryArgs orVAList:(va_list)args; - -NS_ASSUME_NONNULL_END - -@end - -@implementation FMDatabase - -// Because these two properties have all of their accessor methods implemented, -// we have to synthesize them to get the corresponding ivars. The rest of the -// properties have their ivars synthesized automatically for us. - -@synthesize shouldCacheStatements = _shouldCacheStatements; -@synthesize maxBusyRetryTimeInterval = _maxBusyRetryTimeInterval; - -#pragma mark FMDatabase instantiation and deallocation - -+ (instancetype)databaseWithPath:(NSString *)aPath { - return FMDBReturnAutoreleased([[self alloc] initWithPath:aPath]); -} - -+ (instancetype)databaseWithURL:(NSURL *)url { - return FMDBReturnAutoreleased([[self alloc] initWithURL:url]); -} - -- (instancetype)init { - return [self initWithPath:nil]; -} - -- (instancetype)initWithURL:(NSURL *)url { - return [self initWithPath:url.path]; -} - -- (instancetype)initWithPath:(NSString *)path { - - assert(sqlite3_threadsafe()); // whoa there big boy- gotta make sure sqlite it happy with what we're going to do. - - self = [super init]; - - if (self) { - _databasePath = [path copy]; - _openResultSets = [[NSMutableSet alloc] init]; - _db = nil; - _logsErrors = YES; - _crashOnErrors = NO; - _maxBusyRetryTimeInterval = 2; - } - - return self; -} - -#if ! __has_feature(objc_arc) -- (void)finalize { - [self close]; - [super finalize]; -} -#endif - -- (void)dealloc { - [self close]; - FMDBRelease(_openResultSets); - FMDBRelease(_cachedStatements); - FMDBRelease(_dateFormat); - FMDBRelease(_databasePath); - FMDBRelease(_openFunctions); - -#if ! __has_feature(objc_arc) - [super dealloc]; -#endif -} - -- (NSURL *)databaseURL { - return _databasePath ? [NSURL fileURLWithPath:_databasePath] : nil; -} - -+ (NSString*)FMDBUserVersion { - return @"2.7.2"; -} - -// returns 0x0240 for version 2.4. This makes it super easy to do things like: -// /* need to make sure to do X with FMDB version 2.4 or later */ -// if ([FMDatabase FMDBVersion] >= 0x0240) { … } - -+ (SInt32)FMDBVersion { - - // we go through these hoops so that we only have to change the version number in a single spot. - static dispatch_once_t once; - static SInt32 FMDBVersionVal = 0; - - dispatch_once(&once, ^{ - NSString *prodVersion = [self FMDBUserVersion]; - - if ([[prodVersion componentsSeparatedByString:@"."] count] < 3) { - prodVersion = [prodVersion stringByAppendingString:@".0"]; - } - - NSString *junk = [prodVersion stringByReplacingOccurrencesOfString:@"." withString:@""]; - - char *e = nil; - FMDBVersionVal = (int) strtoul([junk UTF8String], &e, 16); - - }); - - return FMDBVersionVal; -} - -#pragma mark SQLite information - -+ (NSString*)sqliteLibVersion { - return [NSString stringWithFormat:@"%s", sqlite3_libversion()]; -} - -+ (BOOL)isSQLiteThreadSafe { - // make sure to read the sqlite headers on this guy! - return sqlite3_threadsafe() != 0; -} - -- (void*)sqliteHandle { - return _db; -} - -- (const char*)sqlitePath { - - if (!_databasePath) { - return ":memory:"; - } - - if ([_databasePath length] == 0) { - return ""; // this creates a temporary database (it's an sqlite thing). - } - - return [_databasePath fileSystemRepresentation]; - -} - -#pragma mark Open and close database - -- (BOOL)open { - if (_db) { - return YES; - } - - int err = sqlite3_open([self sqlitePath], (sqlite3**)&_db ); - if(err != SQLITE_OK) { - NSLog(@"error opening!: %d", err); - return NO; - } - - if (_maxBusyRetryTimeInterval > 0.0) { - // set the handler - [self setMaxBusyRetryTimeInterval:_maxBusyRetryTimeInterval]; - } - - - return YES; -} - -- (BOOL)openWithFlags:(int)flags { - return [self openWithFlags:flags vfs:nil]; -} -- (BOOL)openWithFlags:(int)flags vfs:(NSString *)vfsName { -#if SQLITE_VERSION_NUMBER >= 3005000 - if (_db) { - return YES; - } - - int err = sqlite3_open_v2([self sqlitePath], (sqlite3**)&_db, flags, [vfsName UTF8String]); - if(err != SQLITE_OK) { - NSLog(@"error opening!: %d", err); - return NO; - } - - if (_maxBusyRetryTimeInterval > 0.0) { - // set the handler - [self setMaxBusyRetryTimeInterval:_maxBusyRetryTimeInterval]; - } - - return YES; -#else - NSLog(@"openWithFlags requires SQLite 3.5"); - return NO; -#endif -} - - -- (BOOL)close { - - [self clearCachedStatements]; - [self closeOpenResultSets]; - - if (!_db) { - return YES; - } - - int rc; - BOOL retry; - BOOL triedFinalizingOpenStatements = NO; - - do { - retry = NO; - rc = sqlite3_close(_db); - if (SQLITE_BUSY == rc || SQLITE_LOCKED == rc) { - if (!triedFinalizingOpenStatements) { - triedFinalizingOpenStatements = YES; - sqlite3_stmt *pStmt; - while ((pStmt = sqlite3_next_stmt(_db, nil)) !=0) { - NSLog(@"Closing leaked statement"); - sqlite3_finalize(pStmt); - retry = YES; - } - } - } - else if (SQLITE_OK != rc) { - NSLog(@"error closing!: %d", rc); - } - } - while (retry); - - _db = nil; - return YES; -} - -#pragma mark Busy handler routines - -// NOTE: appledoc seems to choke on this function for some reason; -// so when generating documentation, you might want to ignore the -// .m files so that it only documents the public interfaces outlined -// in the .h files. -// -// This is a known appledoc bug that it has problems with C functions -// within a class implementation, but for some reason, only this -// C function causes problems; the rest don't. Anyway, ignoring the .m -// files with appledoc will prevent this problem from occurring. - -static int FMDBDatabaseBusyHandler(void *f, int count) { - FMDatabase *self = (__bridge FMDatabase*)f; - - if (count == 0) { - self->_startBusyRetryTime = [NSDate timeIntervalSinceReferenceDate]; - return 1; - } - - NSTimeInterval delta = [NSDate timeIntervalSinceReferenceDate] - (self->_startBusyRetryTime); - - if (delta < [self maxBusyRetryTimeInterval]) { - int requestedSleepInMillseconds = (int) arc4random_uniform(50) + 50; - int actualSleepInMilliseconds = sqlite3_sleep(requestedSleepInMillseconds); - if (actualSleepInMilliseconds != requestedSleepInMillseconds) { - NSLog(@"WARNING: Requested sleep of %i milliseconds, but SQLite returned %i. Maybe SQLite wasn't built with HAVE_USLEEP=1?", requestedSleepInMillseconds, actualSleepInMilliseconds); - } - return 1; - } - - return 0; -} - -- (void)setMaxBusyRetryTimeInterval:(NSTimeInterval)timeout { - - _maxBusyRetryTimeInterval = timeout; - - if (!_db) { - return; - } - - if (timeout > 0) { - sqlite3_busy_handler(_db, &FMDBDatabaseBusyHandler, (__bridge void *)(self)); - } - else { - // turn it off otherwise - sqlite3_busy_handler(_db, nil, nil); - } -} - -- (NSTimeInterval)maxBusyRetryTimeInterval { - return _maxBusyRetryTimeInterval; -} - - -// we no longer make busyRetryTimeout public -// but for folks who don't bother noticing that the interface to FMDatabase changed, -// we'll still implement the method so they don't get suprise crashes -- (int)busyRetryTimeout { - NSLog(@"%s:%d", __FUNCTION__, __LINE__); - NSLog(@"FMDB: busyRetryTimeout no longer works, please use maxBusyRetryTimeInterval"); - return -1; -} - -- (void)setBusyRetryTimeout:(int)i { -#pragma unused(i) - NSLog(@"%s:%d", __FUNCTION__, __LINE__); - NSLog(@"FMDB: setBusyRetryTimeout does nothing, please use setMaxBusyRetryTimeInterval:"); -} - -#pragma mark Result set functions - -- (BOOL)hasOpenResultSets { - return [_openResultSets count] > 0; -} - -- (void)closeOpenResultSets { - - //Copy the set so we don't get mutation errors - NSSet *openSetCopy = FMDBReturnAutoreleased([_openResultSets copy]); - for (NSValue *rsInWrappedInATastyValueMeal in openSetCopy) { - FMResultSet *rs = (FMResultSet *)[rsInWrappedInATastyValueMeal pointerValue]; - - [rs setParentDB:nil]; - [rs close]; - - [_openResultSets removeObject:rsInWrappedInATastyValueMeal]; - } -} - -- (void)resultSetDidClose:(FMResultSet *)resultSet { - NSValue *setValue = [NSValue valueWithNonretainedObject:resultSet]; - - [_openResultSets removeObject:setValue]; -} - -#pragma mark Cached statements - -- (void)clearCachedStatements { - - for (NSMutableSet *statements in [_cachedStatements objectEnumerator]) { - for (FMStatement *statement in [statements allObjects]) { - [statement close]; - } - } - - [_cachedStatements removeAllObjects]; -} - -- (FMStatement*)cachedStatementForQuery:(NSString*)query { - - NSMutableSet* statements = [_cachedStatements objectForKey:query]; - - return [[statements objectsPassingTest:^BOOL(FMStatement* statement, BOOL *stop) { - - *stop = ![statement inUse]; - return *stop; - - }] anyObject]; -} - - -- (void)setCachedStatement:(FMStatement*)statement forQuery:(NSString*)query { - - query = [query copy]; // in case we got handed in a mutable string... - [statement setQuery:query]; - - NSMutableSet* statements = [_cachedStatements objectForKey:query]; - if (!statements) { - statements = [NSMutableSet set]; - } - - [statements addObject:statement]; - - [_cachedStatements setObject:statements forKey:query]; - - FMDBRelease(query); -} - -#pragma mark Key routines - -- (BOOL)rekey:(NSString*)key { - NSData *keyData = [NSData dataWithBytes:(void *)[key UTF8String] length:(NSUInteger)strlen([key UTF8String])]; - - return [self rekeyWithData:keyData]; -} - -- (BOOL)rekeyWithData:(NSData *)keyData { -#ifdef SQLITE_HAS_CODEC - if (!keyData) { - return NO; - } - - int rc = sqlite3_rekey(_db, [keyData bytes], (int)[keyData length]); - - if (rc != SQLITE_OK) { - NSLog(@"error on rekey: %d", rc); - NSLog(@"%@", [self lastErrorMessage]); - } - - return (rc == SQLITE_OK); -#else -#pragma unused(keyData) - return NO; -#endif -} - -- (BOOL)setKey:(NSString*)key { - NSData *keyData = [NSData dataWithBytes:[key UTF8String] length:(NSUInteger)strlen([key UTF8String])]; - - return [self setKeyWithData:keyData]; -} - -- (BOOL)setKeyWithData:(NSData *)keyData { -#ifdef SQLITE_HAS_CODEC - if (!keyData) { - return NO; - } - - int rc = sqlite3_key(_db, [keyData bytes], (int)[keyData length]); - - return (rc == SQLITE_OK); -#else -#pragma unused(keyData) - return NO; -#endif -} - -#pragma mark Date routines - -+ (NSDateFormatter *)storeableDateFormat:(NSString *)format { - - NSDateFormatter *result = FMDBReturnAutoreleased([[NSDateFormatter alloc] init]); - result.dateFormat = format; - result.timeZone = [NSTimeZone timeZoneForSecondsFromGMT:0]; - result.locale = FMDBReturnAutoreleased([[NSLocale alloc] initWithLocaleIdentifier:@"en_US"]); - return result; -} - - -- (BOOL)hasDateFormatter { - return _dateFormat != nil; -} - -- (void)setDateFormat:(NSDateFormatter *)format { - FMDBAutorelease(_dateFormat); - _dateFormat = FMDBReturnRetained(format); -} - -- (NSDate *)dateFromString:(NSString *)s { - return [_dateFormat dateFromString:s]; -} - -- (NSString *)stringFromDate:(NSDate *)date { - return [_dateFormat stringFromDate:date]; -} - -#pragma mark State of database - -- (BOOL)goodConnection { - - if (!_db) { - return NO; - } - - FMResultSet *rs = [self executeQuery:@"select name from sqlite_master where type='table'"]; - - if (rs) { - [rs close]; - return YES; - } - - return NO; -} - -- (void)warnInUse { - NSLog(@"The FMDatabase %@ is currently in use.", self); - -#ifndef NS_BLOCK_ASSERTIONS - if (_crashOnErrors) { - NSAssert(false, @"The FMDatabase %@ is currently in use.", self); - abort(); - } -#endif -} - -- (BOOL)databaseExists { - - if (!_db) { - - NSLog(@"The FMDatabase %@ is not open.", self); - -#ifndef NS_BLOCK_ASSERTIONS - if (_crashOnErrors) { - NSAssert(false, @"The FMDatabase %@ is not open.", self); - abort(); - } -#endif - - return NO; - } - - return YES; -} - -#pragma mark Error routines - -- (NSString *)lastErrorMessage { - return [NSString stringWithUTF8String:sqlite3_errmsg(_db)]; -} - -- (BOOL)hadError { - int lastErrCode = [self lastErrorCode]; - - return (lastErrCode > SQLITE_OK && lastErrCode < SQLITE_ROW); -} - -- (int)lastErrorCode { - return sqlite3_errcode(_db); -} - -- (int)lastExtendedErrorCode { - return sqlite3_extended_errcode(_db); -} - -- (NSError*)errorWithMessage:(NSString *)message { - NSDictionary* errorMessage = [NSDictionary dictionaryWithObject:message forKey:NSLocalizedDescriptionKey]; - - return [NSError errorWithDomain:@"FMDatabase" code:sqlite3_errcode(_db) userInfo:errorMessage]; -} - -- (NSError*)lastError { - return [self errorWithMessage:[self lastErrorMessage]]; -} - -#pragma mark Update information routines - -- (sqlite_int64)lastInsertRowId { - - if (_isExecutingStatement) { - [self warnInUse]; - return NO; - } - - _isExecutingStatement = YES; - - sqlite_int64 ret = sqlite3_last_insert_rowid(_db); - - _isExecutingStatement = NO; - - return ret; -} - -- (int)changes { - if (_isExecutingStatement) { - [self warnInUse]; - return 0; - } - - _isExecutingStatement = YES; - - int ret = sqlite3_changes(_db); - - _isExecutingStatement = NO; - - return ret; -} - -#pragma mark SQL manipulation - -- (void)bindObject:(id)obj toColumn:(int)idx inStatement:(sqlite3_stmt*)pStmt { - - if ((!obj) || ((NSNull *)obj == [NSNull null])) { - sqlite3_bind_null(pStmt, idx); - } - - // FIXME - someday check the return codes on these binds. - else if ([obj isKindOfClass:[NSData class]]) { - const void *bytes = [obj bytes]; - if (!bytes) { - // it's an empty NSData object, aka [NSData data]. - // Don't pass a NULL pointer, or sqlite will bind a SQL null instead of a blob. - bytes = ""; - } - sqlite3_bind_blob(pStmt, idx, bytes, (int)[obj length], SQLITE_STATIC); - } - else if ([obj isKindOfClass:[NSDate class]]) { - if (self.hasDateFormatter) - sqlite3_bind_text(pStmt, idx, [[self stringFromDate:obj] UTF8String], -1, SQLITE_STATIC); - else - sqlite3_bind_double(pStmt, idx, [obj timeIntervalSince1970]); - } - else if ([obj isKindOfClass:[NSNumber class]]) { - - if (strcmp([obj objCType], @encode(char)) == 0) { - sqlite3_bind_int(pStmt, idx, [obj charValue]); - } - else if (strcmp([obj objCType], @encode(unsigned char)) == 0) { - sqlite3_bind_int(pStmt, idx, [obj unsignedCharValue]); - } - else if (strcmp([obj objCType], @encode(short)) == 0) { - sqlite3_bind_int(pStmt, idx, [obj shortValue]); - } - else if (strcmp([obj objCType], @encode(unsigned short)) == 0) { - sqlite3_bind_int(pStmt, idx, [obj unsignedShortValue]); - } - else if (strcmp([obj objCType], @encode(int)) == 0) { - sqlite3_bind_int(pStmt, idx, [obj intValue]); - } - else if (strcmp([obj objCType], @encode(unsigned int)) == 0) { - sqlite3_bind_int64(pStmt, idx, (long long)[obj unsignedIntValue]); - } - else if (strcmp([obj objCType], @encode(long)) == 0) { - sqlite3_bind_int64(pStmt, idx, [obj longValue]); - } - else if (strcmp([obj objCType], @encode(unsigned long)) == 0) { - sqlite3_bind_int64(pStmt, idx, (long long)[obj unsignedLongValue]); - } - else if (strcmp([obj objCType], @encode(long long)) == 0) { - sqlite3_bind_int64(pStmt, idx, [obj longLongValue]); - } - else if (strcmp([obj objCType], @encode(unsigned long long)) == 0) { - sqlite3_bind_int64(pStmt, idx, (long long)[obj unsignedLongLongValue]); - } - else if (strcmp([obj objCType], @encode(float)) == 0) { - sqlite3_bind_double(pStmt, idx, [obj floatValue]); - } - else if (strcmp([obj objCType], @encode(double)) == 0) { - sqlite3_bind_double(pStmt, idx, [obj doubleValue]); - } - else if (strcmp([obj objCType], @encode(BOOL)) == 0) { - sqlite3_bind_int(pStmt, idx, ([obj boolValue] ? 1 : 0)); - } - else { - sqlite3_bind_text(pStmt, idx, [[obj description] UTF8String], -1, SQLITE_STATIC); - } - } - else { - sqlite3_bind_text(pStmt, idx, [[obj description] UTF8String], -1, SQLITE_STATIC); - } -} - -- (void)extractSQL:(NSString *)sql argumentsList:(va_list)args intoString:(NSMutableString *)cleanedSQL arguments:(NSMutableArray *)arguments { - - NSUInteger length = [sql length]; - unichar last = '\0'; - for (NSUInteger i = 0; i < length; ++i) { - id arg = nil; - unichar current = [sql characterAtIndex:i]; - unichar add = current; - if (last == '%') { - switch (current) { - case '@': - arg = va_arg(args, id); - break; - case 'c': - // warning: second argument to 'va_arg' is of promotable type 'char'; this va_arg has undefined behavior because arguments will be promoted to 'int' - arg = [NSString stringWithFormat:@"%c", va_arg(args, int)]; - break; - case 's': - arg = [NSString stringWithUTF8String:va_arg(args, char*)]; - break; - case 'd': - case 'D': - case 'i': - arg = [NSNumber numberWithInt:va_arg(args, int)]; - break; - case 'u': - case 'U': - arg = [NSNumber numberWithUnsignedInt:va_arg(args, unsigned int)]; - break; - case 'h': - i++; - if (i < length && [sql characterAtIndex:i] == 'i') { - // warning: second argument to 'va_arg' is of promotable type 'short'; this va_arg has undefined behavior because arguments will be promoted to 'int' - arg = [NSNumber numberWithShort:(short)(va_arg(args, int))]; - } - else if (i < length && [sql characterAtIndex:i] == 'u') { - // warning: second argument to 'va_arg' is of promotable type 'unsigned short'; this va_arg has undefined behavior because arguments will be promoted to 'int' - arg = [NSNumber numberWithUnsignedShort:(unsigned short)(va_arg(args, uint))]; - } - else { - i--; - } - break; - case 'q': - i++; - if (i < length && [sql characterAtIndex:i] == 'i') { - arg = [NSNumber numberWithLongLong:va_arg(args, long long)]; - } - else if (i < length && [sql characterAtIndex:i] == 'u') { - arg = [NSNumber numberWithUnsignedLongLong:va_arg(args, unsigned long long)]; - } - else { - i--; - } - break; - case 'f': - arg = [NSNumber numberWithDouble:va_arg(args, double)]; - break; - case 'g': - // warning: second argument to 'va_arg' is of promotable type 'float'; this va_arg has undefined behavior because arguments will be promoted to 'double' - arg = [NSNumber numberWithFloat:(float)(va_arg(args, double))]; - break; - case 'l': - i++; - if (i < length) { - unichar next = [sql characterAtIndex:i]; - if (next == 'l') { - i++; - if (i < length && [sql characterAtIndex:i] == 'd') { - //%lld - arg = [NSNumber numberWithLongLong:va_arg(args, long long)]; - } - else if (i < length && [sql characterAtIndex:i] == 'u') { - //%llu - arg = [NSNumber numberWithUnsignedLongLong:va_arg(args, unsigned long long)]; - } - else { - i--; - } - } - else if (next == 'd') { - //%ld - arg = [NSNumber numberWithLong:va_arg(args, long)]; - } - else if (next == 'u') { - //%lu - arg = [NSNumber numberWithUnsignedLong:va_arg(args, unsigned long)]; - } - else { - i--; - } - } - else { - i--; - } - break; - default: - // something else that we can't interpret. just pass it on through like normal - break; - } - } - else if (current == '%') { - // percent sign; skip this character - add = '\0'; - } - - if (arg != nil) { - [cleanedSQL appendString:@"?"]; - [arguments addObject:arg]; - } - else if (add == (unichar)'@' && last == (unichar) '%') { - [cleanedSQL appendFormat:@"NULL"]; - } - else if (add != '\0') { - [cleanedSQL appendFormat:@"%C", add]; - } - last = current; - } -} - -#pragma mark Execute queries - -- (FMResultSet *)executeQuery:(NSString *)sql withParameterDictionary:(NSDictionary *)arguments { - return [self executeQuery:sql withArgumentsInArray:nil orDictionary:arguments orVAList:nil]; -} - -- (FMResultSet *)executeQuery:(NSString *)sql withArgumentsInArray:(NSArray*)arrayArgs orDictionary:(NSDictionary *)dictionaryArgs orVAList:(va_list)args { - - if (![self databaseExists]) { - return 0x00; - } - - if (_isExecutingStatement) { - [self warnInUse]; - return 0x00; - } - - _isExecutingStatement = YES; - - int rc = 0x00; - sqlite3_stmt *pStmt = 0x00; - FMStatement *statement = 0x00; - FMResultSet *rs = 0x00; - - if (_traceExecution && sql) { - NSLog(@"%@ executeQuery: %@", self, sql); - } - - if (_shouldCacheStatements) { - statement = [self cachedStatementForQuery:sql]; - pStmt = statement ? [statement statement] : 0x00; - [statement reset]; - } - - if (!pStmt) { - - rc = sqlite3_prepare_v2(_db, [sql UTF8String], -1, &pStmt, 0); - - if (SQLITE_OK != rc) { - if (_logsErrors) { - NSLog(@"DB Error: %d \"%@\"", [self lastErrorCode], [self lastErrorMessage]); - NSLog(@"DB Query: %@", sql); - NSLog(@"DB Path: %@", _databasePath); - } - - if (_crashOnErrors) { - NSAssert(false, @"DB Error: %d \"%@\"", [self lastErrorCode], [self lastErrorMessage]); - abort(); - } - - sqlite3_finalize(pStmt); - _isExecutingStatement = NO; - return nil; - } - } - - id obj; - int idx = 0; - int queryCount = sqlite3_bind_parameter_count(pStmt); // pointed out by Dominic Yu (thanks!) - - // If dictionaryArgs is passed in, that means we are using sqlite's named parameter support - if (dictionaryArgs) { - - for (NSString *dictionaryKey in [dictionaryArgs allKeys]) { - - // Prefix the key with a colon. - NSString *parameterName = [[NSString alloc] initWithFormat:@":%@", dictionaryKey]; - - if (_traceExecution) { - NSLog(@"%@ = %@", parameterName, [dictionaryArgs objectForKey:dictionaryKey]); - } - - // Get the index for the parameter name. - int namedIdx = sqlite3_bind_parameter_index(pStmt, [parameterName UTF8String]); - - FMDBRelease(parameterName); - - if (namedIdx > 0) { - // Standard binding from here. - [self bindObject:[dictionaryArgs objectForKey:dictionaryKey] toColumn:namedIdx inStatement:pStmt]; - // increment the binding count, so our check below works out - idx++; - } - else { - NSLog(@"Could not find index for %@", dictionaryKey); - } - } - } - else { - - while (idx < queryCount) { - - if (arrayArgs && idx < (int)[arrayArgs count]) { - obj = [arrayArgs objectAtIndex:(NSUInteger)idx]; - } - else if (args) { - obj = va_arg(args, id); - } - else { - //We ran out of arguments - break; - } - - if (_traceExecution) { - if ([obj isKindOfClass:[NSData class]]) { - NSLog(@"data: %ld bytes", (unsigned long)[(NSData*)obj length]); - } - else { - NSLog(@"obj: %@", obj); - } - } - - idx++; - - [self bindObject:obj toColumn:idx inStatement:pStmt]; - } - } - - if (idx != queryCount) { - NSLog(@"Error: the bind count is not correct for the # of variables (executeQuery)"); - sqlite3_finalize(pStmt); - _isExecutingStatement = NO; - return nil; - } - - FMDBRetain(statement); // to balance the release below - - if (!statement) { - statement = [[FMStatement alloc] init]; - [statement setStatement:pStmt]; - - if (_shouldCacheStatements && sql) { - [self setCachedStatement:statement forQuery:sql]; - } - } - - // the statement gets closed in rs's dealloc or [rs close]; - rs = [FMResultSet resultSetWithStatement:statement usingParentDatabase:self]; - [rs setQuery:sql]; - - NSValue *openResultSet = [NSValue valueWithNonretainedObject:rs]; - [_openResultSets addObject:openResultSet]; - - [statement setUseCount:[statement useCount] + 1]; - - FMDBRelease(statement); - - _isExecutingStatement = NO; - - return rs; -} - -- (FMResultSet *)executeQuery:(NSString*)sql, ... { - va_list args; - va_start(args, sql); - - id result = [self executeQuery:sql withArgumentsInArray:nil orDictionary:nil orVAList:args]; - - va_end(args); - return result; -} - -- (FMResultSet *)executeQueryWithFormat:(NSString*)format, ... { - va_list args; - va_start(args, format); - - NSMutableString *sql = [NSMutableString stringWithCapacity:[format length]]; - NSMutableArray *arguments = [NSMutableArray array]; - [self extractSQL:format argumentsList:args intoString:sql arguments:arguments]; - - va_end(args); - - return [self executeQuery:sql withArgumentsInArray:arguments]; -} - -- (FMResultSet *)executeQuery:(NSString *)sql withArgumentsInArray:(NSArray *)arguments { - return [self executeQuery:sql withArgumentsInArray:arguments orDictionary:nil orVAList:nil]; -} - -- (FMResultSet *)executeQuery:(NSString *)sql values:(NSArray *)values error:(NSError * __autoreleasing *)error { - FMResultSet *rs = [self executeQuery:sql withArgumentsInArray:values orDictionary:nil orVAList:nil]; - if (!rs && error) { - *error = [self lastError]; - } - return rs; -} - -- (FMResultSet *)executeQuery:(NSString*)sql withVAList:(va_list)args { - return [self executeQuery:sql withArgumentsInArray:nil orDictionary:nil orVAList:args]; -} - -#pragma mark Execute updates - -- (BOOL)executeUpdate:(NSString*)sql error:(NSError**)outErr withArgumentsInArray:(NSArray*)arrayArgs orDictionary:(NSDictionary *)dictionaryArgs orVAList:(va_list)args { - - if (![self databaseExists]) { - return NO; - } - - if (_isExecutingStatement) { - [self warnInUse]; - return NO; - } - - _isExecutingStatement = YES; - - int rc = 0x00; - sqlite3_stmt *pStmt = 0x00; - FMStatement *cachedStmt = 0x00; - - if (_traceExecution && sql) { - NSLog(@"%@ executeUpdate: %@", self, sql); - } - - if (_shouldCacheStatements) { - cachedStmt = [self cachedStatementForQuery:sql]; - pStmt = cachedStmt ? [cachedStmt statement] : 0x00; - [cachedStmt reset]; - } - - if (!pStmt) { - rc = sqlite3_prepare_v2(_db, [sql UTF8String], -1, &pStmt, 0); - - if (SQLITE_OK != rc) { - if (_logsErrors) { - NSLog(@"DB Error: %d \"%@\"", [self lastErrorCode], [self lastErrorMessage]); - NSLog(@"DB Query: %@", sql); - NSLog(@"DB Path: %@", _databasePath); - } - - if (_crashOnErrors) { - NSAssert(false, @"DB Error: %d \"%@\"", [self lastErrorCode], [self lastErrorMessage]); - abort(); - } - - if (outErr) { - *outErr = [self errorWithMessage:[NSString stringWithUTF8String:sqlite3_errmsg(_db)]]; - } - - sqlite3_finalize(pStmt); - - _isExecutingStatement = NO; - return NO; - } - } - - id obj; - int idx = 0; - int queryCount = sqlite3_bind_parameter_count(pStmt); - - // If dictionaryArgs is passed in, that means we are using sqlite's named parameter support - if (dictionaryArgs) { - - for (NSString *dictionaryKey in [dictionaryArgs allKeys]) { - - // Prefix the key with a colon. - NSString *parameterName = [[NSString alloc] initWithFormat:@":%@", dictionaryKey]; - - if (_traceExecution) { - NSLog(@"%@ = %@", parameterName, [dictionaryArgs objectForKey:dictionaryKey]); - } - // Get the index for the parameter name. - int namedIdx = sqlite3_bind_parameter_index(pStmt, [parameterName UTF8String]); - - FMDBRelease(parameterName); - - if (namedIdx > 0) { - // Standard binding from here. - [self bindObject:[dictionaryArgs objectForKey:dictionaryKey] toColumn:namedIdx inStatement:pStmt]; - - // increment the binding count, so our check below works out - idx++; - } - else { - NSString *message = [NSString stringWithFormat:@"Could not find index for %@", dictionaryKey]; - - if (_logsErrors) { - NSLog(@"%@", message); - } - if (outErr) { - *outErr = [self errorWithMessage:message]; - } - } - } - } - else { - - while (idx < queryCount) { - - if (arrayArgs && idx < (int)[arrayArgs count]) { - obj = [arrayArgs objectAtIndex:(NSUInteger)idx]; - } - else if (args) { - obj = va_arg(args, id); - } - else { - //We ran out of arguments - break; - } - - if (_traceExecution) { - if ([obj isKindOfClass:[NSData class]]) { - NSLog(@"data: %ld bytes", (unsigned long)[(NSData*)obj length]); - } - else { - NSLog(@"obj: %@", obj); - } - } - - idx++; - - [self bindObject:obj toColumn:idx inStatement:pStmt]; - } - } - - - if (idx != queryCount) { - NSString *message = [NSString stringWithFormat:@"Error: the bind count (%d) is not correct for the # of variables in the query (%d) (%@) (executeUpdate)", idx, queryCount, sql]; - if (_logsErrors) { - NSLog(@"%@", message); - } - if (outErr) { - *outErr = [self errorWithMessage:message]; - } - - sqlite3_finalize(pStmt); - _isExecutingStatement = NO; - return NO; - } - - /* Call sqlite3_step() to run the virtual machine. Since the SQL being - ** executed is not a SELECT statement, we assume no data will be returned. - */ - - rc = sqlite3_step(pStmt); - - if (SQLITE_DONE == rc) { - // all is well, let's return. - } - else if (SQLITE_INTERRUPT == rc) { - if (_logsErrors) { - NSLog(@"Error calling sqlite3_step. Query was interrupted (%d: %s) SQLITE_INTERRUPT", rc, sqlite3_errmsg(_db)); - NSLog(@"DB Query: %@", sql); - } - } - else if (rc == SQLITE_ROW) { - NSString *message = [NSString stringWithFormat:@"A executeUpdate is being called with a query string '%@'", sql]; - if (_logsErrors) { - NSLog(@"%@", message); - NSLog(@"DB Query: %@", sql); - } - if (outErr) { - *outErr = [self errorWithMessage:message]; - } - } - else { - if (outErr) { - *outErr = [self errorWithMessage:[NSString stringWithUTF8String:sqlite3_errmsg(_db)]]; - } - - if (SQLITE_ERROR == rc) { - if (_logsErrors) { - NSLog(@"Error calling sqlite3_step (%d: %s) SQLITE_ERROR", rc, sqlite3_errmsg(_db)); - NSLog(@"DB Query: %@", sql); - } - } - else if (SQLITE_MISUSE == rc) { - // uh oh. - if (_logsErrors) { - NSLog(@"Error calling sqlite3_step (%d: %s) SQLITE_MISUSE", rc, sqlite3_errmsg(_db)); - NSLog(@"DB Query: %@", sql); - } - } - else { - // wtf? - if (_logsErrors) { - NSLog(@"Unknown error calling sqlite3_step (%d: %s) eu", rc, sqlite3_errmsg(_db)); - NSLog(@"DB Query: %@", sql); - } - } - } - - if (_shouldCacheStatements && !cachedStmt) { - cachedStmt = [[FMStatement alloc] init]; - - [cachedStmt setStatement:pStmt]; - - [self setCachedStatement:cachedStmt forQuery:sql]; - - FMDBRelease(cachedStmt); - } - - int closeErrorCode; - - if (cachedStmt) { - [cachedStmt setUseCount:[cachedStmt useCount] + 1]; - closeErrorCode = sqlite3_reset(pStmt); - } - else { - /* Finalize the virtual machine. This releases all memory and other - ** resources allocated by the sqlite3_prepare() call above. - */ - closeErrorCode = sqlite3_finalize(pStmt); - } - - if (closeErrorCode != SQLITE_OK) { - if (_logsErrors) { - NSLog(@"Unknown error finalizing or resetting statement (%d: %s)", closeErrorCode, sqlite3_errmsg(_db)); - NSLog(@"DB Query: %@", sql); - } - } - - _isExecutingStatement = NO; - return (rc == SQLITE_DONE || rc == SQLITE_OK); -} - - -- (BOOL)executeUpdate:(NSString*)sql, ... { - va_list args; - va_start(args, sql); - - BOOL result = [self executeUpdate:sql error:nil withArgumentsInArray:nil orDictionary:nil orVAList:args]; - - va_end(args); - return result; -} - -- (BOOL)executeUpdate:(NSString*)sql withArgumentsInArray:(NSArray *)arguments { - return [self executeUpdate:sql error:nil withArgumentsInArray:arguments orDictionary:nil orVAList:nil]; -} - -- (BOOL)executeUpdate:(NSString*)sql values:(NSArray *)values error:(NSError * __autoreleasing *)error { - return [self executeUpdate:sql error:error withArgumentsInArray:values orDictionary:nil orVAList:nil]; -} - -- (BOOL)executeUpdate:(NSString*)sql withParameterDictionary:(NSDictionary *)arguments { - return [self executeUpdate:sql error:nil withArgumentsInArray:nil orDictionary:arguments orVAList:nil]; -} - -- (BOOL)executeUpdate:(NSString*)sql withVAList:(va_list)args { - return [self executeUpdate:sql error:nil withArgumentsInArray:nil orDictionary:nil orVAList:args]; -} - -- (BOOL)executeUpdateWithFormat:(NSString*)format, ... { - va_list args; - va_start(args, format); - - NSMutableString *sql = [NSMutableString stringWithCapacity:[format length]]; - NSMutableArray *arguments = [NSMutableArray array]; - - [self extractSQL:format argumentsList:args intoString:sql arguments:arguments]; - - va_end(args); - - return [self executeUpdate:sql withArgumentsInArray:arguments]; -} - - -int FMDBExecuteBulkSQLCallback(void *theBlockAsVoid, int columns, char **values, char **names); // shhh clang. -int FMDBExecuteBulkSQLCallback(void *theBlockAsVoid, int columns, char **values, char **names) { - - if (!theBlockAsVoid) { - return SQLITE_OK; - } - - int (^execCallbackBlock)(NSDictionary *resultsDictionary) = (__bridge int (^)(NSDictionary *__strong))(theBlockAsVoid); - - NSMutableDictionary *dictionary = [NSMutableDictionary dictionaryWithCapacity:(NSUInteger)columns]; - - for (NSInteger i = 0; i < columns; i++) { - NSString *key = [NSString stringWithUTF8String:names[i]]; - id value = values[i] ? [NSString stringWithUTF8String:values[i]] : [NSNull null]; - [dictionary setObject:value forKey:key]; - } - - return execCallbackBlock(dictionary); -} - -- (BOOL)executeStatements:(NSString *)sql { - return [self executeStatements:sql withResultBlock:nil]; -} - -- (BOOL)executeStatements:(NSString *)sql withResultBlock:(FMDBExecuteStatementsCallbackBlock)block { - - int rc; - char *errmsg = nil; - - rc = sqlite3_exec([self sqliteHandle], [sql UTF8String], block ? FMDBExecuteBulkSQLCallback : nil, (__bridge void *)(block), &errmsg); - - if (errmsg && [self logsErrors]) { - NSLog(@"Error inserting batch: %s", errmsg); - sqlite3_free(errmsg); - } - - return (rc == SQLITE_OK); -} - -- (BOOL)executeUpdate:(NSString*)sql withErrorAndBindings:(NSError**)outErr, ... { - - va_list args; - va_start(args, outErr); - - BOOL result = [self executeUpdate:sql error:outErr withArgumentsInArray:nil orDictionary:nil orVAList:args]; - - va_end(args); - return result; -} - - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-implementations" -- (BOOL)update:(NSString*)sql withErrorAndBindings:(NSError**)outErr, ... { - va_list args; - va_start(args, outErr); - - BOOL result = [self executeUpdate:sql error:outErr withArgumentsInArray:nil orDictionary:nil orVAList:args]; - - va_end(args); - return result; -} - -#pragma clang diagnostic pop - -#pragma mark Transactions - -- (BOOL)rollback { - BOOL b = [self executeUpdate:@"rollback transaction"]; - - if (b) { - _isInTransaction = NO; - } - - return b; -} - -- (BOOL)commit { - BOOL b = [self executeUpdate:@"commit transaction"]; - - if (b) { - _isInTransaction = NO; - } - - return b; -} - -- (BOOL)beginDeferredTransaction { - - BOOL b = [self executeUpdate:@"begin deferred transaction"]; - if (b) { - _isInTransaction = YES; - } - - return b; -} - -- (BOOL)beginTransaction { - - BOOL b = [self executeUpdate:@"begin exclusive transaction"]; - if (b) { - _isInTransaction = YES; - } - - return b; -} - -- (BOOL)inTransaction { - return _isInTransaction; -} - -- (BOOL)interrupt -{ - if (_db) { - sqlite3_interrupt([self sqliteHandle]); - return YES; - } - return NO; -} - -static NSString *FMDBEscapeSavePointName(NSString *savepointName) { - return [savepointName stringByReplacingOccurrencesOfString:@"'" withString:@"''"]; -} - -- (BOOL)startSavePointWithName:(NSString*)name error:(NSError**)outErr { -#if SQLITE_VERSION_NUMBER >= 3007000 - NSParameterAssert(name); - - NSString *sql = [NSString stringWithFormat:@"savepoint '%@';", FMDBEscapeSavePointName(name)]; - - return [self executeUpdate:sql error:outErr withArgumentsInArray:nil orDictionary:nil orVAList:nil]; -#else - NSString *errorMessage = NSLocalizedString(@"Save point functions require SQLite 3.7", nil); - if (self.logsErrors) NSLog(@"%@", errorMessage); - return NO; -#endif -} - -- (BOOL)releaseSavePointWithName:(NSString*)name error:(NSError**)outErr { -#if SQLITE_VERSION_NUMBER >= 3007000 - NSParameterAssert(name); - - NSString *sql = [NSString stringWithFormat:@"release savepoint '%@';", FMDBEscapeSavePointName(name)]; - - return [self executeUpdate:sql error:outErr withArgumentsInArray:nil orDictionary:nil orVAList:nil]; -#else - NSString *errorMessage = NSLocalizedString(@"Save point functions require SQLite 3.7", nil); - if (self.logsErrors) NSLog(@"%@", errorMessage); - return NO; -#endif -} - -- (BOOL)rollbackToSavePointWithName:(NSString*)name error:(NSError**)outErr { -#if SQLITE_VERSION_NUMBER >= 3007000 - NSParameterAssert(name); - - NSString *sql = [NSString stringWithFormat:@"rollback transaction to savepoint '%@';", FMDBEscapeSavePointName(name)]; - - return [self executeUpdate:sql error:outErr withArgumentsInArray:nil orDictionary:nil orVAList:nil]; -#else - NSString *errorMessage = NSLocalizedString(@"Save point functions require SQLite 3.7", nil); - if (self.logsErrors) NSLog(@"%@", errorMessage); - return NO; -#endif -} - -- (NSError*)inSavePoint:(void (^)(BOOL *rollback))block { -#if SQLITE_VERSION_NUMBER >= 3007000 - static unsigned long savePointIdx = 0; - - NSString *name = [NSString stringWithFormat:@"dbSavePoint%ld", savePointIdx++]; - - BOOL shouldRollback = NO; - - NSError *err = 0x00; - - if (![self startSavePointWithName:name error:&err]) { - return err; - } - - if (block) { - block(&shouldRollback); - } - - if (shouldRollback) { - // We need to rollback and release this savepoint to remove it - [self rollbackToSavePointWithName:name error:&err]; - } - [self releaseSavePointWithName:name error:&err]; - - return err; -#else - NSString *errorMessage = NSLocalizedString(@"Save point functions require SQLite 3.7", nil); - if (self.logsErrors) NSLog(@"%@", errorMessage); - return [NSError errorWithDomain:@"FMDatabase" code:0 userInfo:@{NSLocalizedDescriptionKey : errorMessage}]; -#endif -} - - -#pragma mark Cache statements - -- (BOOL)shouldCacheStatements { - return _shouldCacheStatements; -} - -- (void)setShouldCacheStatements:(BOOL)value { - - _shouldCacheStatements = value; - - if (_shouldCacheStatements && !_cachedStatements) { - [self setCachedStatements:[NSMutableDictionary dictionary]]; - } - - if (!_shouldCacheStatements) { - [self setCachedStatements:nil]; - } -} - -#pragma mark Callback function - -void FMDBBlockSQLiteCallBackFunction(sqlite3_context *context, int argc, sqlite3_value **argv); // -Wmissing-prototypes -void FMDBBlockSQLiteCallBackFunction(sqlite3_context *context, int argc, sqlite3_value **argv) { -#if ! __has_feature(objc_arc) - void (^block)(sqlite3_context *context, int argc, sqlite3_value **argv) = (id)sqlite3_user_data(context); -#else - void (^block)(sqlite3_context *context, int argc, sqlite3_value **argv) = (__bridge id)sqlite3_user_data(context); -#endif - if (block) { - @autoreleasepool { - block(context, argc, argv); - } - } -} - -// deprecated because "arguments" parameter is not maximum argument count, but actual argument count. - -- (void)makeFunctionNamed:(NSString *)name maximumArguments:(int)arguments withBlock:(void (^)(void *context, int argc, void **argv))block { - [self makeFunctionNamed:name arguments:arguments block:block]; -} - -- (void)makeFunctionNamed:(NSString *)name arguments:(int)arguments block:(void (^)(void *context, int argc, void **argv))block { - - if (!_openFunctions) { - _openFunctions = [NSMutableSet new]; - } - - id b = FMDBReturnAutoreleased([block copy]); - - [_openFunctions addObject:b]; - - /* I tried adding custom functions to release the block when the connection is destroyed- but they seemed to never be called, so we use _openFunctions to store the values instead. */ -#if ! __has_feature(objc_arc) - sqlite3_create_function([self sqliteHandle], [name UTF8String], arguments, SQLITE_UTF8, (void*)b, &FMDBBlockSQLiteCallBackFunction, 0x00, 0x00); -#else - sqlite3_create_function([self sqliteHandle], [name UTF8String], arguments, SQLITE_UTF8, (__bridge void*)b, &FMDBBlockSQLiteCallBackFunction, 0x00, 0x00); -#endif -} - -- (SqliteValueType)valueType:(void *)value { - return sqlite3_value_type(value); -} - -- (int)valueInt:(void *)value { - return sqlite3_value_int(value); -} - -- (long long)valueLong:(void *)value { - return sqlite3_value_int64(value); -} - -- (double)valueDouble:(void *)value { - return sqlite3_value_double(value); -} - -- (NSData *)valueData:(void *)value { - const void *bytes = sqlite3_value_blob(value); - int length = sqlite3_value_bytes(value); - return bytes ? [NSData dataWithBytes:bytes length:length] : nil; -} - -- (NSString *)valueString:(void *)value { - const char *cString = (const char *)sqlite3_value_text(value); - return cString ? [NSString stringWithUTF8String:cString] : nil; -} - -- (void)resultNullInContext:(void *)context { - sqlite3_result_null(context); -} - -- (void)resultInt:(int) value context:(void *)context { - sqlite3_result_int(context, value); -} - -- (void)resultLong:(long long)value context:(void *)context { - sqlite3_result_int64(context, value); -} - -- (void)resultDouble:(double)value context:(void *)context { - sqlite3_result_double(context, value); -} - -- (void)resultData:(NSData *)data context:(void *)context { - sqlite3_result_blob(context, data.bytes, (int)data.length, SQLITE_TRANSIENT); -} - -- (void)resultString:(NSString *)value context:(void *)context { - sqlite3_result_text(context, [value UTF8String], -1, SQLITE_TRANSIENT); -} - -- (void)resultError:(NSString *)error context:(void *)context { - sqlite3_result_error(context, [error UTF8String], -1); -} - -- (void)resultErrorCode:(int)errorCode context:(void *)context { - sqlite3_result_error_code(context, errorCode); -} - -- (void)resultErrorNoMemoryInContext:(void *)context { - sqlite3_result_error_nomem(context); -} - -- (void)resultErrorTooBigInContext:(void *)context { - sqlite3_result_error_toobig(context); -} - -@end - - - -@implementation FMStatement - -#if ! __has_feature(objc_arc) -- (void)finalize { - [self close]; - [super finalize]; -} -#endif - -- (void)dealloc { - [self close]; - FMDBRelease(_query); -#if ! __has_feature(objc_arc) - [super dealloc]; -#endif -} - -- (void)close { - if (_statement) { - sqlite3_finalize(_statement); - _statement = 0x00; - } - - _inUse = NO; -} - -- (void)reset { - if (_statement) { - sqlite3_reset(_statement); - } - - _inUse = NO; -} - -- (NSString*)description { - return [NSString stringWithFormat:@"%@ %ld hit(s) for query %@", [super description], _useCount, _query]; -} - -@end - diff --git a/lib/ios/AirMaps/fmdb/FMDatabaseAdditions.h b/lib/ios/AirMaps/fmdb/FMDatabaseAdditions.h deleted file mode 100644 index 8ee51c721..000000000 --- a/lib/ios/AirMaps/fmdb/FMDatabaseAdditions.h +++ /dev/null @@ -1,250 +0,0 @@ -// -// FMDatabaseAdditions.h -// fmdb -// -// Created by August Mueller on 10/30/05. -// Copyright 2005 Flying Meat Inc.. All rights reserved. -// - -#import -#import "FMDatabase.h" - -NS_ASSUME_NONNULL_BEGIN - -/** Category of additions for `` class. - - ### See also - - - `` - */ - -@interface FMDatabase (FMDatabaseAdditions) - -///---------------------------------------- -/// @name Return results of SQL to variable -///---------------------------------------- - -/** Return `int` value for query - - @param query The SQL query to be performed. - @param ... A list of parameters that will be bound to the `?` placeholders in the SQL query. - - @return `int` value. - - @note This is not available from Swift. - */ - -- (int)intForQuery:(NSString*)query, ...; - -/** Return `long` value for query - - @param query The SQL query to be performed. - @param ... A list of parameters that will be bound to the `?` placeholders in the SQL query. - - @return `long` value. - - @note This is not available from Swift. - */ - -- (long)longForQuery:(NSString*)query, ...; - -/** Return `BOOL` value for query - - @param query The SQL query to be performed. - @param ... A list of parameters that will be bound to the `?` placeholders in the SQL query. - - @return `BOOL` value. - - @note This is not available from Swift. - */ - -- (BOOL)boolForQuery:(NSString*)query, ...; - -/** Return `double` value for query - - @param query The SQL query to be performed. - @param ... A list of parameters that will be bound to the `?` placeholders in the SQL query. - - @return `double` value. - - @note This is not available from Swift. - */ - -- (double)doubleForQuery:(NSString*)query, ...; - -/** Return `NSString` value for query - - @param query The SQL query to be performed. - @param ... A list of parameters that will be bound to the `?` placeholders in the SQL query. - - @return `NSString` value. - - @note This is not available from Swift. - */ - -- (NSString * _Nullable)stringForQuery:(NSString*)query, ...; - -/** Return `NSData` value for query - - @param query The SQL query to be performed. - @param ... A list of parameters that will be bound to the `?` placeholders in the SQL query. - - @return `NSData` value. - - @note This is not available from Swift. - */ - -- (NSData * _Nullable)dataForQuery:(NSString*)query, ...; - -/** Return `NSDate` value for query - - @param query The SQL query to be performed. - @param ... A list of parameters that will be bound to the `?` placeholders in the SQL query. - - @return `NSDate` value. - - @note This is not available from Swift. - */ - -- (NSDate * _Nullable)dateForQuery:(NSString*)query, ...; - - -// Notice that there's no dataNoCopyForQuery:. -// That would be a bad idea, because we close out the result set, and then what -// happens to the data that we just didn't copy? Who knows, not I. - - -///-------------------------------- -/// @name Schema related operations -///-------------------------------- - -/** Does table exist in database? - - @param tableName The name of the table being looked for. - - @return `YES` if table found; `NO` if not found. - */ - -- (BOOL)tableExists:(NSString*)tableName; - -/** The schema of the database. - - This will be the schema for the entire database. For each entity, each row of the result set will include the following fields: - - - `type` - The type of entity (e.g. table, index, view, or trigger) - - `name` - The name of the object - - `tbl_name` - The name of the table to which the object references - - `rootpage` - The page number of the root b-tree page for tables and indices - - `sql` - The SQL that created the entity - - @return `FMResultSet` of schema; `nil` on error. - - @see [SQLite File Format](http://www.sqlite.org/fileformat.html) - */ - -- (FMResultSet *)getSchema; - -/** The schema of the database. - - This will be the schema for a particular table as report by SQLite `PRAGMA`, for example: - - PRAGMA table_info('employees') - - This will report: - - - `cid` - The column ID number - - `name` - The name of the column - - `type` - The data type specified for the column - - `notnull` - whether the field is defined as NOT NULL (i.e. values required) - - `dflt_value` - The default value for the column - - `pk` - Whether the field is part of the primary key of the table - - @param tableName The name of the table for whom the schema will be returned. - - @return `FMResultSet` of schema; `nil` on error. - - @see [table_info](http://www.sqlite.org/pragma.html#pragma_table_info) - */ - -- (FMResultSet*)getTableSchema:(NSString*)tableName; - -/** Test to see if particular column exists for particular table in database - - @param columnName The name of the column. - - @param tableName The name of the table. - - @return `YES` if column exists in table in question; `NO` otherwise. - */ - -- (BOOL)columnExists:(NSString*)columnName inTableWithName:(NSString*)tableName; - -/** Test to see if particular column exists for particular table in database - - @param columnName The name of the column. - - @param tableName The name of the table. - - @return `YES` if column exists in table in question; `NO` otherwise. - - @see columnExists:inTableWithName: - - @warning Deprecated - use `` instead. - */ - -- (BOOL)columnExists:(NSString*)tableName columnName:(NSString*)columnName __deprecated_msg("Use columnExists:inTableWithName: instead"); - - -/** Validate SQL statement - - This validates SQL statement by performing `sqlite3_prepare_v2`, but not returning the results, but instead immediately calling `sqlite3_finalize`. - - @param sql The SQL statement being validated. - - @param error This is a pointer to a `NSError` object that will receive the autoreleased `NSError` object if there was any error. If this is `nil`, no `NSError` result will be returned. - - @return `YES` if validation succeeded without incident; `NO` otherwise. - - */ - -- (BOOL)validateSQL:(NSString*)sql error:(NSError * _Nullable *)error; - - -///----------------------------------- -/// @name Application identifier tasks -///----------------------------------- - -/** Retrieve application ID - - @return The `uint32_t` numeric value of the application ID. - - @see setApplicationID: - */ - -@property (nonatomic) uint32_t applicationID; - -#if TARGET_OS_MAC && !TARGET_OS_IPHONE - -/** Retrieve application ID string - - @see setApplicationIDString: - */ - -@property (nonatomic, retain) NSString *applicationIDString; - -#endif - -///----------------------------------- -/// @name user version identifier tasks -///----------------------------------- - -/** Retrieve user version - - @see setUserVersion: - */ - -@property (nonatomic) uint32_t userVersion; - -@end - -NS_ASSUME_NONNULL_END diff --git a/lib/ios/AirMaps/fmdb/FMDatabaseAdditions.m b/lib/ios/AirMaps/fmdb/FMDatabaseAdditions.m deleted file mode 100644 index 208e69e52..000000000 --- a/lib/ios/AirMaps/fmdb/FMDatabaseAdditions.m +++ /dev/null @@ -1,245 +0,0 @@ -// -// FMDatabaseAdditions.m -// fmdb -// -// Created by August Mueller on 10/30/05. -// Copyright 2005 Flying Meat Inc.. All rights reserved. -// - -#import "FMDatabase.h" -#import "FMDatabaseAdditions.h" -#import "TargetConditionals.h" - -#if FMDB_SQLITE_STANDALONE -#import -#else -#import -#endif - -@interface FMDatabase (PrivateStuff) -- (FMResultSet *)executeQuery:(NSString *)sql withArgumentsInArray:(NSArray * _Nullable)arrayArgs orDictionary:(NSDictionary * _Nullable)dictionaryArgs orVAList:(va_list)args; -@end - -@implementation FMDatabase (FMDatabaseAdditions) - -#define RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(type, sel) \ -va_list args; \ -va_start(args, query); \ -FMResultSet *resultSet = [self executeQuery:query withArgumentsInArray:0x00 orDictionary:0x00 orVAList:args]; \ -va_end(args); \ -if (![resultSet next]) { return (type)0; } \ -type ret = [resultSet sel:0]; \ -[resultSet close]; \ -[resultSet setParentDB:nil]; \ -return ret; - - -- (NSString *)stringForQuery:(NSString*)query, ... { - RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(NSString *, stringForColumnIndex); -} - -- (int)intForQuery:(NSString*)query, ... { - RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(int, intForColumnIndex); -} - -- (long)longForQuery:(NSString*)query, ... { - RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(long, longForColumnIndex); -} - -- (BOOL)boolForQuery:(NSString*)query, ... { - RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(BOOL, boolForColumnIndex); -} - -- (double)doubleForQuery:(NSString*)query, ... { - RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(double, doubleForColumnIndex); -} - -- (NSData*)dataForQuery:(NSString*)query, ... { - RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(NSData *, dataForColumnIndex); -} - -- (NSDate*)dateForQuery:(NSString*)query, ... { - RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(NSDate *, dateForColumnIndex); -} - - -- (BOOL)tableExists:(NSString*)tableName { - - tableName = [tableName lowercaseString]; - - FMResultSet *rs = [self executeQuery:@"select [sql] from sqlite_master where [type] = 'table' and lower(name) = ?", tableName]; - - //if at least one next exists, table exists - BOOL returnBool = [rs next]; - - //close and free object - [rs close]; - - return returnBool; -} - -/* - get table with list of tables: result colums: type[STRING], name[STRING],tbl_name[STRING],rootpage[INTEGER],sql[STRING] - check if table exist in database (patch from OZLB) -*/ -- (FMResultSet*)getSchema { - - //result colums: type[STRING], name[STRING],tbl_name[STRING],rootpage[INTEGER],sql[STRING] - FMResultSet *rs = [self executeQuery:@"SELECT type, name, tbl_name, rootpage, sql FROM (SELECT * FROM sqlite_master UNION ALL SELECT * FROM sqlite_temp_master) WHERE type != 'meta' AND name NOT LIKE 'sqlite_%' ORDER BY tbl_name, type DESC, name"]; - - return rs; -} - -/* - get table schema: result colums: cid[INTEGER], name,type [STRING], notnull[INTEGER], dflt_value[],pk[INTEGER] -*/ -- (FMResultSet*)getTableSchema:(NSString*)tableName { - - //result colums: cid[INTEGER], name,type [STRING], notnull[INTEGER], dflt_value[],pk[INTEGER] - FMResultSet *rs = [self executeQuery:[NSString stringWithFormat: @"pragma table_info('%@')", tableName]]; - - return rs; -} - -- (BOOL)columnExists:(NSString*)columnName inTableWithName:(NSString*)tableName { - - BOOL returnBool = NO; - - tableName = [tableName lowercaseString]; - columnName = [columnName lowercaseString]; - - FMResultSet *rs = [self getTableSchema:tableName]; - - //check if column is present in table schema - while ([rs next]) { - if ([[[rs stringForColumn:@"name"] lowercaseString] isEqualToString:columnName]) { - returnBool = YES; - break; - } - } - - //If this is not done FMDatabase instance stays out of pool - [rs close]; - - return returnBool; -} - - - -- (uint32_t)applicationID { -#if SQLITE_VERSION_NUMBER >= 3007017 - uint32_t r = 0; - - FMResultSet *rs = [self executeQuery:@"pragma application_id"]; - - if ([rs next]) { - r = (uint32_t)[rs longLongIntForColumnIndex:0]; - } - - [rs close]; - - return r; -#else - NSString *errorMessage = NSLocalizedString(@"Application ID functions require SQLite 3.7.17", nil); - if (self.logsErrors) NSLog(@"%@", errorMessage); - return 0; -#endif -} - -- (void)setApplicationID:(uint32_t)appID { -#if SQLITE_VERSION_NUMBER >= 3007017 - NSString *query = [NSString stringWithFormat:@"pragma application_id=%d", appID]; - FMResultSet *rs = [self executeQuery:query]; - [rs next]; - [rs close]; -#else - NSString *errorMessage = NSLocalizedString(@"Application ID functions require SQLite 3.7.17", nil); - if (self.logsErrors) NSLog(@"%@", errorMessage); -#endif -} - - -#if TARGET_OS_MAC && !TARGET_OS_IPHONE - -- (NSString*)applicationIDString { -#if SQLITE_VERSION_NUMBER >= 3007017 - NSString *s = NSFileTypeForHFSTypeCode([self applicationID]); - - assert([s length] == 6); - - s = [s substringWithRange:NSMakeRange(1, 4)]; - - - return s; -#else - NSString *errorMessage = NSLocalizedString(@"Application ID functions require SQLite 3.7.17", nil); - if (self.logsErrors) NSLog(@"%@", errorMessage); - return nil; -#endif -} - -- (void)setApplicationIDString:(NSString*)s { -#if SQLITE_VERSION_NUMBER >= 3007017 - if ([s length] != 4) { - NSLog(@"setApplicationIDString: string passed is not exactly 4 chars long. (was %ld)", [s length]); - } - - [self setApplicationID:NSHFSTypeCodeFromFileType([NSString stringWithFormat:@"'%@'", s])]; -#else - NSString *errorMessage = NSLocalizedString(@"Application ID functions require SQLite 3.7.17", nil); - if (self.logsErrors) NSLog(@"%@", errorMessage); -#endif -} - -#endif - -- (uint32_t)userVersion { - uint32_t r = 0; - - FMResultSet *rs = [self executeQuery:@"pragma user_version"]; - - if ([rs next]) { - r = (uint32_t)[rs longLongIntForColumnIndex:0]; - } - - [rs close]; - return r; -} - -- (void)setUserVersion:(uint32_t)version { - NSString *query = [NSString stringWithFormat:@"pragma user_version = %d", version]; - FMResultSet *rs = [self executeQuery:query]; - [rs next]; - [rs close]; -} - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-implementations" - -- (BOOL)columnExists:(NSString*)tableName columnName:(NSString*)columnName __attribute__ ((deprecated)) { - return [self columnExists:columnName inTableWithName:tableName]; -} - -#pragma clang diagnostic pop - -- (BOOL)validateSQL:(NSString*)sql error:(NSError**)error { - sqlite3_stmt *pStmt = NULL; - BOOL validationSucceeded = YES; - - int rc = sqlite3_prepare_v2([self sqliteHandle], [sql UTF8String], -1, &pStmt, 0); - if (rc != SQLITE_OK) { - validationSucceeded = NO; - if (error) { - *error = [NSError errorWithDomain:NSCocoaErrorDomain - code:[self lastErrorCode] - userInfo:[NSDictionary dictionaryWithObject:[self lastErrorMessage] - forKey:NSLocalizedDescriptionKey]]; - } - } - - sqlite3_finalize(pStmt); - - return validationSucceeded; -} - -@end diff --git a/lib/ios/AirMaps/fmdb/FMDatabasePool.h b/lib/ios/AirMaps/fmdb/FMDatabasePool.h deleted file mode 100755 index 3642f59c5..000000000 --- a/lib/ios/AirMaps/fmdb/FMDatabasePool.h +++ /dev/null @@ -1,258 +0,0 @@ -// -// FMDatabasePool.h -// fmdb -// -// Created by August Mueller on 6/22/11. -// Copyright 2011 Flying Meat Inc. All rights reserved. -// - -#import - -NS_ASSUME_NONNULL_BEGIN - -@class FMDatabase; - -/** Pool of `` objects. - - ### See also - - - `` - - `` - - @warning Before using `FMDatabasePool`, please consider using `` instead. - - If you really really really know what you're doing and `FMDatabasePool` is what - you really really need (ie, you're using a read only database), OK you can use - it. But just be careful not to deadlock! - - For an example on deadlocking, search for: - `ONLY_USE_THE_POOL_IF_YOU_ARE_DOING_READS_OTHERWISE_YOULL_DEADLOCK_USE_FMDATABASEQUEUE_INSTEAD` - in the main.m file. - */ - -@interface FMDatabasePool : NSObject - -/** Database path */ - -@property (atomic, copy, nullable) NSString *path; - -/** Delegate object */ - -@property (atomic, assign, nullable) id delegate; - -/** Maximum number of databases to create */ - -@property (atomic, assign) NSUInteger maximumNumberOfDatabasesToCreate; - -/** Open flags */ - -@property (atomic, readonly) int openFlags; - -/** Custom virtual file system name */ - -@property (atomic, copy, nullable) NSString *vfsName; - - -///--------------------- -/// @name Initialization -///--------------------- - -/** Create pool using path. - - @param aPath The file path of the database. - - @return The `FMDatabasePool` object. `nil` on error. - */ - -+ (instancetype)databasePoolWithPath:(NSString * _Nullable)aPath; - -/** Create pool using file URL. - - @param url The file `NSURL` of the database. - - @return The `FMDatabasePool` object. `nil` on error. - */ - -+ (instancetype)databasePoolWithURL:(NSURL * _Nullable)url; - -/** Create pool using path and specified flags - - @param aPath The file path of the database. - @param openFlags Flags passed to the openWithFlags method of the database. - - @return The `FMDatabasePool` object. `nil` on error. - */ - -+ (instancetype)databasePoolWithPath:(NSString * _Nullable)aPath flags:(int)openFlags; - -/** Create pool using file URL and specified flags - - @param url The file `NSURL` of the database. - @param openFlags Flags passed to the openWithFlags method of the database. - - @return The `FMDatabasePool` object. `nil` on error. - */ - -+ (instancetype)databasePoolWithURL:(NSURL * _Nullable)url flags:(int)openFlags; - -/** Create pool using path. - - @param aPath The file path of the database. - - @return The `FMDatabasePool` object. `nil` on error. - */ - -- (instancetype)initWithPath:(NSString * _Nullable)aPath; - -/** Create pool using file URL. - - @param url The file `NSURL of the database. - - @return The `FMDatabasePool` object. `nil` on error. - */ - -- (instancetype)initWithURL:(NSURL * _Nullable)url; - -/** Create pool using path and specified flags. - - @param aPath The file path of the database. - @param openFlags Flags passed to the openWithFlags method of the database - - @return The `FMDatabasePool` object. `nil` on error. - */ - -- (instancetype)initWithPath:(NSString * _Nullable)aPath flags:(int)openFlags; - -/** Create pool using file URL and specified flags. - - @param url The file `NSURL` of the database. - @param openFlags Flags passed to the openWithFlags method of the database - - @return The `FMDatabasePool` object. `nil` on error. - */ - -- (instancetype)initWithURL:(NSURL * _Nullable)url flags:(int)openFlags; - -/** Create pool using path and specified flags. - - @param aPath The file path of the database. - @param openFlags Flags passed to the openWithFlags method of the database - @param vfsName The name of a custom virtual file system - - @return The `FMDatabasePool` object. `nil` on error. - */ - -- (instancetype)initWithPath:(NSString * _Nullable)aPath flags:(int)openFlags vfs:(NSString * _Nullable)vfsName; - -/** Create pool using file URL and specified flags. - - @param url The file `NSURL` of the database. - @param openFlags Flags passed to the openWithFlags method of the database - @param vfsName The name of a custom virtual file system - - @return The `FMDatabasePool` object. `nil` on error. - */ - -- (instancetype)initWithURL:(NSURL * _Nullable)url flags:(int)openFlags vfs:(NSString * _Nullable)vfsName; - -/** Returns the Class of 'FMDatabase' subclass, that will be used to instantiate database object. - - Subclasses can override this method to return specified Class of 'FMDatabase' subclass. - - @return The Class of 'FMDatabase' subclass, that will be used to instantiate database object. - */ - -+ (Class)databaseClass; - -///------------------------------------------------ -/// @name Keeping track of checked in/out databases -///------------------------------------------------ - -/** Number of checked-in databases in pool - */ - -@property (nonatomic, readonly) NSUInteger countOfCheckedInDatabases; - -/** Number of checked-out databases in pool - */ - -@property (nonatomic, readonly) NSUInteger countOfCheckedOutDatabases; - -/** Total number of databases in pool - */ - -@property (nonatomic, readonly) NSUInteger countOfOpenDatabases; - -/** Release all databases in pool */ - -- (void)releaseAllDatabases; - -///------------------------------------------ -/// @name Perform database operations in pool -///------------------------------------------ - -/** Synchronously perform database operations in pool. - - @param block The code to be run on the `FMDatabasePool` pool. - */ - -- (void)inDatabase:(__attribute__((noescape)) void (^)(FMDatabase *db))block; - -/** Synchronously perform database operations in pool using transaction. - - @param block The code to be run on the `FMDatabasePool` pool. - */ - -- (void)inTransaction:(__attribute__((noescape)) void (^)(FMDatabase *db, BOOL *rollback))block; - -/** Synchronously perform database operations in pool using deferred transaction. - - @param block The code to be run on the `FMDatabasePool` pool. - */ - -- (void)inDeferredTransaction:(__attribute__((noescape)) void (^)(FMDatabase *db, BOOL *rollback))block; - -/** Synchronously perform database operations in pool using save point. - - @param block The code to be run on the `FMDatabasePool` pool. - - @return `NSError` object if error; `nil` if successful. - - @warning You can not nest these, since calling it will pull another database out of the pool and you'll get a deadlock. If you need to nest, use `<[FMDatabase startSavePointWithName:error:]>` instead. -*/ - -- (NSError * _Nullable)inSavePoint:(__attribute__((noescape)) void (^)(FMDatabase *db, BOOL *rollback))block; - -@end - - -/** FMDatabasePool delegate category - - This is a category that defines the protocol for the FMDatabasePool delegate - */ - -@interface NSObject (FMDatabasePoolDelegate) - -/** Asks the delegate whether database should be added to the pool. - - @param pool The `FMDatabasePool` object. - @param database The `FMDatabase` object. - - @return `YES` if it should add database to pool; `NO` if not. - - */ - -- (BOOL)databasePool:(FMDatabasePool*)pool shouldAddDatabaseToPool:(FMDatabase*)database; - -/** Tells the delegate that database was added to the pool. - - @param pool The `FMDatabasePool` object. - @param database The `FMDatabase` object. - - */ - -- (void)databasePool:(FMDatabasePool*)pool didAddDatabase:(FMDatabase*)database; - -@end - -NS_ASSUME_NONNULL_END diff --git a/lib/ios/AirMaps/fmdb/FMDatabasePool.m b/lib/ios/AirMaps/fmdb/FMDatabasePool.m deleted file mode 100755 index 41a598589..000000000 --- a/lib/ios/AirMaps/fmdb/FMDatabasePool.m +++ /dev/null @@ -1,316 +0,0 @@ -// -// FMDatabasePool.m -// fmdb -// -// Created by August Mueller on 6/22/11. -// Copyright 2011 Flying Meat Inc. All rights reserved. -// - -#if FMDB_SQLITE_STANDALONE -#import -#else -#import -#endif - -#import "FMDatabasePool.h" -#import "FMDatabase.h" - -@interface FMDatabasePool () { - dispatch_queue_t _lockQueue; - - NSMutableArray *_databaseInPool; - NSMutableArray *_databaseOutPool; -} - -- (void)pushDatabaseBackInPool:(FMDatabase*)db; -- (FMDatabase*)db; - -@end - - -@implementation FMDatabasePool -@synthesize path=_path; -@synthesize delegate=_delegate; -@synthesize maximumNumberOfDatabasesToCreate=_maximumNumberOfDatabasesToCreate; -@synthesize openFlags=_openFlags; - - -+ (instancetype)databasePoolWithPath:(NSString *)aPath { - return FMDBReturnAutoreleased([[self alloc] initWithPath:aPath]); -} - -+ (instancetype)databasePoolWithURL:(NSURL *)url { - return FMDBReturnAutoreleased([[self alloc] initWithPath:url.path]); -} - -+ (instancetype)databasePoolWithPath:(NSString *)aPath flags:(int)openFlags { - return FMDBReturnAutoreleased([[self alloc] initWithPath:aPath flags:openFlags]); -} - -+ (instancetype)databasePoolWithURL:(NSURL *)url flags:(int)openFlags { - return FMDBReturnAutoreleased([[self alloc] initWithPath:url.path flags:openFlags]); -} - -- (instancetype)initWithURL:(NSURL *)url flags:(int)openFlags vfs:(NSString *)vfsName { - return [self initWithPath:url.path flags:openFlags vfs:vfsName]; -} - -- (instancetype)initWithPath:(NSString*)aPath flags:(int)openFlags vfs:(NSString *)vfsName { - - self = [super init]; - - if (self != nil) { - _path = [aPath copy]; - _lockQueue = dispatch_queue_create([[NSString stringWithFormat:@"fmdb.%@", self] UTF8String], NULL); - _databaseInPool = FMDBReturnRetained([NSMutableArray array]); - _databaseOutPool = FMDBReturnRetained([NSMutableArray array]); - _openFlags = openFlags; - _vfsName = [vfsName copy]; - } - - return self; -} - -- (instancetype)initWithPath:(NSString *)aPath flags:(int)openFlags { - return [self initWithPath:aPath flags:openFlags vfs:nil]; -} - -- (instancetype)initWithURL:(NSURL *)url flags:(int)openFlags { - return [self initWithPath:url.path flags:openFlags vfs:nil]; -} - -- (instancetype)initWithPath:(NSString*)aPath { - // default flags for sqlite3_open - return [self initWithPath:aPath flags:SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE]; -} - -- (instancetype)initWithURL:(NSURL *)url { - return [self initWithPath:url.path]; -} - -- (instancetype)init { - return [self initWithPath:nil]; -} - -+ (Class)databaseClass { - return [FMDatabase class]; -} - -- (void)dealloc { - - _delegate = 0x00; - FMDBRelease(_path); - FMDBRelease(_databaseInPool); - FMDBRelease(_databaseOutPool); - FMDBRelease(_vfsName); - - if (_lockQueue) { - FMDBDispatchQueueRelease(_lockQueue); - _lockQueue = 0x00; - } -#if ! __has_feature(objc_arc) - [super dealloc]; -#endif -} - - -- (void)executeLocked:(void (^)(void))aBlock { - dispatch_sync(_lockQueue, aBlock); -} - -- (void)pushDatabaseBackInPool:(FMDatabase*)db { - - if (!db) { // db can be null if we set an upper bound on the # of databases to create. - return; - } - - [self executeLocked:^() { - - if ([self->_databaseInPool containsObject:db]) { - [[NSException exceptionWithName:@"Database already in pool" reason:@"The FMDatabase being put back into the pool is already present in the pool" userInfo:nil] raise]; - } - - [self->_databaseInPool addObject:db]; - [self->_databaseOutPool removeObject:db]; - - }]; -} - -- (FMDatabase*)db { - - __block FMDatabase *db; - - - [self executeLocked:^() { - db = [self->_databaseInPool lastObject]; - - BOOL shouldNotifyDelegate = NO; - - if (db) { - [self->_databaseOutPool addObject:db]; - [self->_databaseInPool removeLastObject]; - } - else { - - if (self->_maximumNumberOfDatabasesToCreate) { - NSUInteger currentCount = [self->_databaseOutPool count] + [self->_databaseInPool count]; - - if (currentCount >= self->_maximumNumberOfDatabasesToCreate) { - NSLog(@"Maximum number of databases (%ld) has already been reached!", (long)currentCount); - return; - } - } - - db = [[[self class] databaseClass] databaseWithPath:self->_path]; - shouldNotifyDelegate = YES; - } - - //This ensures that the db is opened before returning -#if SQLITE_VERSION_NUMBER >= 3005000 - BOOL success = [db openWithFlags:self->_openFlags vfs:self->_vfsName]; -#else - BOOL success = [db open]; -#endif - if (success) { - if ([self->_delegate respondsToSelector:@selector(databasePool:shouldAddDatabaseToPool:)] && ![self->_delegate databasePool:self shouldAddDatabaseToPool:db]) { - [db close]; - db = 0x00; - } - else { - //It should not get added in the pool twice if lastObject was found - if (![self->_databaseOutPool containsObject:db]) { - [self->_databaseOutPool addObject:db]; - - if (shouldNotifyDelegate && [self->_delegate respondsToSelector:@selector(databasePool:didAddDatabase:)]) { - [self->_delegate databasePool:self didAddDatabase:db]; - } - } - } - } - else { - NSLog(@"Could not open up the database at path %@", self->_path); - db = 0x00; - } - }]; - - return db; -} - -- (NSUInteger)countOfCheckedInDatabases { - - __block NSUInteger count; - - [self executeLocked:^() { - count = [self->_databaseInPool count]; - }]; - - return count; -} - -- (NSUInteger)countOfCheckedOutDatabases { - - __block NSUInteger count; - - [self executeLocked:^() { - count = [self->_databaseOutPool count]; - }]; - - return count; -} - -- (NSUInteger)countOfOpenDatabases { - __block NSUInteger count; - - [self executeLocked:^() { - count = [self->_databaseOutPool count] + [self->_databaseInPool count]; - }]; - - return count; -} - -- (void)releaseAllDatabases { - [self executeLocked:^() { - [self->_databaseOutPool removeAllObjects]; - [self->_databaseInPool removeAllObjects]; - }]; -} - -- (void)inDatabase:(void (^)(FMDatabase *db))block { - - FMDatabase *db = [self db]; - - block(db); - - [self pushDatabaseBackInPool:db]; -} - -- (void)beginTransaction:(BOOL)useDeferred withBlock:(void (^)(FMDatabase *db, BOOL *rollback))block { - - BOOL shouldRollback = NO; - - FMDatabase *db = [self db]; - - if (useDeferred) { - [db beginDeferredTransaction]; - } - else { - [db beginTransaction]; - } - - - block(db, &shouldRollback); - - if (shouldRollback) { - [db rollback]; - } - else { - [db commit]; - } - - [self pushDatabaseBackInPool:db]; -} - -- (void)inDeferredTransaction:(void (^)(FMDatabase *db, BOOL *rollback))block { - [self beginTransaction:YES withBlock:block]; -} - -- (void)inTransaction:(void (^)(FMDatabase *db, BOOL *rollback))block { - [self beginTransaction:NO withBlock:block]; -} - -- (NSError*)inSavePoint:(void (^)(FMDatabase *db, BOOL *rollback))block { -#if SQLITE_VERSION_NUMBER >= 3007000 - static unsigned long savePointIdx = 0; - - NSString *name = [NSString stringWithFormat:@"savePoint%ld", savePointIdx++]; - - BOOL shouldRollback = NO; - - FMDatabase *db = [self db]; - - NSError *err = 0x00; - - if (![db startSavePointWithName:name error:&err]) { - [self pushDatabaseBackInPool:db]; - return err; - } - - block(db, &shouldRollback); - - if (shouldRollback) { - // We need to rollback and release this savepoint to remove it - [db rollbackToSavePointWithName:name error:&err]; - } - [db releaseSavePointWithName:name error:&err]; - - [self pushDatabaseBackInPool:db]; - - return err; -#else - NSString *errorMessage = NSLocalizedString(@"Save point functions require SQLite 3.7", nil); - if (self.logsErrors) NSLog(@"%@", errorMessage); - return [NSError errorWithDomain:@"FMDatabase" code:0 userInfo:@{NSLocalizedDescriptionKey : errorMessage}]; -#endif -} - -@end diff --git a/lib/ios/AirMaps/fmdb/FMDatabaseQueue.h b/lib/ios/AirMaps/fmdb/FMDatabaseQueue.h deleted file mode 100755 index 0a8b93816..000000000 --- a/lib/ios/AirMaps/fmdb/FMDatabaseQueue.h +++ /dev/null @@ -1,235 +0,0 @@ -// -// FMDatabaseQueue.h -// fmdb -// -// Created by August Mueller on 6/22/11. -// Copyright 2011 Flying Meat Inc. All rights reserved. -// - -#import - -NS_ASSUME_NONNULL_BEGIN - -@class FMDatabase; - -/** To perform queries and updates on multiple threads, you'll want to use `FMDatabaseQueue`. - - Using a single instance of `` from multiple threads at once is a bad idea. It has always been OK to make a `` object *per thread*. Just don't share a single instance across threads, and definitely not across multiple threads at the same time. - - Instead, use `FMDatabaseQueue`. Here's how to use it: - - First, make your queue. - - FMDatabaseQueue *queue = [FMDatabaseQueue databaseQueueWithPath:aPath]; - - Then use it like so: - - [queue inDatabase:^(FMDatabase *db) { - [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:1]]; - [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:2]]; - [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:3]]; - - FMResultSet *rs = [db executeQuery:@"select * from foo"]; - while ([rs next]) { - //… - } - }]; - - An easy way to wrap things up in a transaction can be done like this: - - [queue inTransaction:^(FMDatabase *db, BOOL *rollback) { - [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:1]]; - [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:2]]; - [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:3]]; - - if (whoopsSomethingWrongHappened) { - *rollback = YES; - return; - } - // etc… - [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:4]]; - }]; - - `FMDatabaseQueue` will run the blocks on a serialized queue (hence the name of the class). So if you call `FMDatabaseQueue`'s methods from multiple threads at the same time, they will be executed in the order they are received. This way queries and updates won't step on each other's toes, and every one is happy. - - ### See also - - - `` - - @warning Do not instantiate a single `` object and use it across multiple threads. Use `FMDatabaseQueue` instead. - - @warning The calls to `FMDatabaseQueue`'s methods are blocking. So even though you are passing along blocks, they will **not** be run on another thread. - - */ - -@interface FMDatabaseQueue : NSObject -/** Path of database */ - -@property (atomic, retain, nullable) NSString *path; - -/** Open flags */ - -@property (atomic, readonly) int openFlags; - -/** Custom virtual file system name */ - -@property (atomic, copy, nullable) NSString *vfsName; - -///---------------------------------------------------- -/// @name Initialization, opening, and closing of queue -///---------------------------------------------------- - -/** Create queue using path. - - @param aPath The file path of the database. - - @return The `FMDatabaseQueue` object. `nil` on error. - */ - -+ (instancetype)databaseQueueWithPath:(NSString * _Nullable)aPath; - -/** Create queue using file URL. - - @param url The file `NSURL` of the database. - - @return The `FMDatabaseQueue` object. `nil` on error. - */ - -+ (instancetype)databaseQueueWithURL:(NSURL * _Nullable)url; - -/** Create queue using path and specified flags. - - @param aPath The file path of the database. - @param openFlags Flags passed to the openWithFlags method of the database. - - @return The `FMDatabaseQueue` object. `nil` on error. - */ -+ (instancetype)databaseQueueWithPath:(NSString * _Nullable)aPath flags:(int)openFlags; - -/** Create queue using file URL and specified flags. - - @param url The file `NSURL` of the database. - @param openFlags Flags passed to the openWithFlags method of the database. - - @return The `FMDatabaseQueue` object. `nil` on error. - */ -+ (instancetype)databaseQueueWithURL:(NSURL * _Nullable)url flags:(int)openFlags; - -/** Create queue using path. - - @param aPath The file path of the database. - - @return The `FMDatabaseQueue` object. `nil` on error. - */ - -- (instancetype)initWithPath:(NSString * _Nullable)aPath; - -/** Create queue using file URL. - - @param url The file `NSURL of the database. - - @return The `FMDatabaseQueue` object. `nil` on error. - */ - -- (instancetype)initWithURL:(NSURL * _Nullable)url; - -/** Create queue using path and specified flags. - - @param aPath The file path of the database. - @param openFlags Flags passed to the openWithFlags method of the database. - - @return The `FMDatabaseQueue` object. `nil` on error. - */ - -- (instancetype)initWithPath:(NSString * _Nullable)aPath flags:(int)openFlags; - -/** Create queue using file URL and specified flags. - - @param url The file path of the database. - @param openFlags Flags passed to the openWithFlags method of the database. - - @return The `FMDatabaseQueue` object. `nil` on error. - */ - -- (instancetype)initWithURL:(NSURL * _Nullable)url flags:(int)openFlags; - -/** Create queue using path and specified flags. - - @param aPath The file path of the database. - @param openFlags Flags passed to the openWithFlags method of the database - @param vfsName The name of a custom virtual file system - - @return The `FMDatabaseQueue` object. `nil` on error. - */ - -- (instancetype)initWithPath:(NSString * _Nullable)aPath flags:(int)openFlags vfs:(NSString * _Nullable)vfsName; - -/** Create queue using file URL and specified flags. - - @param url The file `NSURL of the database. - @param openFlags Flags passed to the openWithFlags method of the database - @param vfsName The name of a custom virtual file system - - @return The `FMDatabaseQueue` object. `nil` on error. - */ - -- (instancetype)initWithURL:(NSURL * _Nullable)url flags:(int)openFlags vfs:(NSString * _Nullable)vfsName; - -/** Returns the Class of 'FMDatabase' subclass, that will be used to instantiate database object. - - Subclasses can override this method to return specified Class of 'FMDatabase' subclass. - - @return The Class of 'FMDatabase' subclass, that will be used to instantiate database object. - */ - -+ (Class)databaseClass; - -/** Close database used by queue. */ - -- (void)close; - -/** Interupt pending database operation. */ - -- (void)interrupt; - -///----------------------------------------------- -/// @name Dispatching database operations to queue -///----------------------------------------------- - -/** Synchronously perform database operations on queue. - - @param block The code to be run on the queue of `FMDatabaseQueue` - */ - -- (void)inDatabase:(__attribute__((noescape)) void (^)(FMDatabase *db))block; - -/** Synchronously perform database operations on queue, using transactions. - - @param block The code to be run on the queue of `FMDatabaseQueue` - */ - -- (void)inTransaction:(__attribute__((noescape)) void (^)(FMDatabase *db, BOOL *rollback))block; - -/** Synchronously perform database operations on queue, using deferred transactions. - - @param block The code to be run on the queue of `FMDatabaseQueue` - */ - -- (void)inDeferredTransaction:(__attribute__((noescape)) void (^)(FMDatabase *db, BOOL *rollback))block; - -///----------------------------------------------- -/// @name Dispatching database operations to queue -///----------------------------------------------- - -/** Synchronously perform database operations using save point. - - @param block The code to be run on the queue of `FMDatabaseQueue` - */ - -// NOTE: you can not nest these, since calling it will pull another database out of the pool and you'll get a deadlock. -// If you need to nest, use FMDatabase's startSavePointWithName:error: instead. -- (NSError * _Nullable)inSavePoint:(__attribute__((noescape)) void (^)(FMDatabase *db, BOOL *rollback))block; - -@end - -NS_ASSUME_NONNULL_END diff --git a/lib/ios/AirMaps/fmdb/FMDatabaseQueue.m b/lib/ios/AirMaps/fmdb/FMDatabaseQueue.m deleted file mode 100755 index f3f30cf26..000000000 --- a/lib/ios/AirMaps/fmdb/FMDatabaseQueue.m +++ /dev/null @@ -1,270 +0,0 @@ -// -// FMDatabaseQueue.m -// fmdb -// -// Created by August Mueller on 6/22/11. -// Copyright 2011 Flying Meat Inc. All rights reserved. -// - -#import "FMDatabaseQueue.h" -#import "FMDatabase.h" - -#if FMDB_SQLITE_STANDALONE -#import -#else -#import -#endif - -/* - - Note: we call [self retain]; before using dispatch_sync, just incase - FMDatabaseQueue is released on another thread and we're in the middle of doing - something in dispatch_sync - - */ - -/* - * A key used to associate the FMDatabaseQueue object with the dispatch_queue_t it uses. - * This in turn is used for deadlock detection by seeing if inDatabase: is called on - * the queue's dispatch queue, which should not happen and causes a deadlock. - */ -static const void * const kDispatchQueueSpecificKey = &kDispatchQueueSpecificKey; - -@interface FMDatabaseQueue () { - dispatch_queue_t _queue; - FMDatabase *_db; -} -@end - -@implementation FMDatabaseQueue - -+ (instancetype)databaseQueueWithPath:(NSString *)aPath { - FMDatabaseQueue *q = [[self alloc] initWithPath:aPath]; - - FMDBAutorelease(q); - - return q; -} - -+ (instancetype)databaseQueueWithURL:(NSURL *)url { - return [self databaseQueueWithPath:url.path]; -} - -+ (instancetype)databaseQueueWithPath:(NSString *)aPath flags:(int)openFlags { - FMDatabaseQueue *q = [[self alloc] initWithPath:aPath flags:openFlags]; - - FMDBAutorelease(q); - - return q; -} - -+ (instancetype)databaseQueueWithURL:(NSURL *)url flags:(int)openFlags { - return [self databaseQueueWithPath:url.path flags:openFlags]; -} - -+ (Class)databaseClass { - return [FMDatabase class]; -} - -- (instancetype)initWithURL:(NSURL *)url flags:(int)openFlags vfs:(NSString *)vfsName { - return [self initWithPath:url.path flags:openFlags vfs:vfsName]; -} - -- (instancetype)initWithPath:(NSString*)aPath flags:(int)openFlags vfs:(NSString *)vfsName { - self = [super init]; - - if (self != nil) { - - _db = [[[self class] databaseClass] databaseWithPath:aPath]; - FMDBRetain(_db); - -#if SQLITE_VERSION_NUMBER >= 3005000 - BOOL success = [_db openWithFlags:openFlags vfs:vfsName]; -#else - BOOL success = [_db open]; -#endif - if (!success) { - NSLog(@"Could not create database queue for path %@", aPath); - FMDBRelease(self); - return 0x00; - } - - _path = FMDBReturnRetained(aPath); - - _queue = dispatch_queue_create([[NSString stringWithFormat:@"fmdb.%@", self] UTF8String], NULL); - dispatch_queue_set_specific(_queue, kDispatchQueueSpecificKey, (__bridge void *)self, NULL); - _openFlags = openFlags; - _vfsName = [vfsName copy]; - } - - return self; -} - -- (instancetype)initWithPath:(NSString *)aPath flags:(int)openFlags { - return [self initWithPath:aPath flags:openFlags vfs:nil]; -} - -- (instancetype)initWithURL:(NSURL *)url flags:(int)openFlags { - return [self initWithPath:url.path flags:openFlags vfs:nil]; -} - -- (instancetype)initWithURL:(NSURL *)url { - return [self initWithPath:url.path]; -} - -- (instancetype)initWithPath:(NSString *)aPath { - // default flags for sqlite3_open - return [self initWithPath:aPath flags:SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE vfs:nil]; -} - -- (instancetype)init { - return [self initWithPath:nil]; -} - - -- (void)dealloc { - FMDBRelease(_db); - FMDBRelease(_path); - FMDBRelease(_vfsName); - - if (_queue) { - FMDBDispatchQueueRelease(_queue); - _queue = 0x00; - } -#if ! __has_feature(objc_arc) - [super dealloc]; -#endif -} - -- (void)close { - FMDBRetain(self); - dispatch_sync(_queue, ^() { - [self->_db close]; - FMDBRelease(_db); - self->_db = 0x00; - }); - FMDBRelease(self); -} - -- (void)interrupt { - [[self database] interrupt]; -} - -- (FMDatabase*)database { - if (!_db) { - _db = FMDBReturnRetained([[[self class] databaseClass] databaseWithPath:_path]); - -#if SQLITE_VERSION_NUMBER >= 3005000 - BOOL success = [_db openWithFlags:_openFlags vfs:_vfsName]; -#else - BOOL success = [_db open]; -#endif - if (!success) { - NSLog(@"FMDatabaseQueue could not reopen database for path %@", _path); - FMDBRelease(_db); - _db = 0x00; - return 0x00; - } - } - - return _db; -} - -- (void)inDatabase:(void (^)(FMDatabase *db))block { -#ifndef NDEBUG - /* Get the currently executing queue (which should probably be nil, but in theory could be another DB queue - * and then check it against self to make sure we're not about to deadlock. */ - FMDatabaseQueue *currentSyncQueue = (__bridge id)dispatch_get_specific(kDispatchQueueSpecificKey); - assert(currentSyncQueue != self && "inDatabase: was called reentrantly on the same queue, which would lead to a deadlock"); -#endif - - FMDBRetain(self); - - dispatch_sync(_queue, ^() { - - FMDatabase *db = [self database]; - block(db); - - if ([db hasOpenResultSets]) { - NSLog(@"Warning: there is at least one open result set around after performing [FMDatabaseQueue inDatabase:]"); - -#if defined(DEBUG) && DEBUG - NSSet *openSetCopy = FMDBReturnAutoreleased([[db valueForKey:@"_openResultSets"] copy]); - for (NSValue *rsInWrappedInATastyValueMeal in openSetCopy) { - FMResultSet *rs = (FMResultSet *)[rsInWrappedInATastyValueMeal pointerValue]; - NSLog(@"query: '%@'", [rs query]); - } -#endif - } - }); - - FMDBRelease(self); -} - -- (void)beginTransaction:(BOOL)useDeferred withBlock:(void (^)(FMDatabase *db, BOOL *rollback))block { - FMDBRetain(self); - dispatch_sync(_queue, ^() { - - BOOL shouldRollback = NO; - - if (useDeferred) { - [[self database] beginDeferredTransaction]; - } - else { - [[self database] beginTransaction]; - } - - block([self database], &shouldRollback); - - if (shouldRollback) { - [[self database] rollback]; - } - else { - [[self database] commit]; - } - }); - - FMDBRelease(self); -} - -- (void)inDeferredTransaction:(void (^)(FMDatabase *db, BOOL *rollback))block { - [self beginTransaction:YES withBlock:block]; -} - -- (void)inTransaction:(void (^)(FMDatabase *db, BOOL *rollback))block { - [self beginTransaction:NO withBlock:block]; -} - -- (NSError*)inSavePoint:(void (^)(FMDatabase *db, BOOL *rollback))block { -#if SQLITE_VERSION_NUMBER >= 3007000 - static unsigned long savePointIdx = 0; - __block NSError *err = 0x00; - FMDBRetain(self); - dispatch_sync(_queue, ^() { - - NSString *name = [NSString stringWithFormat:@"savePoint%ld", savePointIdx++]; - - BOOL shouldRollback = NO; - - if ([[self database] startSavePointWithName:name error:&err]) { - - block([self database], &shouldRollback); - - if (shouldRollback) { - // We need to rollback and release this savepoint to remove it - [[self database] rollbackToSavePointWithName:name error:&err]; - } - [[self database] releaseSavePointWithName:name error:&err]; - - } - }); - FMDBRelease(self); - return err; -#else - NSString *errorMessage = NSLocalizedString(@"Save point functions require SQLite 3.7", nil); - if (self.logsErrors) NSLog(@"%@", errorMessage); - return [NSError errorWithDomain:@"FMDatabase" code:0 userInfo:@{NSLocalizedDescriptionKey : errorMessage}]; -#endif -} - -@end diff --git a/lib/ios/AirMaps/fmdb/FMResultSet.h b/lib/ios/AirMaps/fmdb/FMResultSet.h deleted file mode 100644 index 805729109..000000000 --- a/lib/ios/AirMaps/fmdb/FMResultSet.h +++ /dev/null @@ -1,467 +0,0 @@ -#import - -NS_ASSUME_NONNULL_BEGIN - -#ifndef __has_feature // Optional. -#define __has_feature(x) 0 // Compatibility with non-clang compilers. -#endif - -#ifndef NS_RETURNS_NOT_RETAINED -#if __has_feature(attribute_ns_returns_not_retained) -#define NS_RETURNS_NOT_RETAINED __attribute__((ns_returns_not_retained)) -#else -#define NS_RETURNS_NOT_RETAINED -#endif -#endif - -@class FMDatabase; -@class FMStatement; - -/** Represents the results of executing a query on an ``. - - ### See also - - - `` - */ - -@interface FMResultSet : NSObject - -@property (nonatomic, retain, nullable) FMDatabase *parentDB; - -///----------------- -/// @name Properties -///----------------- - -/** Executed query */ - -@property (atomic, retain, nullable) NSString *query; - -/** `NSMutableDictionary` mapping column names to numeric index */ - -@property (readonly) NSMutableDictionary *columnNameToIndexMap; - -/** `FMStatement` used by result set. */ - -@property (atomic, retain, nullable) FMStatement *statement; - -///------------------------------------ -/// @name Creating and closing database -///------------------------------------ - -/** Create result set from `` - - @param statement A `` to be performed - - @param aDB A `` to be used - - @return A `FMResultSet` on success; `nil` on failure - */ - -+ (instancetype)resultSetWithStatement:(FMStatement *)statement usingParentDatabase:(FMDatabase*)aDB; - -/** Close result set */ - -- (void)close; - -///--------------------------------------- -/// @name Iterating through the result set -///--------------------------------------- - -/** Retrieve next row for result set. - - You must always invoke `next` or `nextWithError` before attempting to access the values returned in a query, even if you're only expecting one. - - @return `YES` if row successfully retrieved; `NO` if end of result set reached - - @see hasAnotherRow - */ - -- (BOOL)next; - -/** Retrieve next row for result set. - - You must always invoke `next` or `nextWithError` before attempting to access the values returned in a query, even if you're only expecting one. - - @param outErr A 'NSError' object to receive any error object (if any). - - @return 'YES' if row successfully retrieved; 'NO' if end of result set reached - - @see hasAnotherRow - */ - -- (BOOL)nextWithError:(NSError * _Nullable *)outErr; - -/** Did the last call to `` succeed in retrieving another row? - - @return `YES` if the last call to `` succeeded in retrieving another record; `NO` if not. - - @see next - - @warning The `hasAnotherRow` method must follow a call to ``. If the previous database interaction was something other than a call to `next`, then this method may return `NO`, whether there is another row of data or not. - */ - -- (BOOL)hasAnotherRow; - -///--------------------------------------------- -/// @name Retrieving information from result set -///--------------------------------------------- - -/** How many columns in result set - - @return Integer value of the number of columns. - */ - -@property (nonatomic, readonly) int columnCount; - -/** Column index for column name - - @param columnName `NSString` value of the name of the column. - - @return Zero-based index for column. - */ - -- (int)columnIndexForName:(NSString*)columnName; - -/** Column name for column index - - @param columnIdx Zero-based index for column. - - @return columnName `NSString` value of the name of the column. - */ - -- (NSString * _Nullable)columnNameForIndex:(int)columnIdx; - -/** Result set integer value for column. - - @param columnName `NSString` value of the name of the column. - - @return `int` value of the result set's column. - */ - -- (int)intForColumn:(NSString*)columnName; - -/** Result set integer value for column. - - @param columnIdx Zero-based index for column. - - @return `int` value of the result set's column. - */ - -- (int)intForColumnIndex:(int)columnIdx; - -/** Result set `long` value for column. - - @param columnName `NSString` value of the name of the column. - - @return `long` value of the result set's column. - */ - -- (long)longForColumn:(NSString*)columnName; - -/** Result set long value for column. - - @param columnIdx Zero-based index for column. - - @return `long` value of the result set's column. - */ - -- (long)longForColumnIndex:(int)columnIdx; - -/** Result set `long long int` value for column. - - @param columnName `NSString` value of the name of the column. - - @return `long long int` value of the result set's column. - */ - -- (long long int)longLongIntForColumn:(NSString*)columnName; - -/** Result set `long long int` value for column. - - @param columnIdx Zero-based index for column. - - @return `long long int` value of the result set's column. - */ - -- (long long int)longLongIntForColumnIndex:(int)columnIdx; - -/** Result set `unsigned long long int` value for column. - - @param columnName `NSString` value of the name of the column. - - @return `unsigned long long int` value of the result set's column. - */ - -- (unsigned long long int)unsignedLongLongIntForColumn:(NSString*)columnName; - -/** Result set `unsigned long long int` value for column. - - @param columnIdx Zero-based index for column. - - @return `unsigned long long int` value of the result set's column. - */ - -- (unsigned long long int)unsignedLongLongIntForColumnIndex:(int)columnIdx; - -/** Result set `BOOL` value for column. - - @param columnName `NSString` value of the name of the column. - - @return `BOOL` value of the result set's column. - */ - -- (BOOL)boolForColumn:(NSString*)columnName; - -/** Result set `BOOL` value for column. - - @param columnIdx Zero-based index for column. - - @return `BOOL` value of the result set's column. - */ - -- (BOOL)boolForColumnIndex:(int)columnIdx; - -/** Result set `double` value for column. - - @param columnName `NSString` value of the name of the column. - - @return `double` value of the result set's column. - - */ - -- (double)doubleForColumn:(NSString*)columnName; - -/** Result set `double` value for column. - - @param columnIdx Zero-based index for column. - - @return `double` value of the result set's column. - - */ - -- (double)doubleForColumnIndex:(int)columnIdx; - -/** Result set `NSString` value for column. - - @param columnName `NSString` value of the name of the column. - - @return String value of the result set's column. - - */ - -- (NSString * _Nullable)stringForColumn:(NSString*)columnName; - -/** Result set `NSString` value for column. - - @param columnIdx Zero-based index for column. - - @return String value of the result set's column. - */ - -- (NSString * _Nullable)stringForColumnIndex:(int)columnIdx; - -/** Result set `NSDate` value for column. - - @param columnName `NSString` value of the name of the column. - - @return Date value of the result set's column. - */ - -- (NSDate * _Nullable)dateForColumn:(NSString*)columnName; - -/** Result set `NSDate` value for column. - - @param columnIdx Zero-based index for column. - - @return Date value of the result set's column. - - */ - -- (NSDate * _Nullable)dateForColumnIndex:(int)columnIdx; - -/** Result set `NSData` value for column. - - This is useful when storing binary data in table (such as image or the like). - - @param columnName `NSString` value of the name of the column. - - @return Data value of the result set's column. - - */ - -- (NSData * _Nullable)dataForColumn:(NSString*)columnName; - -/** Result set `NSData` value for column. - - @param columnIdx Zero-based index for column. - - @return Data value of the result set's column. - */ - -- (NSData * _Nullable)dataForColumnIndex:(int)columnIdx; - -/** Result set `(const unsigned char *)` value for column. - - @param columnName `NSString` value of the name of the column. - - @return `(const unsigned char *)` value of the result set's column. - */ - -- (const unsigned char * _Nullable)UTF8StringForColumn:(NSString*)columnName; - -- (const unsigned char * _Nullable)UTF8StringForColumnName:(NSString*)columnName __deprecated_msg("Use UTF8StringForColumn instead"); - -/** Result set `(const unsigned char *)` value for column. - - @param columnIdx Zero-based index for column. - - @return `(const unsigned char *)` value of the result set's column. - */ - -- (const unsigned char * _Nullable)UTF8StringForColumnIndex:(int)columnIdx; - -/** Result set object for column. - - @param columnName Name of the column. - - @return Either `NSNumber`, `NSString`, `NSData`, or `NSNull`. If the column was `NULL`, this returns `[NSNull null]` object. - - @see objectForKeyedSubscript: - */ - -- (id _Nullable)objectForColumn:(NSString*)columnName; - -- (id _Nullable)objectForColumnName:(NSString*)columnName __deprecated_msg("Use objectForColumn instead"); - -/** Result set object for column. - - @param columnIdx Zero-based index for column. - - @return Either `NSNumber`, `NSString`, `NSData`, or `NSNull`. If the column was `NULL`, this returns `[NSNull null]` object. - - @see objectAtIndexedSubscript: - */ - -- (id _Nullable)objectForColumnIndex:(int)columnIdx; - -/** Result set object for column. - - This method allows the use of the "boxed" syntax supported in Modern Objective-C. For example, by defining this method, the following syntax is now supported: - - id result = rs[@"employee_name"]; - - This simplified syntax is equivalent to calling: - - id result = [rs objectForKeyedSubscript:@"employee_name"]; - - which is, it turns out, equivalent to calling: - - id result = [rs objectForColumnName:@"employee_name"]; - - @param columnName `NSString` value of the name of the column. - - @return Either `NSNumber`, `NSString`, `NSData`, or `NSNull`. If the column was `NULL`, this returns `[NSNull null]` object. - */ - -- (id _Nullable)objectForKeyedSubscript:(NSString *)columnName; - -/** Result set object for column. - - This method allows the use of the "boxed" syntax supported in Modern Objective-C. For example, by defining this method, the following syntax is now supported: - - id result = rs[0]; - - This simplified syntax is equivalent to calling: - - id result = [rs objectForKeyedSubscript:0]; - - which is, it turns out, equivalent to calling: - - id result = [rs objectForColumnName:0]; - - @param columnIdx Zero-based index for column. - - @return Either `NSNumber`, `NSString`, `NSData`, or `NSNull`. If the column was `NULL`, this returns `[NSNull null]` object. - */ - -- (id _Nullable)objectAtIndexedSubscript:(int)columnIdx; - -/** Result set `NSData` value for column. - - @param columnName `NSString` value of the name of the column. - - @return Data value of the result set's column. - - @warning If you are going to use this data after you iterate over the next row, or after you close the -result set, make sure to make a copy of the data first (or just use ``/``) -If you don't, you're going to be in a world of hurt when you try and use the data. - - */ - -- (NSData * _Nullable)dataNoCopyForColumn:(NSString *)columnName NS_RETURNS_NOT_RETAINED; - -/** Result set `NSData` value for column. - - @param columnIdx Zero-based index for column. - - @return Data value of the result set's column. - - @warning If you are going to use this data after you iterate over the next row, or after you close the - result set, make sure to make a copy of the data first (or just use ``/``) - If you don't, you're going to be in a world of hurt when you try and use the data. - - */ - -- (NSData * _Nullable)dataNoCopyForColumnIndex:(int)columnIdx NS_RETURNS_NOT_RETAINED; - -/** Is the column `NULL`? - - @param columnIdx Zero-based index for column. - - @return `YES` if column is `NULL`; `NO` if not `NULL`. - */ - -- (BOOL)columnIndexIsNull:(int)columnIdx; - -/** Is the column `NULL`? - - @param columnName `NSString` value of the name of the column. - - @return `YES` if column is `NULL`; `NO` if not `NULL`. - */ - -- (BOOL)columnIsNull:(NSString*)columnName; - - -/** Returns a dictionary of the row results mapped to case sensitive keys of the column names. - - @warning The keys to the dictionary are case sensitive of the column names. - */ - -@property (nonatomic, readonly, nullable) NSDictionary *resultDictionary; - -/** Returns a dictionary of the row results - - @see resultDictionary - - @warning **Deprecated**: Please use `` instead. Also, beware that `` is case sensitive! - */ - -- (NSDictionary * _Nullable)resultDict __deprecated_msg("Use resultDictionary instead"); - -///----------------------------- -/// @name Key value coding magic -///----------------------------- - -/** Performs `setValue` to yield support for key value observing. - - @param object The object for which the values will be set. This is the key-value-coding compliant object that you might, for example, observe. - - */ - -- (void)kvcMagic:(id)object; - - -@end - -NS_ASSUME_NONNULL_END diff --git a/lib/ios/AirMaps/fmdb/FMResultSet.m b/lib/ios/AirMaps/fmdb/FMResultSet.m deleted file mode 100644 index 2231e4761..000000000 --- a/lib/ios/AirMaps/fmdb/FMResultSet.m +++ /dev/null @@ -1,432 +0,0 @@ -#import "FMResultSet.h" -#import "FMDatabase.h" -#import "unistd.h" - -#if FMDB_SQLITE_STANDALONE -#import -#else -#import -#endif - -@interface FMDatabase () -- (void)resultSetDidClose:(FMResultSet *)resultSet; -@end - -@interface FMResultSet () { - NSMutableDictionary *_columnNameToIndexMap; -} -@end - -@implementation FMResultSet - -+ (instancetype)resultSetWithStatement:(FMStatement *)statement usingParentDatabase:(FMDatabase*)aDB { - - FMResultSet *rs = [[FMResultSet alloc] init]; - - [rs setStatement:statement]; - [rs setParentDB:aDB]; - - NSParameterAssert(![statement inUse]); - [statement setInUse:YES]; // weak reference - - return FMDBReturnAutoreleased(rs); -} - -#if ! __has_feature(objc_arc) -- (void)finalize { - [self close]; - [super finalize]; -} -#endif - -- (void)dealloc { - [self close]; - - FMDBRelease(_query); - _query = nil; - - FMDBRelease(_columnNameToIndexMap); - _columnNameToIndexMap = nil; - -#if ! __has_feature(objc_arc) - [super dealloc]; -#endif -} - -- (void)close { - [_statement reset]; - FMDBRelease(_statement); - _statement = nil; - - // we don't need this anymore... (i think) - //[_parentDB setInUse:NO]; - [_parentDB resultSetDidClose:self]; - _parentDB = nil; -} - -- (int)columnCount { - return sqlite3_column_count([_statement statement]); -} - -- (NSMutableDictionary *)columnNameToIndexMap { - if (!_columnNameToIndexMap) { - int columnCount = sqlite3_column_count([_statement statement]); - _columnNameToIndexMap = [[NSMutableDictionary alloc] initWithCapacity:(NSUInteger)columnCount]; - int columnIdx = 0; - for (columnIdx = 0; columnIdx < columnCount; columnIdx++) { - [_columnNameToIndexMap setObject:[NSNumber numberWithInt:columnIdx] - forKey:[[NSString stringWithUTF8String:sqlite3_column_name([_statement statement], columnIdx)] lowercaseString]]; - } - } - return _columnNameToIndexMap; -} - -- (void)kvcMagic:(id)object { - - int columnCount = sqlite3_column_count([_statement statement]); - - int columnIdx = 0; - for (columnIdx = 0; columnIdx < columnCount; columnIdx++) { - - const char *c = (const char *)sqlite3_column_text([_statement statement], columnIdx); - - // check for a null row - if (c) { - NSString *s = [NSString stringWithUTF8String:c]; - - [object setValue:s forKey:[NSString stringWithUTF8String:sqlite3_column_name([_statement statement], columnIdx)]]; - } - } -} - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-implementations" - -- (NSDictionary *)resultDict { - - NSUInteger num_cols = (NSUInteger)sqlite3_data_count([_statement statement]); - - if (num_cols > 0) { - NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithCapacity:num_cols]; - - NSEnumerator *columnNames = [[self columnNameToIndexMap] keyEnumerator]; - NSString *columnName = nil; - while ((columnName = [columnNames nextObject])) { - id objectValue = [self objectForColumnName:columnName]; - [dict setObject:objectValue forKey:columnName]; - } - - return FMDBReturnAutoreleased([dict copy]); - } - else { - NSLog(@"Warning: There seem to be no columns in this set."); - } - - return nil; -} - -#pragma clang diagnostic pop - -- (NSDictionary*)resultDictionary { - - NSUInteger num_cols = (NSUInteger)sqlite3_data_count([_statement statement]); - - if (num_cols > 0) { - NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithCapacity:num_cols]; - - int columnCount = sqlite3_column_count([_statement statement]); - - int columnIdx = 0; - for (columnIdx = 0; columnIdx < columnCount; columnIdx++) { - - NSString *columnName = [NSString stringWithUTF8String:sqlite3_column_name([_statement statement], columnIdx)]; - id objectValue = [self objectForColumnIndex:columnIdx]; - [dict setObject:objectValue forKey:columnName]; - } - - return dict; - } - else { - NSLog(@"Warning: There seem to be no columns in this set."); - } - - return nil; -} - - - - -- (BOOL)next { - return [self nextWithError:nil]; -} - -- (BOOL)nextWithError:(NSError **)outErr { - - int rc = sqlite3_step([_statement statement]); - - if (SQLITE_BUSY == rc || SQLITE_LOCKED == rc) { - NSLog(@"%s:%d Database busy (%@)", __FUNCTION__, __LINE__, [_parentDB databasePath]); - NSLog(@"Database busy"); - if (outErr) { - *outErr = [_parentDB lastError]; - } - } - else if (SQLITE_DONE == rc || SQLITE_ROW == rc) { - // all is well, let's return. - } - else if (SQLITE_ERROR == rc) { - NSLog(@"Error calling sqlite3_step (%d: %s) rs", rc, sqlite3_errmsg([_parentDB sqliteHandle])); - if (outErr) { - *outErr = [_parentDB lastError]; - } - } - else if (SQLITE_MISUSE == rc) { - // uh oh. - NSLog(@"Error calling sqlite3_step (%d: %s) rs", rc, sqlite3_errmsg([_parentDB sqliteHandle])); - if (outErr) { - if (_parentDB) { - *outErr = [_parentDB lastError]; - } - else { - // If 'next' or 'nextWithError' is called after the result set is closed, - // we need to return the appropriate error. - NSDictionary* errorMessage = [NSDictionary dictionaryWithObject:@"parentDB does not exist" forKey:NSLocalizedDescriptionKey]; - *outErr = [NSError errorWithDomain:@"FMDatabase" code:SQLITE_MISUSE userInfo:errorMessage]; - } - - } - } - else { - // wtf? - NSLog(@"Unknown error calling sqlite3_step (%d: %s) rs", rc, sqlite3_errmsg([_parentDB sqliteHandle])); - if (outErr) { - *outErr = [_parentDB lastError]; - } - } - - - if (rc != SQLITE_ROW) { - [self close]; - } - - return (rc == SQLITE_ROW); -} - -- (BOOL)hasAnotherRow { - return sqlite3_errcode([_parentDB sqliteHandle]) == SQLITE_ROW; -} - -- (int)columnIndexForName:(NSString*)columnName { - columnName = [columnName lowercaseString]; - - NSNumber *n = [[self columnNameToIndexMap] objectForKey:columnName]; - - if (n != nil) { - return [n intValue]; - } - - NSLog(@"Warning: I could not find the column named '%@'.", columnName); - - return -1; -} - -- (int)intForColumn:(NSString*)columnName { - return [self intForColumnIndex:[self columnIndexForName:columnName]]; -} - -- (int)intForColumnIndex:(int)columnIdx { - return sqlite3_column_int([_statement statement], columnIdx); -} - -- (long)longForColumn:(NSString*)columnName { - return [self longForColumnIndex:[self columnIndexForName:columnName]]; -} - -- (long)longForColumnIndex:(int)columnIdx { - return (long)sqlite3_column_int64([_statement statement], columnIdx); -} - -- (long long int)longLongIntForColumn:(NSString*)columnName { - return [self longLongIntForColumnIndex:[self columnIndexForName:columnName]]; -} - -- (long long int)longLongIntForColumnIndex:(int)columnIdx { - return sqlite3_column_int64([_statement statement], columnIdx); -} - -- (unsigned long long int)unsignedLongLongIntForColumn:(NSString*)columnName { - return [self unsignedLongLongIntForColumnIndex:[self columnIndexForName:columnName]]; -} - -- (unsigned long long int)unsignedLongLongIntForColumnIndex:(int)columnIdx { - return (unsigned long long int)[self longLongIntForColumnIndex:columnIdx]; -} - -- (BOOL)boolForColumn:(NSString*)columnName { - return [self boolForColumnIndex:[self columnIndexForName:columnName]]; -} - -- (BOOL)boolForColumnIndex:(int)columnIdx { - return ([self intForColumnIndex:columnIdx] != 0); -} - -- (double)doubleForColumn:(NSString*)columnName { - return [self doubleForColumnIndex:[self columnIndexForName:columnName]]; -} - -- (double)doubleForColumnIndex:(int)columnIdx { - return sqlite3_column_double([_statement statement], columnIdx); -} - -- (NSString *)stringForColumnIndex:(int)columnIdx { - - if (sqlite3_column_type([_statement statement], columnIdx) == SQLITE_NULL || (columnIdx < 0) || columnIdx >= sqlite3_column_count([_statement statement])) { - return nil; - } - - const char *c = (const char *)sqlite3_column_text([_statement statement], columnIdx); - - if (!c) { - // null row. - return nil; - } - - return [NSString stringWithUTF8String:c]; -} - -- (NSString*)stringForColumn:(NSString*)columnName { - return [self stringForColumnIndex:[self columnIndexForName:columnName]]; -} - -- (NSDate*)dateForColumn:(NSString*)columnName { - return [self dateForColumnIndex:[self columnIndexForName:columnName]]; -} - -- (NSDate*)dateForColumnIndex:(int)columnIdx { - - if (sqlite3_column_type([_statement statement], columnIdx) == SQLITE_NULL || (columnIdx < 0) || columnIdx >= sqlite3_column_count([_statement statement])) { - return nil; - } - - return [_parentDB hasDateFormatter] ? [_parentDB dateFromString:[self stringForColumnIndex:columnIdx]] : [NSDate dateWithTimeIntervalSince1970:[self doubleForColumnIndex:columnIdx]]; -} - - -- (NSData*)dataForColumn:(NSString*)columnName { - return [self dataForColumnIndex:[self columnIndexForName:columnName]]; -} - -- (NSData*)dataForColumnIndex:(int)columnIdx { - - if (sqlite3_column_type([_statement statement], columnIdx) == SQLITE_NULL || (columnIdx < 0) || columnIdx >= sqlite3_column_count([_statement statement])) { - return nil; - } - - const char *dataBuffer = sqlite3_column_blob([_statement statement], columnIdx); - int dataSize = sqlite3_column_bytes([_statement statement], columnIdx); - - if (dataBuffer == NULL) { - return nil; - } - - return [NSData dataWithBytes:(const void *)dataBuffer length:(NSUInteger)dataSize]; -} - - -- (NSData*)dataNoCopyForColumn:(NSString*)columnName { - return [self dataNoCopyForColumnIndex:[self columnIndexForName:columnName]]; -} - -- (NSData*)dataNoCopyForColumnIndex:(int)columnIdx { - - if (sqlite3_column_type([_statement statement], columnIdx) == SQLITE_NULL || (columnIdx < 0) || columnIdx >= sqlite3_column_count([_statement statement])) { - return nil; - } - - const char *dataBuffer = sqlite3_column_blob([_statement statement], columnIdx); - int dataSize = sqlite3_column_bytes([_statement statement], columnIdx); - - NSData *data = [NSData dataWithBytesNoCopy:(void *)dataBuffer length:(NSUInteger)dataSize freeWhenDone:NO]; - - return data; -} - - -- (BOOL)columnIndexIsNull:(int)columnIdx { - return sqlite3_column_type([_statement statement], columnIdx) == SQLITE_NULL; -} - -- (BOOL)columnIsNull:(NSString*)columnName { - return [self columnIndexIsNull:[self columnIndexForName:columnName]]; -} - -- (const unsigned char *)UTF8StringForColumnIndex:(int)columnIdx { - - if (sqlite3_column_type([_statement statement], columnIdx) == SQLITE_NULL || (columnIdx < 0) || columnIdx >= sqlite3_column_count([_statement statement])) { - return nil; - } - - return sqlite3_column_text([_statement statement], columnIdx); -} - -- (const unsigned char *)UTF8StringForColumn:(NSString*)columnName { - return [self UTF8StringForColumnIndex:[self columnIndexForName:columnName]]; -} - -- (const unsigned char *)UTF8StringForColumnName:(NSString*)columnName { - return [self UTF8StringForColumn:columnName]; -} - -- (id)objectForColumnIndex:(int)columnIdx { - if (columnIdx < 0 || columnIdx >= sqlite3_column_count([_statement statement])) { - return nil; - } - - int columnType = sqlite3_column_type([_statement statement], columnIdx); - - id returnValue = nil; - - if (columnType == SQLITE_INTEGER) { - returnValue = [NSNumber numberWithLongLong:[self longLongIntForColumnIndex:columnIdx]]; - } - else if (columnType == SQLITE_FLOAT) { - returnValue = [NSNumber numberWithDouble:[self doubleForColumnIndex:columnIdx]]; - } - else if (columnType == SQLITE_BLOB) { - returnValue = [self dataForColumnIndex:columnIdx]; - } - else { - //default to a string for everything else - returnValue = [self stringForColumnIndex:columnIdx]; - } - - if (returnValue == nil) { - returnValue = [NSNull null]; - } - - return returnValue; -} - -- (id)objectForColumnName:(NSString*)columnName { - return [self objectForColumn:columnName]; -} - -- (id)objectForColumn:(NSString*)columnName { - return [self objectForColumnIndex:[self columnIndexForName:columnName]]; -} - -// returns autoreleased NSString containing the name of the column in the result set -- (NSString*)columnNameForIndex:(int)columnIdx { - return [NSString stringWithUTF8String: sqlite3_column_name([_statement statement], columnIdx)]; -} - -- (id)objectAtIndexedSubscript:(int)columnIdx { - return [self objectForColumnIndex:columnIdx]; -} - -- (id)objectForKeyedSubscript:(NSString *)columnName { - return [self objectForColumn:columnName]; -} - - -@end From 83c1a0186fccf2ef3a4bc7950717948c6fd09fc8 Mon Sep 17 00:00:00 2001 From: Hinrich Date: Tue, 14 Aug 2018 16:57:49 +0200 Subject: [PATCH 0483/1148] docs: pin color limitations for android (#2429) --- docs/marker.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/marker.md b/docs/marker.md index 53fdbedc3..97170b02b 100644 --- a/docs/marker.md +++ b/docs/marker.md @@ -7,7 +7,7 @@ | `title` | `String` | | The title of the marker. This is only used if the component has no children that are a ``, in which case the default callout behavior will be used, which will show both the `title` and the `description`, if provided. | `description` | `String` | | The description of the marker. This is only used if the component has no children that are a ``, in which case the default callout behavior will be used, which will show both the `title` and the `description`, if provided. | `image` | `ImageSource` | | A custom image to be used as the marker's icon. Only local image resources are allowed to be used. -| `pinColor` | `Color` | | If no custom marker view or custom image is provided, the platform default pin will be used, which can be customized by this color. Ignored if a custom marker is being used. +| `pinColor` | `Color` | | If no custom marker view or custom image is provided, the platform default pin will be used, which can be customized by this color. Ignored if a custom marker is being used.

For Android, the set of available colors is limited. Unsupported colors will fall back to red. See [#887](https://github.com/react-community/react-native-maps/issues/887) for more information. | `coordinate` | `LatLng` | | The coordinate for the marker. | `centerOffset` | `Point` | (0, 0) | The offset (in points) at which to display the view.

By default, the center point of an annotation view is placed at the coordinate point of the associated annotation. You can use this property to reposition the annotation view as needed. This x and y offset values are measured in points. Positive offset values move the annotation view down and to the right, while negative values move it up and to the left.

For Google Maps, see the `anchor` prop. | `calloutOffset` | `Point` | (0, 0) | The offset (in points) at which to place the callout bubble.

This property determines the additional distance by which to move the callout bubble. When this property is set to (0, 0), the anchor point of the callout bubble is placed on the top-center point of the marker view’s frame. Specifying positive offset values moves the callout bubble down and to the right, while specifying negative values moves it up and to the left.

For Google Maps, see the `calloutAnchor` prop. From 108bf755ba0ff0a7b9cdc1b6d29d9d9593b44ffe Mon Sep 17 00:00:00 2001 From: Stephen Kempin Date: Tue, 14 Aug 2018 15:58:10 +0100 Subject: [PATCH 0484/1148] Adding overlaying components details (#2425) How to overlay other React components on top of the `MapView`. This was not clear from the documentation and took some research to find a solution. --- README.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/README.md b/README.md index e6e08cf7f..089b31073 100644 --- a/README.md +++ b/README.md @@ -221,6 +221,23 @@ For Android: LocalTile is still just overlay over original map tiles. It means t See [OSM Wiki](https://wiki.openstreetmap.org/wiki/Category:Tile_downloading) for how to download tiles for offline usage. +### Overlaying other components on the map + +Place components you that wish to overlay `MapView` underneath the `MapView` closing tag. Absolutely position these elements. + +```jsx +render() { + return ( + + + ); +} +``` + ### Customizing the map style Create the json object, or download a generated one from the [google style generator](https://mapstyle.withgoogle.com/). From 6fd2483cb2a9405f4346a26415e46ad3507fb8f9 Mon Sep 17 00:00:00 2001 From: "ITONE\\bussakorn.wonghom" <> Date: Wed, 22 Aug 2018 15:46:01 +0700 Subject: [PATCH 0485/1148] Add indoor events support for Android/iOS --- docs/mapview.md | 19 +++++ example/App.js | 2 + example/examples/IndoorMap.js | 72 ++++++++++++++++ .../android/react/maps/AirMapManager.java | 14 ++- .../airbnb/android/react/maps/AirMapView.java | 74 +++++++++++++++- lib/components/MapView.js | 13 +++ lib/ios/AirGoogleMaps/AIRGoogleMap.h | 3 + lib/ios/AirGoogleMaps/AIRGoogleMap.m | 8 ++ lib/ios/AirGoogleMaps/AIRGoogleMapManager.h | 2 + lib/ios/AirGoogleMaps/AIRGoogleMapManager.m | 85 ++++++++++++++++++- 10 files changed, 287 insertions(+), 5 deletions(-) create mode 100644 example/examples/IndoorMap.js diff --git a/docs/mapview.md b/docs/mapview.md index edbe23a85..4f055da7a 100644 --- a/docs/mapview.md +++ b/docs/mapview.md @@ -62,6 +62,8 @@ To access event data, you will need to use `e.nativeEvent`. For example, `onPres | `onMarkerDragStart` | `{ coordinate: LatLng, position: Point }` | Callback that is called when the user initiates a drag on a marker (if it is draggable) | `onMarkerDrag` | `{ coordinate: LatLng, position: Point }` | Callback called continuously as a marker is dragged | `onMarkerDragEnd` | `{ coordinate: LatLng, position: Point }` | Callback that is called when a drag on a marker finishes. This is usually the point you will want to setState on the marker's coordinate again +| `onIndoorLevelActivated` | `IndoorLevel` | Callback that is called when a level on indoor building is activated +| `onIndoorBuildingFocused` | `IndoorBuilding` | Callback that is called when a indoor building is focused/unfocused @@ -75,6 +77,7 @@ To access event data, you will need to use `e.nativeEvent`. For example, `onPres | `animateToBearing` | `bearing: Number`, `duration: Number` | | `animateToViewingAngle` | `angle: Number`, `duration: Number` | | `setMapBoundaries` | `northEast: LatLng`, `southWest: LatLng` | `GoogleMaps only` +| `setIndoorActiveLevelIndex` | `levelIndex: Number` | | `fitToElements` | `animated: Boolean` | | `fitToSuppliedMarkers` | `markerIDs: String[]`, `animated: Boolean` | If you need to use this in `ComponentDidMount`, make sure you put it in a timeout or it will cause performance problems. | `fitToCoordinates` | `coordinates: Array, options: { edgePadding: EdgePadding, animated: Boolean }` | If called in `ComponentDidMount` in android, it will cause an exception. It is recommended to call it from the MapView `onLayout` event. @@ -161,3 +164,19 @@ type KmlContainer { markers: [Marker] } ``` + +``` +type IndoorBuilding { + underground: boolean, + activeLevelIndex: Number, + levels: Array, +} +``` + +``` +type IndoorLevel { + activeLevelIndex: Number, + name: String, + shortName: String, +} +``` diff --git a/example/App.js b/example/App.js index 7b6231e61..9c000ddc9 100644 --- a/example/App.js +++ b/example/App.js @@ -42,6 +42,7 @@ import ImageOverlayWithAssets from './examples/ImageOverlayWithAssets'; import ImageOverlayWithURL from './examples/ImageOverlayWithURL'; import AnimatedNavigation from './examples/AnimatedNavigation'; import OnPoiClick from './examples/OnPoiClick'; +import IndoorMap from './examples/IndoorMap'; const IOS = Platform.OS === 'ios'; const ANDROID = Platform.OS === 'android'; @@ -162,6 +163,7 @@ class App extends React.Component { [ImageOverlayWithURL, 'Image Overlay Component with URL', true], [AnimatedNavigation, 'Animated Map Navigation', true], [OnPoiClick, 'On Poi Click', true], + [IndoorMap, 'Indoor Map', true], ] // Filter out examples that are not yet supported for Google Maps on iOS. .filter(example => ANDROID || (IOS && (example[2] || !this.state.useGoogleMaps))) diff --git a/example/examples/IndoorMap.js b/example/examples/IndoorMap.js new file mode 100644 index 000000000..bcb6290bf --- /dev/null +++ b/example/examples/IndoorMap.js @@ -0,0 +1,72 @@ +import React from 'react'; +import { + StyleSheet, + View, + Dimensions, + Button, + Alert, +} from 'react-native'; + import MapView from 'react-native-maps'; + const { width, height } = Dimensions.get('window'); + const ASPECT_RATIO = width / height; +const LATITUDE = 1.3039991; +const LONGITUDE = 103.8316911; +// const LATITUDE = 37.6167451; +// const LONGITUDE = -122.3876189; +const LATITUDE_DELTA = 0.003; +const LONGITUDE_DELTA = LATITUDE_DELTA * ASPECT_RATIO; + class IndoorMap extends React.Component { + constructor(props) { + super(props); + this.setIndoorLevel = this.setIndoorLevel.bind(this); + } + handleIndoorFocus(event) { + const { indoorBuilding } = event.nativeEvent; + const { defaultLevelIndex, levels } = indoorBuilding; + const levelNames = levels.map(lv => lv.name || ''); + const msg = `Default Level: ${defaultLevelIndex}\nLevels: ${levelNames.toString()}`; + Alert.alert( + 'Indoor building focused', + msg + ); + } + setIndoorLevel(level) { + this.map.setIndoorActiveLevelIndex(level); + } + render() { + return ( + + { this.map = map; }} + /> +