react-native-maps 1.21.0-alpha.6 → 1.21.0-alpha.60

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (132) hide show
  1. package/android/build.gradle +32 -8
  2. package/android/generated/java/com/facebook/fbreact/specs/NativeAirMapsModuleSpec.java +63 -0
  3. package/android/generated/java/com/facebook/react/viewmanagers/RNMapsMapViewManagerDelegate.java +199 -0
  4. package/android/generated/java/com/facebook/react/viewmanagers/RNMapsMapViewManagerInterface.java +71 -0
  5. package/android/generated/java/com/facebook/react/viewmanagers/RNMapsMarkerManagerDelegate.java +103 -0
  6. package/android/generated/java/com/facebook/react/viewmanagers/RNMapsMarkerManagerInterface.java +39 -0
  7. package/android/generated/jni/CMakeLists.txt +36 -0
  8. package/android/generated/jni/RNMapsSpecs-generated.cpp +68 -0
  9. package/android/generated/jni/RNMapsSpecs.h +31 -0
  10. package/android/generated/jni/react/renderer/components/RNMapsSpecs/ComponentDescriptors.cpp +25 -0
  11. package/android/generated/jni/react/renderer/components/RNMapsSpecs/ComponentDescriptors.h +27 -0
  12. package/android/generated/jni/react/renderer/components/RNMapsSpecs/EventEmitters.cpp +896 -0
  13. package/android/generated/jni/react/renderer/components/RNMapsSpecs/EventEmitters.h +765 -0
  14. package/android/generated/jni/react/renderer/components/RNMapsSpecs/Props.cpp +146 -0
  15. package/android/generated/jni/react/renderer/components/RNMapsSpecs/Props.h +1047 -0
  16. package/android/generated/jni/react/renderer/components/RNMapsSpecs/RNMapsSpecsJSI-generated.cpp +74 -0
  17. package/android/generated/jni/react/renderer/components/RNMapsSpecs/RNMapsSpecsJSI.h +264 -0
  18. package/android/generated/jni/react/renderer/components/RNMapsSpecs/ShadowNodes.cpp +20 -0
  19. package/android/generated/jni/react/renderer/components/RNMapsSpecs/ShadowNodes.h +65 -0
  20. package/android/generated/jni/react/renderer/components/RNMapsSpecs/States.cpp +16 -0
  21. package/android/generated/jni/react/renderer/components/RNMapsSpecs/States.h +65 -0
  22. package/android/src/main/java/com/rnmaps/fabric/JSONUtil.java +86 -0
  23. package/android/src/main/java/com/rnmaps/fabric/MapViewManager.java +577 -0
  24. package/android/src/main/java/com/rnmaps/fabric/MarkerManager.java +176 -0
  25. package/android/src/main/java/com/rnmaps/fabric/NativeAirMapsModule.java +25 -2
  26. package/android/src/main/java/com/rnmaps/fabric/event/OnCalloutPressEvent.java +25 -0
  27. package/android/src/main/java/com/rnmaps/fabric/event/OnDeselectEvent.java +28 -0
  28. package/android/src/main/java/com/rnmaps/fabric/event/OnDragEndEvent.java +28 -0
  29. package/android/src/main/java/com/rnmaps/fabric/event/OnDragEvent.java +28 -0
  30. package/android/src/main/java/com/rnmaps/fabric/event/OnDragStartEvent.java +28 -0
  31. package/android/src/main/java/com/rnmaps/fabric/event/OnLongPressEvent.java +28 -0
  32. package/android/src/main/java/com/rnmaps/fabric/event/OnMapReadyEvent.java +29 -0
  33. package/android/src/main/java/com/rnmaps/fabric/event/OnMarkerDeselectEvent.java +28 -0
  34. package/android/src/main/java/com/rnmaps/fabric/event/OnMarkerDragEndEvent.java +28 -0
  35. package/android/src/main/java/com/rnmaps/fabric/event/OnMarkerDragEvent.java +28 -0
  36. package/android/src/main/java/com/rnmaps/fabric/event/OnMarkerDragStartEvent.java +28 -0
  37. package/android/src/main/java/com/rnmaps/fabric/event/OnMarkerPressEvent.java +28 -0
  38. package/android/src/main/java/com/rnmaps/fabric/event/OnMarkerSelectEvent.java +28 -0
  39. package/android/src/main/java/com/rnmaps/fabric/event/OnPoiClickEvent.java +27 -0
  40. package/android/src/main/java/com/rnmaps/fabric/event/OnPressEvent.java +27 -0
  41. package/android/src/main/java/com/rnmaps/fabric/event/OnRegionChangeEvent.java +48 -0
  42. package/android/src/main/java/com/rnmaps/fabric/event/OnSelectEvent.java +28 -0
  43. package/android/src/main/java/com/rnmaps/fabric/event/OnUserLocationChangeEvent.java +28 -0
  44. package/android/src/main/java/com/rnmaps/maps/MapAirModulePackage.java +18 -2
  45. package/android/src/main/java/com/rnmaps/maps/MapManager.java +14 -14
  46. package/android/src/main/java/com/rnmaps/maps/MapMarker.java +53 -1
  47. package/android/src/main/java/com/rnmaps/maps/MapView.java +1613 -1346
  48. package/ios/AirGoogleMaps/AIRGoogleMap.h +8 -2
  49. package/ios/AirGoogleMaps/AIRGoogleMap.m +243 -55
  50. package/ios/AirGoogleMaps/AIRGoogleMapCircle.h +0 -1
  51. package/ios/AirGoogleMaps/AIRGoogleMapCircle.m +23 -11
  52. package/ios/AirGoogleMaps/AIRGoogleMapCoordinate.h +13 -0
  53. package/ios/AirGoogleMaps/AIRGoogleMapCoordinate.m +10 -0
  54. package/ios/AirGoogleMaps/AIRGoogleMapManager.h +7 -0
  55. package/ios/AirGoogleMaps/AIRGoogleMapManager.m +30 -119
  56. package/ios/AirGoogleMaps/AIRGoogleMapMarker.h +2 -0
  57. package/ios/AirGoogleMaps/AIRGoogleMapMarker.m +347 -243
  58. package/ios/AirGoogleMaps/AIRGoogleMapMarkerManager.m +0 -1
  59. package/ios/AirGoogleMaps/AIRGoogleMapOverlay.h +0 -1
  60. package/ios/AirGoogleMaps/AIRGoogleMapPolygon.h +5 -4
  61. package/ios/AirGoogleMaps/AIRGoogleMapPolygon.m +32 -2
  62. package/ios/AirGoogleMaps/AIRGoogleMapPolygonManager.m +3 -3
  63. package/ios/AirGoogleMaps/AIRGoogleMapPolyline.h +3 -2
  64. package/ios/AirGoogleMaps/AIRGoogleMapPolyline.m +2 -3
  65. package/ios/AirGoogleMaps/AIRGoogleMapPolylineManager.m +2 -2
  66. package/ios/AirGoogleMaps/AIRGoogleMapWMSTile.h +1 -1
  67. package/ios/AirGoogleMaps/AIRGoogleMapWMSTile.m +2 -2
  68. package/ios/AirGoogleMaps/RCTConvert+GMSMapViewType.h +3 -0
  69. package/ios/AirGoogleMaps/RCTConvert+GMSMapViewType.m +18 -0
  70. package/ios/AirGoogleMaps/RNMapsGoogleMapView.h +26 -0
  71. package/ios/AirGoogleMaps/RNMapsGoogleMapView.mm +629 -0
  72. package/ios/AirGoogleMaps/RNMapsGoogleMapViewManager.mm +25 -0
  73. package/ios/AirGoogleMaps/RNMapsGooglePolygonView.h +26 -0
  74. package/ios/AirGoogleMaps/RNMapsGooglePolygonView.mm +217 -0
  75. package/ios/AirGoogleMaps/RNMapsGooglePolygonViewManager.mm +25 -0
  76. package/ios/AirMaps/AIRMap.h +8 -5
  77. package/ios/AirMaps/AIRMap.m +292 -141
  78. package/ios/AirMaps/AIRMapManager.m +12 -21
  79. package/ios/AirMaps/AIRMapMarker.h +1 -0
  80. package/ios/AirMaps/AIRMapMarker.m +165 -103
  81. package/ios/AirMaps/Callout/SMCalloutView.m +1 -1
  82. package/ios/AirMaps/RCTConvert+AirMap.h +4 -0
  83. package/ios/AirMaps/RCTConvert+AirMap.m +2 -0
  84. package/ios/AirMaps/RNMapsAirModule.h +4 -1
  85. package/ios/AirMaps/RNMapsAirModule.mm +42 -172
  86. package/ios/AirMaps/RNMapsAirModuleDelegate.h +24 -0
  87. package/ios/AirMaps/RNMapsHostVewDelegate.h +17 -0
  88. package/ios/AirMaps/RNMapsMapView.h +6 -3
  89. package/ios/AirMaps/RNMapsMapView.mm +346 -332
  90. package/ios/AirMaps/RNMapsMarkerView.h +24 -0
  91. package/ios/AirMaps/RNMapsMarkerView.mm +430 -0
  92. package/ios/AirMaps/RNMapsMarkerViewManager.mm +21 -0
  93. package/ios/AirMaps/UIView +AirMap.m +20 -0
  94. package/ios/AirMaps/UIView+AirMap.h +11 -0
  95. package/ios/AirMaps.xcodeproj/project.pbxproj +60 -0
  96. package/ios/generated/RNMapsSpecs/ComponentDescriptors.cpp +25 -0
  97. package/ios/generated/RNMapsSpecs/ComponentDescriptors.h +27 -0
  98. package/ios/generated/RNMapsSpecs/EventEmitters.cpp +896 -0
  99. package/ios/generated/RNMapsSpecs/EventEmitters.h +765 -0
  100. package/ios/generated/RNMapsSpecs/Props.cpp +146 -0
  101. package/ios/generated/RNMapsSpecs/Props.h +1047 -0
  102. package/ios/generated/RNMapsSpecs/RCTComponentViewHelpers.h +549 -0
  103. package/ios/generated/RNMapsSpecs/RNMapsSpecs-generated.mm +92 -0
  104. package/ios/generated/RNMapsSpecs/RNMapsSpecs.h +134 -0
  105. package/ios/generated/RNMapsSpecs/ShadowNodes.cpp +20 -0
  106. package/ios/generated/RNMapsSpecs/ShadowNodes.h +65 -0
  107. package/ios/generated/RNMapsSpecs/States.cpp +16 -0
  108. package/ios/generated/RNMapsSpecs/States.h +65 -0
  109. package/ios/generated/RNMapsSpecsJSI-generated.cpp +74 -0
  110. package/ios/generated/RNMapsSpecsJSI.h +264 -0
  111. package/lib/MapMarker.d.ts +15 -2
  112. package/lib/MapMarker.js +53 -9
  113. package/lib/MapMarkerNativeComponent.js +0 -2
  114. package/lib/MapOverlay.d.ts +1 -1
  115. package/lib/MapOverlay.js +2 -8
  116. package/lib/MapView.d.ts +5 -22
  117. package/lib/MapView.js +61 -80
  118. package/lib/{FabricMapView.d.ts → createFabricMap.d.ts} +7 -6
  119. package/lib/createFabricMap.js +175 -0
  120. package/lib/decorateMapComponent.js +17 -0
  121. package/lib/specs/NativeAirMapsModule.d.ts +2 -2
  122. package/lib/specs/NativeComponentGoogleMapView.d.ts +713 -0
  123. package/lib/specs/NativeComponentGoogleMapView.js +21 -0
  124. package/lib/specs/NativeComponentGooglePolygon.d.ts +75 -0
  125. package/lib/specs/NativeComponentGooglePolygon.js +9 -0
  126. package/lib/specs/NativeComponentMapView.d.ts +21 -45
  127. package/lib/specs/NativeComponentMapView.js +1 -3
  128. package/lib/specs/NativeComponentMarker.d.ts +258 -0
  129. package/lib/specs/NativeComponentMarker.js +19 -0
  130. package/package.json +13 -7
  131. package/react-native-maps.podspec +2 -1
  132. package/lib/FabricMapView.js +0 -175
@@ -20,6 +20,7 @@
20
20
  #import "AIRMapWMSTile.h"
21
21
  #import "AIRMapLocalTile.h"
22
22
  #import "AIRMapOverlay.h"
23
+ #import "AIRMapSnapshot.h"
23
24
 
24
25
  const NSTimeInterval AIRMapRegionChangeObserveInterval = 0.1;
25
26
  const CGFloat AIRMapZoomBoundBuffer = 0.01;
@@ -38,8 +39,6 @@ const NSInteger AIRMapMaxZoomLevel = 20;
38
39
  @property (nonatomic, strong) UIActivityIndicatorView *activityIndicatorView;
39
40
  @property (nonatomic, assign) NSNumber *shouldZoomEnabled;
40
41
  @property (nonatomic, assign) NSNumber *shouldScrollEnabled;
41
- @property (nonatomic, strong) MKCompassButton *defaultCompassButton;
42
- @property (nonatomic, strong) MKCompassButton *overlayCompassButton;
43
42
 
44
43
  - (void)updateScrollEnabled;
45
44
  - (void)updateZoomEnabled;
@@ -50,8 +49,12 @@ const NSInteger AIRMapMaxZoomLevel = 20;
50
49
  {
51
50
  UIView *_legalLabel;
52
51
  BOOL _initialRegionSet;
52
+ BOOL _initialRegionProvided;
53
+ BOOL _initialCameraProvided;
53
54
  BOOL _initialCameraSet;
54
-
55
+ BOOL _initialized;
56
+ BOOL _loadingStarted;
57
+
55
58
  // Array to manually track RN subviews
56
59
  //
57
60
  // AIRMap implicitly creates subviews that aren't regular RN children
@@ -69,7 +72,7 @@ const NSInteger AIRMapMaxZoomLevel = 20;
69
72
  if ((self = [super init])) {
70
73
  _hasStartedRendering = NO;
71
74
  _reactSubviews = [NSMutableArray new];
72
-
75
+
73
76
  // Find Apple link label
74
77
  for (UIView *subview in self.subviews) {
75
78
  if ([NSStringFromClass(subview.class) isEqualToString:@"MKAttributionLabel"]) {
@@ -79,16 +82,18 @@ const NSInteger AIRMapMaxZoomLevel = 20;
79
82
  break;
80
83
  }
81
84
  }
82
-
85
+
83
86
  // 3rd-party callout view for MapKit that has more options than the built-in. It's painstakingly built to
84
87
  // be identical to the built-in callout view (which has a private API)
85
88
  self.calloutView = [SMCalloutView platformCalloutView];
86
89
  self.calloutView.delegate = self;
87
-
88
- self.minZoomLevel = 0;
89
- self.maxZoomLevel = AIRMapMaxZoomLevel;
90
+
91
+ self.minZoom = 0;
92
+ self.maxZoom = AIRMapMaxZoomLevel;
90
93
  self.compassOffset = CGPointMake(0, 0);
91
94
  self.legacyZoomConstraintsEnabled = YES;
95
+ _initialized = YES;
96
+ [self listenToMemoryWarnings];
92
97
  }
93
98
  return self;
94
99
  }
@@ -199,6 +204,20 @@ const NSInteger AIRMapMaxZoomLevel = 20;
199
204
  }
200
205
  return marker;
201
206
  }
207
+ // Create Polyline with coordinates
208
+ -(void) fitToCoordinates:(NSArray<AIRMapCoordinate*>*) coordinates edgePadding:(UIEdgeInsets) edgeInsets animated:(Boolean) animated {
209
+ CLLocationCoordinate2D coords[coordinates.count];
210
+ for(int i = 0; i < coordinates.count; i++)
211
+ {
212
+ coords[i] = coordinates[i].coordinate;
213
+ }
214
+ MKPolyline *polyline = [MKPolyline polylineWithCoordinates:coords count:coordinates.count];
215
+
216
+ // Set Map viewport
217
+
218
+ [self setVisibleMapRect:[polyline boundingMapRect] edgePadding:edgeInsets animated:animated];
219
+ }
220
+
202
221
 
203
222
  - (CGRect) frameForMarker:(AIRMapMarker*) mrkAnn {
204
223
  MKAnnotationView* mrkView = [self viewForAnnotation: mrkAnn];
@@ -206,29 +225,6 @@ const NSInteger AIRMapMaxZoomLevel = 20;
206
225
  return mrkFrame;
207
226
  }
208
227
 
209
- - (NSDictionary*) getMarkersFramesWithOnlyVisible:(BOOL)onlyVisible {
210
- NSMutableDictionary* markersFrames = [NSMutableDictionary new];
211
- for (AIRMapMarker* mrkAnn in self.markers) {
212
- CGRect frame = [self frameForMarker:mrkAnn];
213
- CGPoint point = [self convertCoordinate:mrkAnn.coordinate toPointToView:self];
214
- NSDictionary* frameDict = @{
215
- @"x": @(frame.origin.x),
216
- @"y": @(frame.origin.y),
217
- @"width": @(frame.size.width),
218
- @"height": @(frame.size.height)
219
- };
220
- NSDictionary* pointDict = @{
221
- @"x": @(point.x),
222
- @"y": @(point.y)
223
- };
224
- NSString* k = mrkAnn.identifier;
225
- BOOL isVisible = CGRectIntersectsRect(self.bounds, frame);
226
- if (k != nil && (!onlyVisible || isVisible)) {
227
- [markersFrames setObject:@{ @"frame": frameDict, @"point": pointDict } forKey:k];
228
- }
229
- }
230
- return markersFrames;
231
- }
232
228
 
233
229
  - (AIRMapMarker*) markerAtPoint:(CGPoint)point {
234
230
  AIRMapMarker* mrk = nil;
@@ -257,16 +253,16 @@ const NSInteger AIRMapMaxZoomLevel = 20;
257
253
  // Allow touches to be sent to our calloutview.
258
254
  // See this for some discussion of why we need to override this: https://github.com/nfarina/calloutview/pull/9
259
255
  - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
260
-
256
+
261
257
  CGPoint touchPoint = [self.calloutView convertPoint:point fromView:self];
262
258
  UIView *touchedView = [self.calloutView hitTest:touchPoint withEvent:event];
263
-
259
+
264
260
  if (touchedView) {
265
261
  UIWindow* win = [[[UIApplication sharedApplication] windows] firstObject];
266
262
  AIRMapCalloutSubview* calloutSubview = nil;
267
263
  AIRMapCallout* callout = nil;
268
264
  AIRMapMarker* marker = nil;
269
-
265
+
270
266
  UIView* tmp = touchedView;
271
267
  while (tmp && tmp != win && tmp != self.calloutView) {
272
268
  if ([tmp respondsToSelector:@selector(onPress)]) {
@@ -278,7 +274,7 @@ const NSInteger AIRMapMaxZoomLevel = 20;
278
274
  }
279
275
  tmp = tmp.superview;
280
276
  }
281
-
277
+
282
278
  if (callout) {
283
279
  marker = [self markerForCallout:callout];
284
280
  if (marker) {
@@ -288,49 +284,49 @@ const NSInteger AIRMapMaxZoomLevel = 20;
288
284
  }
289
285
  }
290
286
  }
291
-
287
+
292
288
  return calloutSubview ? calloutSubview : touchedView;
293
289
  }
294
-
290
+
295
291
  return [super hitTest:point withEvent:event];
296
292
  }
297
293
 
298
294
  #pragma mark SMCalloutViewDelegate
299
295
 
300
296
  - (NSTimeInterval)calloutView:(SMCalloutView *)calloutView delayForRepositionWithSize:(CGSize)offset {
301
-
297
+
302
298
  // When the callout is being asked to present in a way where it or its target will be partially offscreen, it asks us
303
299
  // if we'd like to reposition our surface first so the callout is completely visible. Here we scroll the map into view,
304
300
  // but it takes some math because we have to deal in lon/lat instead of the given offset in pixels.
305
-
301
+
306
302
  CLLocationCoordinate2D coordinate = self.region.center;
307
-
303
+
308
304
  // where's the center coordinate in terms of our view?
309
305
  CGPoint center = [self convertCoordinate:coordinate toPointToView:self];
310
-
306
+
311
307
  // move it by the requested offset
312
308
  center.x -= offset.width;
313
309
  center.y -= offset.height;
314
-
310
+
315
311
  // and translate it back into map coordinates
316
312
  coordinate = [self convertPoint:center toCoordinateFromView:self];
317
-
313
+
318
314
  // move the map!
319
315
  [self setCenterCoordinate:coordinate animated:YES];
320
-
316
+
321
317
  // tell the callout to wait for a while while we scroll (we assume the scroll delay for MKMapView matches UIScrollView)
322
318
  return kSMCalloutViewRepositionDelayForUIScrollView;
323
319
  }
324
320
 
325
- #pragma mark Accessors
321
+ #pragma mark RNMapsAirModuleDelegate.h
326
322
 
327
323
  - (NSArray *)getMapBoundaries
328
324
  {
329
325
  MKMapRect mapRect = self.visibleMapRect;
330
-
326
+
331
327
  CLLocationCoordinate2D northEast = MKCoordinateForMapPoint(MKMapPointMake(MKMapRectGetMaxX(mapRect), mapRect.origin.y));
332
328
  CLLocationCoordinate2D southWest = MKCoordinateForMapPoint(MKMapPointMake(mapRect.origin.x, MKMapRectGetMaxY(mapRect)));
333
-
329
+
334
330
  return @[
335
331
  @[
336
332
  [NSNumber numberWithDouble:northEast.longitude],
@@ -342,6 +338,174 @@ const NSInteger AIRMapMaxZoomLevel = 20;
342
338
  ]
343
339
  ];
344
340
  }
341
+ - (NSDictionary *) getPointForCoordinates:(CLLocationCoordinate2D) location
342
+ {
343
+ CGPoint touchPoint = [self convertCoordinate:location toPointToView:self];
344
+
345
+ return @{
346
+ @"x": @(touchPoint.x),
347
+ @"y": @(touchPoint.y),
348
+ };
349
+ }
350
+ - (NSDictionary *) getCoordinatesForPoint:(CGPoint)point
351
+ {
352
+ CLLocationCoordinate2D coordinate = [self convertPoint:point toCoordinateFromView:self];
353
+ return @{
354
+ @"latitude": @(coordinate.latitude),
355
+ @"longitude": @(coordinate.longitude),
356
+ };
357
+
358
+ }
359
+
360
+ - (NSDictionary*) getMarkersFramesWithOnlyVisible:(BOOL)onlyVisible {
361
+ NSMutableDictionary* markersFrames = [NSMutableDictionary new];
362
+ for (AIRMapMarker* mrkAnn in self.markers) {
363
+ CGRect frame = [self frameForMarker:mrkAnn];
364
+ CGPoint point = [self convertCoordinate:mrkAnn.coordinate toPointToView:self];
365
+ NSDictionary* frameDict = @{
366
+ @"x": @(frame.origin.x),
367
+ @"y": @(frame.origin.y),
368
+ @"width": @(frame.size.width),
369
+ @"height": @(frame.size.height)
370
+ };
371
+ NSDictionary* pointDict = @{
372
+ @"x": @(point.x),
373
+ @"y": @(point.y)
374
+ };
375
+ NSString* k = mrkAnn.identifier;
376
+ BOOL isVisible = CGRectIntersectsRect(self.bounds, frame);
377
+ if (k != nil && (!onlyVisible || isVisible)) {
378
+ [markersFrames setObject:@{ @"frame": frameDict, @"point": pointDict } forKey:k];
379
+ }
380
+ }
381
+ return markersFrames;
382
+ }
383
+
384
+ - (NSDictionary *) getCameraDic {
385
+ MKMapCamera *camera = [self camera];
386
+ return @{
387
+ @"center": @{
388
+ @"latitude": @(camera.centerCoordinate.latitude),
389
+ @"longitude": @(camera.centerCoordinate.longitude),
390
+ },
391
+ @"pitch": @(camera.pitch),
392
+ @"heading": @(camera.heading),
393
+ @"altitude": @(camera.altitude),
394
+ };
395
+ }
396
+ - (void)takeSnapshotWithConfig:(NSDictionary *)config
397
+ success:(RCTPromiseResolveBlock)success error:(RCTPromiseRejectBlock)error
398
+ {
399
+
400
+ MKMapSnapshotOptions *options = [[MKMapSnapshotOptions alloc] init];
401
+
402
+ options.mapType = self.mapType;
403
+ NSNumber *width = config[@"width"];
404
+ NSNumber *height = config[@"height"];
405
+ NSNumber *quality = config[@"quality"];
406
+ NSString*format =config[@"format"];
407
+ NSString*result =config[@"result"];
408
+ if (config[@"region"]){
409
+ MKCoordinateRegion region = [RCTConvert MKCoordinateRegion:config[@"region"]];
410
+ options.region = region;
411
+ } else
412
+ {
413
+ options.region = self.region;
414
+ }
415
+ options.size = CGSizeMake(
416
+ ([width floatValue] == 0) ? self.bounds.size.width : [width floatValue],
417
+ ([height floatValue] == 0) ? self.bounds.size.height : [height floatValue]
418
+ );
419
+
420
+ options.scale = [[UIScreen mainScreen] scale];
421
+
422
+
423
+ MKMapSnapshotter *snapshotter = [[MKMapSnapshotter alloc] initWithOptions:options];
424
+
425
+ [self takeMapSnapshot:snapshotter
426
+ format:format
427
+ quality:[quality floatValue]
428
+ result:result
429
+ success:success error:error];
430
+ }
431
+
432
+ #pragma mark Take Snapshot
433
+ - (void)takeMapSnapshot:(MKMapSnapshotter *) snapshotter
434
+ format:(NSString *)format
435
+ quality:(CGFloat) quality
436
+ result:(NSString *)result
437
+ success:(RCTPromiseResolveBlock) success
438
+ error:(RCTPromiseRejectBlock) errorCallback {
439
+ NSTimeInterval timeStamp = [[NSDate date] timeIntervalSince1970];
440
+ NSString *pathComponent = [NSString stringWithFormat:@"Documents/snapshot-%.20lf.%@", timeStamp, format];
441
+ NSString *filePath = [NSHomeDirectory() stringByAppendingPathComponent: pathComponent];
442
+
443
+ [snapshotter startWithQueue:dispatch_get_main_queue()
444
+ completionHandler:^(MKMapSnapshot *snapshot, NSError *error) {
445
+ if (error) {
446
+ errorCallback(@"snapshotterError", @"failed", error);
447
+ return;
448
+ }
449
+ MKAnnotationView *pin = [[MKPinAnnotationView alloc] initWithAnnotation:nil reuseIdentifier:nil];
450
+
451
+ UIImage *image = snapshot.image;
452
+ UIGraphicsBeginImageContextWithOptions(image.size, YES, image.scale);
453
+ {
454
+ [image drawAtPoint:CGPointMake(0.0f, 0.0f)];
455
+
456
+ CGRect rect = CGRectMake(0.0f, 0.0f, image.size.width, image.size.height);
457
+
458
+ for (id <AIRMapSnapshot> overlay in self.overlays) {
459
+ if ([overlay respondsToSelector:@selector(drawToSnapshot:context:)]) {
460
+ [overlay drawToSnapshot:snapshot context:UIGraphicsGetCurrentContext()];
461
+ }
462
+ }
463
+
464
+
465
+ for (id <MKAnnotation> annotation in self.annotations) {
466
+ CGPoint point = [snapshot pointForCoordinate:annotation.coordinate];
467
+
468
+ MKAnnotationView* anView = [self viewForAnnotation: annotation];
469
+
470
+ if (anView){
471
+ pin = anView;
472
+ }
473
+
474
+ if (CGRectContainsPoint(rect, point)) {
475
+ point.x = point.x + pin.centerOffset.x - (pin.bounds.size.width / 2.0f);
476
+ point.y = point.y + pin.centerOffset.y - (pin.bounds.size.height / 2.0f);
477
+ if (pin.image) {
478
+ [pin.image drawAtPoint:point];
479
+ } else {
480
+ CGRect pinRect = CGRectMake(point.x, point.y, pin.bounds.size.width, pin.bounds.size.height);
481
+ [pin drawViewHierarchyInRect:pinRect afterScreenUpdates:NO];
482
+ }
483
+ }
484
+ }
485
+
486
+ UIImage *compositeImage = UIGraphicsGetImageFromCurrentImageContext();
487
+
488
+ NSData *data;
489
+ if ([format isEqualToString:@"png"]) {
490
+ data = UIImagePNGRepresentation(compositeImage);
491
+ }
492
+ else if([format isEqualToString:@"jpg"]) {
493
+ data = UIImageJPEGRepresentation(compositeImage, quality);
494
+ }
495
+
496
+ if ([result isEqualToString:@"file"]) {
497
+ [data writeToFile:filePath atomically:YES];
498
+ success(filePath);
499
+ }
500
+ else if ([result isEqualToString:@"base64"]) {
501
+ success([data base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithCarriageReturn]);
502
+ }
503
+ }
504
+ UIGraphicsEndImageContext();
505
+ }];
506
+ }
507
+
508
+
345
509
 
346
510
  - (void)setShowsUserLocation:(BOOL)showsUserLocation
347
511
  {
@@ -380,13 +544,14 @@ const NSInteger AIRMapMaxZoomLevel = 20;
380
544
  _userLocationCalloutEnabled = calloutEnabled;
381
545
  }
382
546
 
383
- - (void)setHandlePanDrag:(BOOL)handleMapDrag {
547
+ - (void)setHandlePanDrag:(BOOL)handlePanDrag {
384
548
  for (UIGestureRecognizer *recognizer in [self gestureRecognizers]) {
385
549
  if ([recognizer isKindOfClass:[UIPanGestureRecognizer class]]) {
386
- recognizer.enabled = handleMapDrag;
550
+ recognizer.enabled = handlePanDrag;
387
551
  break;
388
552
  }
389
553
  }
554
+ _handlePanDrag = handlePanDrag;
390
555
  }
391
556
 
392
557
  - (void)setRegion:(MKCoordinateRegion)region animated:(BOOL)animated
@@ -395,7 +560,7 @@ const NSInteger AIRMapMaxZoomLevel = 20;
395
560
  if (!CLLocationCoordinate2DIsValid(region.center)) {
396
561
  return;
397
562
  }
398
-
563
+
399
564
  // If new span values are nil, use old values instead
400
565
  if (!region.span.latitudeDelta) {
401
566
  region.span.latitudeDelta = self.region.span.latitudeDelta;
@@ -403,13 +568,28 @@ const NSInteger AIRMapMaxZoomLevel = 20;
403
568
  if (!region.span.longitudeDelta) {
404
569
  region.span.longitudeDelta = self.region.span.longitudeDelta;
405
570
  }
406
-
571
+
407
572
  // Animate/move to new position
408
573
  [super setRegion:region animated:animated];
409
574
  }
575
+ - (void) setRegion:(MKCoordinateRegion)region
576
+ {
577
+ if (!CLLocationCoordinate2DIsValid(region.center)) {
578
+ return;
579
+ }
580
+ if (!CLLocationCoordinate2DIsValid(_initialRegion.center)) {
581
+ [self setInitialRegion:region];
582
+ }
583
+ [self setRegion:region animated:NO];
584
+ }
410
585
 
411
586
  - (void)setInitialRegion:(MKCoordinateRegion)initialRegion {
412
- if (!_initialRegionSet) {
587
+ if (!CLLocationCoordinate2DIsValid(initialRegion.center)) {
588
+ return;
589
+ }
590
+ _initialRegion = initialRegion;
591
+ _initialRegionProvided = YES;
592
+ if (!_initialRegionSet && _loadingStarted) {
413
593
  _initialRegionSet = YES;
414
594
  [self setRegion:initialRegion animated:NO];
415
595
  }
@@ -422,9 +602,13 @@ const NSInteger AIRMapMaxZoomLevel = 20;
422
602
 
423
603
 
424
604
  - (void)setInitialCamera:(MKMapCamera*)initialCamera {
425
- if (!_initialCameraSet) {
426
- _initialCameraSet = YES;
427
- [self setCamera:initialCamera animated:NO];
605
+ _initialCamera = initialCamera;
606
+ _initialCameraProvided = YES;
607
+ if (initialCamera){
608
+ if (!_initialCameraSet && _loadingStarted) {
609
+ _initialCameraSet = YES;
610
+ [self setCamera:initialCamera animated:NO];
611
+ }
428
612
  }
429
613
  }
430
614
 
@@ -471,25 +655,25 @@ const NSInteger AIRMapMaxZoomLevel = 20;
471
655
 
472
656
  - (void)setCameraZoomRange:(NSDictionary *)cameraZoomRange {
473
657
  if (@available(iOS 13.0, *)) {
474
-
658
+
475
659
  if (cameraZoomRange == nil) {
476
660
  cameraZoomRange = @{};
477
661
  }
478
-
662
+
479
663
  NSNumber *minValue = cameraZoomRange[@"minCenterCoordinateDistance"];
480
664
  NSNumber *maxValue = cameraZoomRange[@"maxCenterCoordinateDistance"];
481
-
665
+
482
666
  if (minValue == nil && maxValue == nil) {
483
667
  self.legacyZoomConstraintsEnabled = YES;
484
-
668
+
485
669
  MKMapCameraZoomRange *defaultZoomRange = [[MKMapCameraZoomRange alloc] initWithMinCenterCoordinateDistance:MKMapCameraZoomDefault maxCenterCoordinateDistance:MKMapCameraZoomDefault];
486
670
  [super setCameraZoomRange:defaultZoomRange animated:NO];
487
-
671
+
488
672
  return;
489
673
  }
490
-
674
+
491
675
  MKMapCameraZoomRange *zoomRange = nil;
492
-
676
+
493
677
  if (minValue != nil && maxValue != nil) {
494
678
  zoomRange = [[MKMapCameraZoomRange alloc] initWithMinCenterCoordinateDistance:[minValue doubleValue] maxCenterCoordinateDistance:[maxValue doubleValue]];
495
679
  } else if (minValue != nil) {
@@ -497,61 +681,14 @@ const NSInteger AIRMapMaxZoomLevel = 20;
497
681
  } else if (maxValue != nil) {
498
682
  zoomRange = [[MKMapCameraZoomRange alloc] initWithMaxCenterCoordinateDistance:[maxValue doubleValue]];
499
683
  }
500
-
684
+
501
685
  BOOL animated = [cameraZoomRange[@"animated"] boolValue];
502
-
686
+
503
687
  self.legacyZoomConstraintsEnabled = NO;
504
688
  [super setCameraZoomRange:zoomRange animated:animated];
505
689
  }
506
690
  }
507
691
 
508
- // Include properties of MKMapView which are only available on iOS 9+
509
- // and check if their selector is available before calling super method.
510
-
511
- - (void)setShowsCompass:(BOOL)showsCompass {
512
- if (self.overlayCompassButton != nil) {
513
- self.overlayCompassButton.compassVisibility = showsCompass ? MKFeatureVisibilityAdaptive : MKFeatureVisibilityHidden;
514
- }
515
- if ([MKMapView instancesRespondToSelector:@selector(setShowsCompass:)]) {
516
- [super setShowsCompass:showsCompass];
517
- }
518
- }
519
-
520
- - (BOOL)showsCompass {
521
- if ([MKMapView instancesRespondToSelector:@selector(showsCompass)]) {
522
- return [super showsCompass];
523
- } else {
524
- return NO;
525
- }
526
- }
527
-
528
- - (void)setShowsScale:(BOOL)showsScale {
529
- if ([MKMapView instancesRespondToSelector:@selector(setShowsScale:)]) {
530
- [super setShowsScale:showsScale];
531
- }
532
- }
533
-
534
- - (BOOL)showsScale {
535
- if ([MKMapView instancesRespondToSelector:@selector(showsScale)]) {
536
- return [super showsScale];
537
- } else {
538
- return NO;
539
- }
540
- }
541
-
542
- - (void)setShowsTraffic:(BOOL)showsTraffic {
543
- if ([MKMapView instancesRespondToSelector:@selector(setShowsTraffic:)]) {
544
- [super setShowsTraffic:showsTraffic];
545
- }
546
- }
547
-
548
- - (BOOL)showsTraffic {
549
- if ([MKMapView instancesRespondToSelector:@selector(showsTraffic)]) {
550
- return [super showsTraffic];
551
- } else {
552
- return NO;
553
- }
554
- }
555
692
 
556
693
  - (void)setScrollEnabled:(BOOL)scrollEnabled {
557
694
  self.shouldScrollEnabled = [NSNumber numberWithBool:scrollEnabled];
@@ -597,7 +734,7 @@ const NSInteger AIRMapMaxZoomLevel = 20;
597
734
  else {
598
735
  self.cacheImageView.image = nil;
599
736
  self.cacheImageView.hidden = YES;
600
-
737
+
601
738
  dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.01 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
602
739
  self.cacheImageView.image = nil;
603
740
  self.cacheImageView.hidden = YES;
@@ -605,18 +742,47 @@ const NSInteger AIRMapMaxZoomLevel = 20;
605
742
  [self.layer renderInContext:UIGraphicsGetCurrentContext()];
606
743
  UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
607
744
  UIGraphicsEndImageContext();
608
-
745
+
609
746
  self.cacheImageView.image = image;
610
747
  self.cacheImageView.hidden = NO;
611
748
  });
612
749
  }
613
-
750
+
614
751
  [self updateScrollEnabled];
615
752
  [self updateZoomEnabled];
616
753
  [self updateLegalLabelInsets];
617
754
  }
618
755
  }
619
756
 
757
+ - (void) listenToMemoryWarnings
758
+ {
759
+ __weak typeof(self) weakSelf = self;
760
+ static dispatch_once_t onceToken;
761
+ static dispatch_source_t source;
762
+ dispatch_once(&onceToken, ^{
763
+ source = dispatch_source_create(DISPATCH_SOURCE_TYPE_MEMORYPRESSURE, 0, DISPATCH_MEMORYPRESSURE_WARN|DISPATCH_MEMORYPRESSURE_CRITICAL, dispatch_get_main_queue());
764
+ dispatch_source_set_event_handler(source, ^{
765
+ [weakSelf handleMemoryWarning];
766
+ });
767
+ dispatch_resume(source);
768
+ });
769
+ }
770
+ /*
771
+ hacky way to release all cache
772
+ this is our last chance to release cache before app crash
773
+ */
774
+ - (void) handleMemoryWarning
775
+ {
776
+ NSLog(@"handleMemoryWarning warning");
777
+ MKMapType type = self.mapType;
778
+ if (type == MKMapTypeSatellite){
779
+ self.mapType = MKMapTypeStandard;
780
+ } else {
781
+ self.mapType = MKMapTypeSatellite;
782
+ }
783
+ self.mapType = type;
784
+ }
785
+
620
786
  - (void)updateLegalLabelInsets {
621
787
  if (_legalLabel) {
622
788
  dispatch_async(dispatch_get_main_queue(), ^{
@@ -660,6 +826,14 @@ const NSInteger AIRMapMaxZoomLevel = 20;
660
826
  self.loadingView.hidden = YES;
661
827
  }
662
828
  }
829
+ _loadingStarted = YES;
830
+ // display initialRegion/Camera
831
+ if (_initialRegionProvided){
832
+ [self setInitialRegion:_initialRegion];
833
+ }
834
+ if (_initialCameraProvided){
835
+ [self setInitialCamera:_initialCamera];
836
+ }
663
837
  }
664
838
 
665
839
  - (void)finishLoading {
@@ -706,50 +880,27 @@ const NSInteger AIRMapMaxZoomLevel = 20;
706
880
  - (void)layoutSubviews {
707
881
  [super layoutSubviews];
708
882
  [self cacheViewIfNeeded];
709
-
710
- if (self.overlayCompassButton == nil) {
711
- for (UIView *subview in self.subviews) {
712
- if (![NSStringFromClass(subview.class) isEqualToString:@"MKPassThroughStackView"]) continue;
713
- self.overlayCompassButton = [MKCompassButton compassButtonWithMapView:self];
714
- [subview addSubview:self.overlayCompassButton];
715
- self.overlayCompassButton.frame = CGRectMake(self.overlayCompassButton.frame.origin.x + _compassOffset.x, self.overlayCompassButton.frame.origin.y + _compassOffset.y, self.overlayCompassButton.frame.size.width, self.overlayCompassButton.frame.size.height);
716
- break;
717
- }
718
- }
719
-
720
- if (self.defaultCompassButton == nil) {
721
- for (UIView *subview in self.subviews) {
722
- if (![NSStringFromClass(subview.class) isEqualToString:@"MKPassThroughStackView"]) continue;
723
- for (UIView *subview2 in subview.subviews) {
724
- if (![NSStringFromClass(subview2.class) isEqualToString:@"MKCompassView"]) continue;
725
- self.defaultCompassButton = subview2;
726
- self.defaultCompassButton.hidden = YES;
727
- }
728
- break;
729
- }
730
- }
731
-
732
883
  }
733
884
 
734
885
  // based on https://medium.com/@dmytrobabych/getting-actual-rotation-and-zoom-level-for-mapkit-mkmapview-e7f03f430aa9
735
886
  - (CGFloat)getZoomLevel {
736
887
  CGFloat cameraAngle = self.camera.heading;
737
-
888
+
738
889
  if (cameraAngle > 270) {
739
890
  cameraAngle = 360 - cameraAngle;
740
891
  } else if (cameraAngle > 90) {
741
892
  cameraAngle = fabs(cameraAngle - 180);
742
893
  }
743
-
894
+
744
895
  CGFloat angleRad = M_PI * cameraAngle / 180; // map rotation in radians
745
896
  CGFloat width = self.frame.size.width;
746
897
  CGFloat height = self.frame.size.height;
747
898
  CGFloat heightOffset = 20; // the offset (status bar height) which is taken by MapKit into consideration to calculate visible area height
748
-
899
+
749
900
  // calculating Longitude span corresponding to normal (non-rotated) width
750
901
  CGFloat spanStraight = width * self.region.span.longitudeDelta / (width * cos(angleRad) + (height - heightOffset) * sin(angleRad));
751
902
  int normalizingFactor = 512;
752
-
903
+
753
904
  return log2(360 * ((width / normalizingFactor) / spanStraight));
754
905
  }
755
906