react-native-maps 1.21.0-alpha.2 → 1.21.0-alpha.20

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 (63) hide show
  1. package/android/build.gradle +19 -4
  2. package/android/src/main/java/com/rnmaps/fabric/NativeAirMapsModule.java +51 -0
  3. package/android/src/main/java/com/rnmaps/maps/MapAirModulePackage.java +46 -0
  4. package/ios/AirGoogleMaps/AIRGoogleMap.h +8 -2
  5. package/ios/AirGoogleMaps/AIRGoogleMap.m +166 -11
  6. package/ios/AirGoogleMaps/AIRGoogleMapCircle.h +0 -1
  7. package/ios/AirGoogleMaps/AIRGoogleMapCoordinate.h +13 -0
  8. package/ios/AirGoogleMaps/AIRGoogleMapCoordinate.m +10 -0
  9. package/ios/AirGoogleMaps/AIRGoogleMapManager.h +7 -0
  10. package/ios/AirGoogleMaps/AIRGoogleMapManager.m +28 -119
  11. package/ios/AirGoogleMaps/AIRGoogleMapMarker.h +2 -0
  12. package/ios/AirGoogleMaps/AIRGoogleMapMarker.m +344 -243
  13. package/ios/AirGoogleMaps/AIRGoogleMapMarkerManager.m +0 -1
  14. package/ios/AirGoogleMaps/AIRGoogleMapOverlay.h +0 -1
  15. package/ios/AirGoogleMaps/AIRGoogleMapPolygon.h +5 -4
  16. package/ios/AirGoogleMaps/AIRGoogleMapPolygon.m +29 -2
  17. package/ios/AirGoogleMaps/AIRGoogleMapPolygonManager.m +3 -3
  18. package/ios/AirGoogleMaps/AIRGoogleMapPolyline.h +3 -2
  19. package/ios/AirGoogleMaps/AIRGoogleMapPolyline.m +2 -3
  20. package/ios/AirGoogleMaps/AIRGoogleMapPolylineManager.m +2 -2
  21. package/ios/AirGoogleMaps/AIRGoogleMapWMSTile.h +1 -1
  22. package/ios/AirGoogleMaps/AIRGoogleMapWMSTile.m +2 -2
  23. package/ios/AirGoogleMaps/RCTConvert+GMSMapViewType.h +3 -0
  24. package/ios/AirGoogleMaps/RCTConvert+GMSMapViewType.m +18 -0
  25. package/ios/AirGoogleMaps/RNMapsGoogleMapView.h +26 -0
  26. package/ios/AirGoogleMaps/RNMapsGoogleMapView.mm +599 -0
  27. package/ios/AirGoogleMaps/RNMapsGoogleMapViewManager.mm +25 -0
  28. package/ios/AirGoogleMaps/RNMapsGooglePolygonView.h +26 -0
  29. package/ios/AirGoogleMaps/RNMapsGooglePolygonView.mm +217 -0
  30. package/ios/AirGoogleMaps/RNMapsGooglePolygonViewManager.mm +25 -0
  31. package/ios/AirMaps/AIRMap.h +8 -4
  32. package/ios/AirMaps/AIRMap.m +227 -137
  33. package/ios/AirMaps/AIRMapManager.m +9 -21
  34. package/ios/AirMaps/AIRMapMarker.m +8 -2
  35. package/ios/AirMaps/RCTConvert+AirMap.h +4 -0
  36. package/ios/AirMaps/RCTConvert+AirMap.m +2 -0
  37. package/ios/AirMaps/RNMapsAirModule.h +3 -0
  38. package/ios/AirMaps/RNMapsAirModule.mm +40 -171
  39. package/ios/AirMaps/RNMapsAirModuleDelegate.h +24 -0
  40. package/ios/AirMaps/RNMapsHostVewDelegate.h +17 -0
  41. package/ios/AirMaps/RNMapsMapView.h +6 -3
  42. package/ios/AirMaps/RNMapsMapView.mm +340 -334
  43. package/ios/AirMaps/UIView +AirMap.m +20 -0
  44. package/ios/AirMaps/UIView+AirMap.h +11 -0
  45. package/lib/MapMarker.d.ts +2 -2
  46. package/lib/MapMarker.js +12 -5
  47. package/lib/MapMarkerNativeComponent.js +0 -2
  48. package/lib/MapOverlay.d.ts +1 -1
  49. package/lib/MapView.d.ts +4 -22
  50. package/lib/MapView.js +28 -21
  51. package/lib/{FabricMapView.d.ts → createFabricMap.d.ts} +7 -6
  52. package/lib/createFabricMap.js +175 -0
  53. package/lib/decorateMapComponent.js +18 -0
  54. package/lib/specs/NativeComponentGoogleMapView.d.ts +713 -0
  55. package/lib/specs/NativeComponentGoogleMapView.js +21 -0
  56. package/lib/specs/NativeComponentGooglePolygon.d.ts +75 -0
  57. package/lib/specs/NativeComponentGooglePolygon.js +9 -0
  58. package/lib/specs/NativeComponentMapView.d.ts +21 -45
  59. package/lib/specs/NativeComponentMarker.d.ts +245 -0
  60. package/lib/specs/NativeComponentMarker.js +20 -0
  61. package/package.json +10 -7
  62. package/react-native-maps.podspec +1 -1
  63. 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;
@@ -51,7 +50,8 @@ const NSInteger AIRMapMaxZoomLevel = 20;
51
50
  UIView *_legalLabel;
52
51
  BOOL _initialRegionSet;
53
52
  BOOL _initialCameraSet;
54
-
53
+ BOOL _initialized;
54
+
55
55
  // Array to manually track RN subviews
56
56
  //
57
57
  // AIRMap implicitly creates subviews that aren't regular RN children
@@ -69,7 +69,7 @@ const NSInteger AIRMapMaxZoomLevel = 20;
69
69
  if ((self = [super init])) {
70
70
  _hasStartedRendering = NO;
71
71
  _reactSubviews = [NSMutableArray new];
72
-
72
+
73
73
  // Find Apple link label
74
74
  for (UIView *subview in self.subviews) {
75
75
  if ([NSStringFromClass(subview.class) isEqualToString:@"MKAttributionLabel"]) {
@@ -79,16 +79,17 @@ const NSInteger AIRMapMaxZoomLevel = 20;
79
79
  break;
80
80
  }
81
81
  }
82
-
82
+
83
83
  // 3rd-party callout view for MapKit that has more options than the built-in. It's painstakingly built to
84
84
  // be identical to the built-in callout view (which has a private API)
85
85
  self.calloutView = [SMCalloutView platformCalloutView];
86
86
  self.calloutView.delegate = self;
87
-
88
- self.minZoomLevel = 0;
89
- self.maxZoomLevel = AIRMapMaxZoomLevel;
87
+
88
+ self.minZoom = 0;
89
+ self.maxZoom = AIRMapMaxZoomLevel;
90
90
  self.compassOffset = CGPointMake(0, 0);
91
91
  self.legacyZoomConstraintsEnabled = YES;
92
+ _initialized = YES;
92
93
  }
93
94
  return self;
94
95
  }
@@ -100,6 +101,9 @@ const NSInteger AIRMapMaxZoomLevel = 20;
100
101
  [super addSubview:view];
101
102
  }
102
103
  }
104
+ - (void) didSetRegion {
105
+ _initialRegionSet = YES;
106
+ }
103
107
 
104
108
  #pragma clang diagnostic push
105
109
  #pragma clang diagnostic ignored "-Wobjc-missing-super-calls"
@@ -199,36 +203,25 @@ const NSInteger AIRMapMaxZoomLevel = 20;
199
203
  }
200
204
  return marker;
201
205
  }
206
+ // Create Polyline with coordinates
207
+ -(void) fitToCoordinates:(NSArray<AIRMapCoordinate*>*) coordinates edgePadding:(UIEdgeInsets) edgeInsets animated:(Boolean) animated {
208
+ CLLocationCoordinate2D coords[coordinates.count];
209
+ for(int i = 0; i < coordinates.count; i++)
210
+ {
211
+ coords[i] = coordinates[i].coordinate;
212
+ }
213
+ MKPolyline *polyline = [MKPolyline polylineWithCoordinates:coords count:coordinates.count];
202
214
 
215
+ // Set Map viewport
216
+
217
+ [self setVisibleMapRect:[polyline boundingMapRect] edgePadding:edgeInsets animated:animated];
218
+ }
203
219
  - (CGRect) frameForMarker:(AIRMapMarker*) mrkAnn {
204
220
  MKAnnotationView* mrkView = [self viewForAnnotation: mrkAnn];
205
221
  CGRect mrkFrame = mrkView.frame;
206
222
  return mrkFrame;
207
223
  }
208
224
 
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
225
 
233
226
  - (AIRMapMarker*) markerAtPoint:(CGPoint)point {
234
227
  AIRMapMarker* mrk = nil;
@@ -257,16 +250,16 @@ const NSInteger AIRMapMaxZoomLevel = 20;
257
250
  // Allow touches to be sent to our calloutview.
258
251
  // See this for some discussion of why we need to override this: https://github.com/nfarina/calloutview/pull/9
259
252
  - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
260
-
253
+
261
254
  CGPoint touchPoint = [self.calloutView convertPoint:point fromView:self];
262
255
  UIView *touchedView = [self.calloutView hitTest:touchPoint withEvent:event];
263
-
256
+
264
257
  if (touchedView) {
265
258
  UIWindow* win = [[[UIApplication sharedApplication] windows] firstObject];
266
259
  AIRMapCalloutSubview* calloutSubview = nil;
267
260
  AIRMapCallout* callout = nil;
268
261
  AIRMapMarker* marker = nil;
269
-
262
+
270
263
  UIView* tmp = touchedView;
271
264
  while (tmp && tmp != win && tmp != self.calloutView) {
272
265
  if ([tmp respondsToSelector:@selector(onPress)]) {
@@ -278,7 +271,7 @@ const NSInteger AIRMapMaxZoomLevel = 20;
278
271
  }
279
272
  tmp = tmp.superview;
280
273
  }
281
-
274
+
282
275
  if (callout) {
283
276
  marker = [self markerForCallout:callout];
284
277
  if (marker) {
@@ -288,49 +281,49 @@ const NSInteger AIRMapMaxZoomLevel = 20;
288
281
  }
289
282
  }
290
283
  }
291
-
284
+
292
285
  return calloutSubview ? calloutSubview : touchedView;
293
286
  }
294
-
287
+
295
288
  return [super hitTest:point withEvent:event];
296
289
  }
297
290
 
298
291
  #pragma mark SMCalloutViewDelegate
299
292
 
300
293
  - (NSTimeInterval)calloutView:(SMCalloutView *)calloutView delayForRepositionWithSize:(CGSize)offset {
301
-
294
+
302
295
  // When the callout is being asked to present in a way where it or its target will be partially offscreen, it asks us
303
296
  // if we'd like to reposition our surface first so the callout is completely visible. Here we scroll the map into view,
304
297
  // but it takes some math because we have to deal in lon/lat instead of the given offset in pixels.
305
-
298
+
306
299
  CLLocationCoordinate2D coordinate = self.region.center;
307
-
300
+
308
301
  // where's the center coordinate in terms of our view?
309
302
  CGPoint center = [self convertCoordinate:coordinate toPointToView:self];
310
-
303
+
311
304
  // move it by the requested offset
312
305
  center.x -= offset.width;
313
306
  center.y -= offset.height;
314
-
307
+
315
308
  // and translate it back into map coordinates
316
309
  coordinate = [self convertPoint:center toCoordinateFromView:self];
317
-
310
+
318
311
  // move the map!
319
312
  [self setCenterCoordinate:coordinate animated:YES];
320
-
313
+
321
314
  // tell the callout to wait for a while while we scroll (we assume the scroll delay for MKMapView matches UIScrollView)
322
315
  return kSMCalloutViewRepositionDelayForUIScrollView;
323
316
  }
324
317
 
325
- #pragma mark Accessors
318
+ #pragma mark RNMapsAirModuleDelegate.h
326
319
 
327
320
  - (NSArray *)getMapBoundaries
328
321
  {
329
322
  MKMapRect mapRect = self.visibleMapRect;
330
-
323
+
331
324
  CLLocationCoordinate2D northEast = MKCoordinateForMapPoint(MKMapPointMake(MKMapRectGetMaxX(mapRect), mapRect.origin.y));
332
325
  CLLocationCoordinate2D southWest = MKCoordinateForMapPoint(MKMapPointMake(mapRect.origin.x, MKMapRectGetMaxY(mapRect)));
333
-
326
+
334
327
  return @[
335
328
  @[
336
329
  [NSNumber numberWithDouble:northEast.longitude],
@@ -342,6 +335,169 @@ const NSInteger AIRMapMaxZoomLevel = 20;
342
335
  ]
343
336
  ];
344
337
  }
338
+ - (NSDictionary *) getPointForCoordinates:(CLLocationCoordinate2D) location
339
+ {
340
+ CGPoint touchPoint = [self convertCoordinate:location toPointToView:self];
341
+
342
+ return @{
343
+ @"x": @(touchPoint.x),
344
+ @"y": @(touchPoint.y),
345
+ };
346
+ }
347
+ - (NSDictionary *) getCoordinatesForPoint:(CGPoint)point
348
+ {
349
+ CLLocationCoordinate2D coordinate = [self convertPoint:point toCoordinateFromView:self];
350
+ return @{
351
+ @"latitude": @(coordinate.latitude),
352
+ @"longitude": @(coordinate.longitude),
353
+ };
354
+
355
+ }
356
+
357
+ - (NSDictionary*) getMarkersFramesWithOnlyVisible:(BOOL)onlyVisible {
358
+ NSMutableDictionary* markersFrames = [NSMutableDictionary new];
359
+ for (AIRMapMarker* mrkAnn in self.markers) {
360
+ CGRect frame = [self frameForMarker:mrkAnn];
361
+ CGPoint point = [self convertCoordinate:mrkAnn.coordinate toPointToView:self];
362
+ NSDictionary* frameDict = @{
363
+ @"x": @(frame.origin.x),
364
+ @"y": @(frame.origin.y),
365
+ @"width": @(frame.size.width),
366
+ @"height": @(frame.size.height)
367
+ };
368
+ NSDictionary* pointDict = @{
369
+ @"x": @(point.x),
370
+ @"y": @(point.y)
371
+ };
372
+ NSString* k = mrkAnn.identifier;
373
+ BOOL isVisible = CGRectIntersectsRect(self.bounds, frame);
374
+ if (k != nil && (!onlyVisible || isVisible)) {
375
+ [markersFrames setObject:@{ @"frame": frameDict, @"point": pointDict } forKey:k];
376
+ }
377
+ }
378
+ return markersFrames;
379
+ }
380
+
381
+ - (NSDictionary *) getCamera {
382
+ MKMapCamera *camera = [self camera];
383
+ return @{
384
+ @"center": @{
385
+ @"latitude": @(camera.centerCoordinate.latitude),
386
+ @"longitude": @(camera.centerCoordinate.longitude),
387
+ },
388
+ @"pitch": @(camera.pitch),
389
+ @"heading": @(camera.heading),
390
+ @"altitude": @(camera.altitude),
391
+ };
392
+ }
393
+ - (void)takeSnapshotWithConfig:(NSDictionary *)config
394
+ callback:(RCTPromiseResolveBlock) callback
395
+ {
396
+
397
+ MKMapSnapshotOptions *options = [[MKMapSnapshotOptions alloc] init];
398
+
399
+ options.mapType = self.mapType;
400
+ NSNumber *width = config[@"width"];
401
+ NSNumber *height = config[@"height"];
402
+ NSNumber *quality = config[@"quality"];
403
+ NSString*format =config[@"format"];
404
+ NSString*result =config[@"result"];
405
+ MKCoordinateRegion region = [RCTConvert MKCoordinateRegion:config[@"region"]];
406
+
407
+
408
+ options.region = (region.center.latitude && region.center.longitude) ? region : self.region;
409
+ options.size = CGSizeMake(
410
+ ([width floatValue] == 0) ? self.bounds.size.width : [width floatValue],
411
+ ([height floatValue] == 0) ? self.bounds.size.height : [height floatValue]
412
+ );
413
+
414
+ options.scale = [[UIScreen mainScreen] scale];
415
+
416
+
417
+ MKMapSnapshotter *snapshotter = [[MKMapSnapshotter alloc] initWithOptions:options];
418
+
419
+ [self takeMapSnapshot:snapshotter
420
+ format:format
421
+ quality:[quality floatValue]
422
+ result:result
423
+ callback:callback];
424
+ }
425
+
426
+ #pragma mark Take Snapshot
427
+ - (void)takeMapSnapshot:(MKMapSnapshotter *) snapshotter
428
+ format:(NSString *)format
429
+ quality:(CGFloat) quality
430
+ result:(NSString *)result
431
+ callback:(RCTPromiseResolveBlock) callback {
432
+ NSTimeInterval timeStamp = [[NSDate date] timeIntervalSince1970];
433
+ NSString *pathComponent = [NSString stringWithFormat:@"Documents/snapshot-%.20lf.%@", timeStamp, format];
434
+ NSString *filePath = [NSHomeDirectory() stringByAppendingPathComponent: pathComponent];
435
+
436
+ [snapshotter startWithQueue:dispatch_get_main_queue()
437
+ completionHandler:^(MKMapSnapshot *snapshot, NSError *error) {
438
+ if (error) {
439
+ callback(@[error]);
440
+ return;
441
+ }
442
+ MKAnnotationView *pin = [[MKPinAnnotationView alloc] initWithAnnotation:nil reuseIdentifier:nil];
443
+
444
+ UIImage *image = snapshot.image;
445
+ UIGraphicsBeginImageContextWithOptions(image.size, YES, image.scale);
446
+ {
447
+ [image drawAtPoint:CGPointMake(0.0f, 0.0f)];
448
+
449
+ CGRect rect = CGRectMake(0.0f, 0.0f, image.size.width, image.size.height);
450
+
451
+ for (id <AIRMapSnapshot> overlay in self.overlays) {
452
+ if ([overlay respondsToSelector:@selector(drawToSnapshot:context:)]) {
453
+ [overlay drawToSnapshot:snapshot context:UIGraphicsGetCurrentContext()];
454
+ }
455
+ }
456
+
457
+ for (id <MKAnnotation> annotation in self.annotations) {
458
+ CGPoint point = [snapshot pointForCoordinate:annotation.coordinate];
459
+
460
+ MKAnnotationView* anView = [self viewForAnnotation: annotation];
461
+
462
+ if (anView){
463
+ pin = anView;
464
+ }
465
+
466
+ if (CGRectContainsPoint(rect, point)) {
467
+ point.x = point.x + pin.centerOffset.x - (pin.bounds.size.width / 2.0f);
468
+ point.y = point.y + pin.centerOffset.y - (pin.bounds.size.height / 2.0f);
469
+ if (pin.image) {
470
+ [pin.image drawAtPoint:point];
471
+ } else {
472
+ CGRect pinRect = CGRectMake(point.x, point.y, pin.bounds.size.width, pin.bounds.size.height);
473
+ [pin drawViewHierarchyInRect:pinRect afterScreenUpdates:NO];
474
+ }
475
+ }
476
+ }
477
+
478
+ UIImage *compositeImage = UIGraphicsGetImageFromCurrentImageContext();
479
+
480
+ NSData *data;
481
+ if ([format isEqualToString:@"png"]) {
482
+ data = UIImagePNGRepresentation(compositeImage);
483
+ }
484
+ else if([format isEqualToString:@"jpg"]) {
485
+ data = UIImageJPEGRepresentation(compositeImage, quality);
486
+ }
487
+
488
+ if ([result isEqualToString:@"file"]) {
489
+ [data writeToFile:filePath atomically:YES];
490
+ callback(filePath);
491
+ }
492
+ else if ([result isEqualToString:@"base64"]) {
493
+ callback([data base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithCarriageReturn]);
494
+ }
495
+ }
496
+ UIGraphicsEndImageContext();
497
+ }];
498
+ }
499
+
500
+
345
501
 
346
502
  - (void)setShowsUserLocation:(BOOL)showsUserLocation
347
503
  {
@@ -380,13 +536,14 @@ const NSInteger AIRMapMaxZoomLevel = 20;
380
536
  _userLocationCalloutEnabled = calloutEnabled;
381
537
  }
382
538
 
383
- - (void)setHandlePanDrag:(BOOL)handleMapDrag {
539
+ - (void)setHandlePanDrag:(BOOL)handlePanDrag {
384
540
  for (UIGestureRecognizer *recognizer in [self gestureRecognizers]) {
385
541
  if ([recognizer isKindOfClass:[UIPanGestureRecognizer class]]) {
386
- recognizer.enabled = handleMapDrag;
542
+ recognizer.enabled = handlePanDrag;
387
543
  break;
388
544
  }
389
545
  }
546
+ _handlePanDrag = handlePanDrag;
390
547
  }
391
548
 
392
549
  - (void)setRegion:(MKCoordinateRegion)region animated:(BOOL)animated
@@ -395,7 +552,7 @@ const NSInteger AIRMapMaxZoomLevel = 20;
395
552
  if (!CLLocationCoordinate2DIsValid(region.center)) {
396
553
  return;
397
554
  }
398
-
555
+
399
556
  // If new span values are nil, use old values instead
400
557
  if (!region.span.latitudeDelta) {
401
558
  region.span.latitudeDelta = self.region.span.latitudeDelta;
@@ -403,12 +560,15 @@ const NSInteger AIRMapMaxZoomLevel = 20;
403
560
  if (!region.span.longitudeDelta) {
404
561
  region.span.longitudeDelta = self.region.span.longitudeDelta;
405
562
  }
406
-
563
+
407
564
  // Animate/move to new position
408
565
  [super setRegion:region animated:animated];
409
566
  }
410
567
 
411
568
  - (void)setInitialRegion:(MKCoordinateRegion)initialRegion {
569
+ if (!CLLocationCoordinate2DIsValid(initialRegion.center)) {
570
+ return;
571
+ }
412
572
  if (!_initialRegionSet) {
413
573
  _initialRegionSet = YES;
414
574
  [self setRegion:initialRegion animated:NO];
@@ -471,25 +631,25 @@ const NSInteger AIRMapMaxZoomLevel = 20;
471
631
 
472
632
  - (void)setCameraZoomRange:(NSDictionary *)cameraZoomRange {
473
633
  if (@available(iOS 13.0, *)) {
474
-
634
+
475
635
  if (cameraZoomRange == nil) {
476
636
  cameraZoomRange = @{};
477
637
  }
478
-
638
+
479
639
  NSNumber *minValue = cameraZoomRange[@"minCenterCoordinateDistance"];
480
640
  NSNumber *maxValue = cameraZoomRange[@"maxCenterCoordinateDistance"];
481
-
641
+
482
642
  if (minValue == nil && maxValue == nil) {
483
643
  self.legacyZoomConstraintsEnabled = YES;
484
-
644
+
485
645
  MKMapCameraZoomRange *defaultZoomRange = [[MKMapCameraZoomRange alloc] initWithMinCenterCoordinateDistance:MKMapCameraZoomDefault maxCenterCoordinateDistance:MKMapCameraZoomDefault];
486
646
  [super setCameraZoomRange:defaultZoomRange animated:NO];
487
-
647
+
488
648
  return;
489
649
  }
490
-
650
+
491
651
  MKMapCameraZoomRange *zoomRange = nil;
492
-
652
+
493
653
  if (minValue != nil && maxValue != nil) {
494
654
  zoomRange = [[MKMapCameraZoomRange alloc] initWithMinCenterCoordinateDistance:[minValue doubleValue] maxCenterCoordinateDistance:[maxValue doubleValue]];
495
655
  } else if (minValue != nil) {
@@ -497,61 +657,14 @@ const NSInteger AIRMapMaxZoomLevel = 20;
497
657
  } else if (maxValue != nil) {
498
658
  zoomRange = [[MKMapCameraZoomRange alloc] initWithMaxCenterCoordinateDistance:[maxValue doubleValue]];
499
659
  }
500
-
660
+
501
661
  BOOL animated = [cameraZoomRange[@"animated"] boolValue];
502
-
662
+
503
663
  self.legacyZoomConstraintsEnabled = NO;
504
664
  [super setCameraZoomRange:zoomRange animated:animated];
505
665
  }
506
666
  }
507
667
 
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
668
 
556
669
  - (void)setScrollEnabled:(BOOL)scrollEnabled {
557
670
  self.shouldScrollEnabled = [NSNumber numberWithBool:scrollEnabled];
@@ -597,7 +710,7 @@ const NSInteger AIRMapMaxZoomLevel = 20;
597
710
  else {
598
711
  self.cacheImageView.image = nil;
599
712
  self.cacheImageView.hidden = YES;
600
-
713
+
601
714
  dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.01 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
602
715
  self.cacheImageView.image = nil;
603
716
  self.cacheImageView.hidden = YES;
@@ -605,12 +718,12 @@ const NSInteger AIRMapMaxZoomLevel = 20;
605
718
  [self.layer renderInContext:UIGraphicsGetCurrentContext()];
606
719
  UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
607
720
  UIGraphicsEndImageContext();
608
-
721
+
609
722
  self.cacheImageView.image = image;
610
723
  self.cacheImageView.hidden = NO;
611
724
  });
612
725
  }
613
-
726
+
614
727
  [self updateScrollEnabled];
615
728
  [self updateZoomEnabled];
616
729
  [self updateLegalLabelInsets];
@@ -706,50 +819,27 @@ const NSInteger AIRMapMaxZoomLevel = 20;
706
819
  - (void)layoutSubviews {
707
820
  [super layoutSubviews];
708
821
  [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
822
  }
733
823
 
734
824
  // based on https://medium.com/@dmytrobabych/getting-actual-rotation-and-zoom-level-for-mapkit-mkmapview-e7f03f430aa9
735
825
  - (CGFloat)getZoomLevel {
736
826
  CGFloat cameraAngle = self.camera.heading;
737
-
827
+
738
828
  if (cameraAngle > 270) {
739
829
  cameraAngle = 360 - cameraAngle;
740
830
  } else if (cameraAngle > 90) {
741
831
  cameraAngle = fabs(cameraAngle - 180);
742
832
  }
743
-
833
+
744
834
  CGFloat angleRad = M_PI * cameraAngle / 180; // map rotation in radians
745
835
  CGFloat width = self.frame.size.width;
746
836
  CGFloat height = self.frame.size.height;
747
837
  CGFloat heightOffset = 20; // the offset (status bar height) which is taken by MapKit into consideration to calculate visible area height
748
-
838
+
749
839
  // calculating Longitude span corresponding to normal (non-rotated) width
750
840
  CGFloat spanStraight = width * self.region.span.longitudeDelta / (width * cos(angleRad) + (height - heightOffset) * sin(angleRad));
751
841
  int normalizingFactor = 512;
752
-
842
+
753
843
  return log2(360 * ((width / normalizingFactor) / spanStraight));
754
844
  }
755
845
 
@@ -350,23 +350,8 @@ RCT_EXPORT_METHOD(fitToCoordinates:(nonnull NSNumber *)reactTag
350
350
  RCTLogError(@"Invalid view returned from registry, expecting AIRMap, got: %@", view);
351
351
  } else {
352
352
  AIRMap *mapView = (AIRMap *)view;
353
-
354
- // Create Polyline with coordinates
355
- CLLocationCoordinate2D coords[coordinates.count];
356
- for(int i = 0; i < coordinates.count; i++)
357
- {
358
- coords[i] = coordinates[i].coordinate;
359
- }
360
- MKPolyline *polyline = [MKPolyline polylineWithCoordinates:coords count:coordinates.count];
361
-
362
- // Set Map viewport
363
- CGFloat top = [RCTConvert CGFloat:edgePadding[@"top"]];
364
- CGFloat right = [RCTConvert CGFloat:edgePadding[@"right"]];
365
- CGFloat bottom = [RCTConvert CGFloat:edgePadding[@"bottom"]];
366
- CGFloat left = [RCTConvert CGFloat:edgePadding[@"left"]];
367
-
368
- [mapView setVisibleMapRect:[polyline boundingMapRect] edgePadding:UIEdgeInsetsMake(top, left, bottom, right) animated:animated];
369
-
353
+ UIEdgeInsets edgeInsets = [RCTConvert UIEdgeInsets:edgePadding];
354
+ [mapView fitToCoordinates: coordinates edgePadding:edgeInsets animated:animated];
370
355
  }
371
356
  }];
372
357
  }
@@ -966,6 +951,8 @@ static int kDragCenterContext;
966
951
 
967
952
  mapView.pendingCenter = mapView.region.center;
968
953
  mapView.pendingSpan = mapView.region.span;
954
+ // reset original state (checkout setCamera / region animated)
955
+ mapView.ignoreRegionChanges = NO;
969
956
  }
970
957
 
971
958
  - (void)mapViewWillStartRenderingMap:(AIRMap *)mapView
@@ -980,6 +967,7 @@ static int kDragCenterContext;
980
967
  - (void)mapViewDidFinishRenderingMap:(AIRMap *)mapView fullyRendered:(BOOL)fullyRendered
981
968
  {
982
969
  [mapView finishLoading];
970
+ mapView.ignoreRegionChanges = NO;
983
971
  }
984
972
 
985
973
  #pragma mark Private
@@ -1175,11 +1163,11 @@ static int kDragCenterContext;
1175
1163
 
1176
1164
  CGFloat zoomLevel = [mapView getZoomLevel];
1177
1165
 
1178
- if (zoomLevel < mapView.minZoomLevel) {
1179
- [self setCenterCoordinate:[mapView centerCoordinate] zoomLevel:mapView.minZoomLevel animated:TRUE mapView:mapView];
1166
+ if (zoomLevel < mapView.minZoom) {
1167
+ [self setCenterCoordinate:[mapView centerCoordinate] zoomLevel:mapView.minZoom animated:TRUE mapView:mapView];
1180
1168
  }
1181
- else if (zoomLevel > mapView.maxZoomLevel) {
1182
- [self setCenterCoordinate:[mapView centerCoordinate] zoomLevel:mapView.maxZoomLevel animated:TRUE mapView:mapView];
1169
+ else if (zoomLevel > mapView.maxZoom) {
1170
+ [self setCenterCoordinate:[mapView centerCoordinate] zoomLevel:mapView.maxZoom animated:TRUE mapView:mapView];
1183
1171
  }
1184
1172
  }
1185
1173
 
@@ -14,6 +14,8 @@
14
14
  #import <React/RCTImageLoaderProtocol.h>
15
15
  #import <React/RCTUtils.h>
16
16
  #import <React/UIView+React.h>
17
+ #import <React/RCTImageLoader.h>
18
+ #import <React/RCTBridge+Private.h>
17
19
 
18
20
  NSInteger const AIR_CALLOUT_OPEN_ZINDEX_BASELINE = 999;
19
21
 
@@ -68,6 +70,7 @@ NSInteger const AIR_CALLOUT_OPEN_ZINDEX_BASELINE = 999;
68
70
  self.calloutView = (AIRMapCallout *)subview;
69
71
  } else {
70
72
  [super insertReactSubview:(UIView *)subview atIndex:atIndex];
73
+ [self addSubview:subview];
71
74
  }
72
75
  }
73
76
  - (void) setFrame:(CGRect)frame {
@@ -84,6 +87,7 @@ NSInteger const AIR_CALLOUT_OPEN_ZINDEX_BASELINE = 999;
84
87
  self.calloutView = nil;
85
88
  } else {
86
89
  [super removeReactSubview:(UIView *)subview];
90
+ [(UIView *) subview removeFromSuperview];
87
91
  }
88
92
  }
89
93
 
@@ -344,7 +348,8 @@ NSInteger const AIR_CALLOUT_OPEN_ZINDEX_BASELINE = 999;
344
348
  _reloadImageCancellationBlock();
345
349
  _reloadImageCancellationBlock = nil;
346
350
  }
347
- _reloadImageCancellationBlock = [[_bridge moduleForName:@"ImageLoader"] loadImageWithURLRequest:[RCTConvert NSURLRequest:_imageSrc]
351
+
352
+ _reloadImageCancellationBlock = [[[RCTBridge currentBridge] moduleForName:@"ImageLoader"] loadImageWithURLRequest:[RCTConvert NSURLRequest:_imageSrc]
348
353
  size:self.bounds.size
349
354
  scale:RCTScreenScale()
350
355
  clipped:YES
@@ -352,9 +357,10 @@ NSInteger const AIR_CALLOUT_OPEN_ZINDEX_BASELINE = 999;
352
357
  progressBlock:nil
353
358
  partialLoadBlock:nil
354
359
  completionBlock:^(NSError *error, UIImage *image) {
360
+ NSLog(@"image load completed");
355
361
  if (error) {
356
362
  // TODO(lmr): do something with the error?
357
- NSLog(@"%@", error);
363
+ NSLog(@"failed to load image: %@", error);
358
364
  }
359
365
  dispatch_async(dispatch_get_main_queue(), ^{
360
366
  self.image = image;