react-native-maps 1.20.1 → 1.21.0-alpha.2
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.
- package/README.md +13 -6
- package/ios/AirMaps/AIRMap.h +2 -1
- package/ios/AirMaps/AIRMap.m +1 -1
- package/ios/AirMaps/AIRMapManager.m +18 -18
- package/ios/AirMaps/AIRMapMarker.m +11 -3
- package/ios/AirMaps/RCTConvert+AirMap.h +2 -1
- package/ios/AirMaps/RCTConvert+AirMap.m +16 -0
- package/ios/AirMaps/RNMapsAirModule.h +13 -0
- package/ios/AirMaps/RNMapsAirModule.mm +280 -0
- package/ios/AirMaps/RNMapsMapView.h +21 -0
- package/ios/AirMaps/RNMapsMapView.mm +548 -0
- package/ios/AirMaps/RNMapsMapViewManager.mm +24 -0
- package/ios/AirMaps.xcodeproj/project.pbxproj +10 -0
- package/lib/FabricMapView.d.ts +22 -0
- package/lib/FabricMapView.js +175 -0
- package/lib/MapView.d.ts +6 -2
- package/lib/MapView.js +144 -71
- package/lib/specs/NativeAirMapsModule.d.ts +31 -0
- package/lib/specs/NativeAirMapsModule.js +4 -0
- package/lib/specs/NativeComponentMapView.d.ts +862 -0
- package/lib/specs/NativeComponentMapView.js +21 -0
- package/package.json +6 -2
- package/react-native-maps.podspec +3 -1
- package/react-native-google-maps.podspec +0 -25
package/README.md
CHANGED
|
@@ -14,10 +14,19 @@ See [Setup Instructions for the Included Example Project](docs/examples-setup.md
|
|
|
14
14
|
|
|
15
15
|
## Compatibility
|
|
16
16
|
|
|
17
|
-
## React
|
|
17
|
+
## React Native Compatibility
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
|
|
19
|
+
### Important Notes:
|
|
20
|
+
|
|
21
|
+
- **Fabric is not yet supported**:
|
|
22
|
+
This feature is currently under development. Fabric is enabled by default in React Native `0.76` and above, so **please disable it** for now.
|
|
23
|
+
Follow updates on this issue here: [react-native-maps/issues/5206](https://github.com/react-native-maps/react-native-maps/issues/5206).
|
|
24
|
+
Kindly refrain from opening duplicate tickets regarding this matter.
|
|
25
|
+
|
|
26
|
+
### Version Requirements:
|
|
27
|
+
|
|
28
|
+
- **Version `1.14.0` and above**: Requires **React Native `>= 0.74`**.
|
|
29
|
+
- **Versions below `1.14.0`**: Require **React Native `>= 0.64.3`**.
|
|
21
30
|
|
|
22
31
|
## Component API
|
|
23
32
|
|
|
@@ -202,9 +211,7 @@ For IOS: configure [App Transport Security](https://developer.apple.com/library/
|
|
|
202
211
|
|
|
203
212
|
## React Native Configuration for Fabric / New Architecture
|
|
204
213
|
|
|
205
|
-
This library
|
|
206
|
-
|
|
207
|
-
There is a warning message that those steps are not necessary; but we couldn't get the example working without them so far.
|
|
214
|
+
This library doesn't support the new arch yet due to issues with inserting subviews / interoplayer. we're working on it.
|
|
208
215
|
|
|
209
216
|
### Configuration Steps
|
|
210
217
|
|
package/ios/AirMaps/AIRMap.h
CHANGED
|
@@ -28,7 +28,7 @@ extern const NSInteger AIRMapMaxZoomLevel;
|
|
|
28
28
|
@property (nonatomic, strong) UIView *loadingView;
|
|
29
29
|
|
|
30
30
|
@property (nonatomic, copy) NSString *userLocationAnnotationTitle;
|
|
31
|
-
@property (nonatomic, assign) BOOL
|
|
31
|
+
@property (nonatomic, assign) BOOL followsUserLocation;
|
|
32
32
|
@property (nonatomic, assign) BOOL userLocationCalloutEnabled;
|
|
33
33
|
@property (nonatomic, assign) BOOL hasStartedRendering;
|
|
34
34
|
@property (nonatomic, assign) BOOL cacheEnabled;
|
|
@@ -79,5 +79,6 @@ extern const NSInteger AIRMapMaxZoomLevel;
|
|
|
79
79
|
|
|
80
80
|
- (AIRMapMarker*) markerAtPoint:(CGPoint)point;
|
|
81
81
|
- (NSDictionary*) getMarkersFramesWithOnlyVisible:(BOOL)onlyVisible;
|
|
82
|
+
- (void)insertReactSubview:(id<RCTComponent>)subview atIndex:(NSInteger)atIndex;
|
|
82
83
|
|
|
83
84
|
@end
|
package/ios/AirMaps/AIRMap.m
CHANGED
|
@@ -372,7 +372,7 @@ const NSInteger AIRMapMaxZoomLevel = 20;
|
|
|
372
372
|
|
|
373
373
|
- (void)setFollowsUserLocation:(BOOL)followsUserLocation
|
|
374
374
|
{
|
|
375
|
-
|
|
375
|
+
_followsUserLocation = followsUserLocation;
|
|
376
376
|
}
|
|
377
377
|
|
|
378
378
|
- (void)setUserLocationCalloutEnabled:(BOOL)calloutEnabled
|
|
@@ -52,13 +52,13 @@ RCT_EXPORT_MODULE()
|
|
|
52
52
|
|
|
53
53
|
map.isAccessibilityElement = NO;
|
|
54
54
|
map.accessibilityElementsHidden = NO;
|
|
55
|
-
|
|
55
|
+
|
|
56
56
|
// MKMapView doesn't report tap events, so we attach gesture recognizers to it
|
|
57
57
|
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleMapTap:)];
|
|
58
58
|
UITapGestureRecognizer *doubleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleMapDoubleTap:)];
|
|
59
59
|
[doubleTap setNumberOfTapsRequired:2];
|
|
60
60
|
[tap requireGestureRecognizerToFail:doubleTap];
|
|
61
|
-
|
|
61
|
+
|
|
62
62
|
UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handleMapLongPress:)];
|
|
63
63
|
UIPanGestureRecognizer *drag = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handleMapDrag:)];
|
|
64
64
|
[drag setMinimumNumberOfTouches:1];
|
|
@@ -66,13 +66,13 @@ RCT_EXPORT_MODULE()
|
|
|
66
66
|
tap.cancelsTouchesInView = NO;
|
|
67
67
|
doubleTap.cancelsTouchesInView = NO;
|
|
68
68
|
longPress.cancelsTouchesInView = NO;
|
|
69
|
-
|
|
69
|
+
|
|
70
70
|
doubleTap.delegate = self;
|
|
71
|
-
|
|
71
|
+
|
|
72
72
|
// disable drag by default
|
|
73
73
|
drag.enabled = NO;
|
|
74
74
|
drag.delegate = self;
|
|
75
|
-
|
|
75
|
+
|
|
76
76
|
[map addGestureRecognizer:tap];
|
|
77
77
|
[map addGestureRecognizer:doubleTap];
|
|
78
78
|
[map addGestureRecognizer:longPress];
|
|
@@ -139,7 +139,7 @@ RCT_CUSTOM_VIEW_PROPERTY(initialRegion, MKCoordinateRegion, AIRMap)
|
|
|
139
139
|
RCT_CUSTOM_VIEW_PROPERTY(initialCamera, MKMapCamera, AIRMap)
|
|
140
140
|
{
|
|
141
141
|
if (json == nil) return;
|
|
142
|
-
|
|
142
|
+
|
|
143
143
|
// don't emit region change events when we are setting the initialCamera
|
|
144
144
|
BOOL originalIgnore = view.ignoreRegionChanges;
|
|
145
145
|
view.ignoreRegionChanges = YES;
|
|
@@ -166,7 +166,7 @@ RCT_CUSTOM_VIEW_PROPERTY(region, MKCoordinateRegion, AIRMap)
|
|
|
166
166
|
RCT_CUSTOM_VIEW_PROPERTY(camera, MKMapCamera*, AIRMap)
|
|
167
167
|
{
|
|
168
168
|
if (json == nil) return;
|
|
169
|
-
|
|
169
|
+
|
|
170
170
|
// don't emit region change events when we are setting the camera
|
|
171
171
|
BOOL originalIgnore = view.ignoreRegionChanges;
|
|
172
172
|
view.ignoreRegionChanges = YES;
|
|
@@ -551,16 +551,16 @@ RCT_EXPORT_METHOD(getAddressFromCoordinates:(nonnull NSNumber *)reactTag
|
|
|
551
551
|
[overlay drawToSnapshot:snapshot context:UIGraphicsGetCurrentContext()];
|
|
552
552
|
}
|
|
553
553
|
}
|
|
554
|
-
|
|
554
|
+
|
|
555
555
|
for (id <MKAnnotation> annotation in mapView.annotations) {
|
|
556
556
|
CGPoint point = [snapshot pointForCoordinate:annotation.coordinate];
|
|
557
|
-
|
|
557
|
+
|
|
558
558
|
MKAnnotationView* anView = [mapView viewForAnnotation: annotation];
|
|
559
|
-
|
|
559
|
+
|
|
560
560
|
if (anView){
|
|
561
561
|
pin = anView;
|
|
562
562
|
}
|
|
563
|
-
|
|
563
|
+
|
|
564
564
|
if (CGRectContainsPoint(rect, point)) {
|
|
565
565
|
point.x = point.x + pin.centerOffset.x - (pin.bounds.size.width / 2.0f);
|
|
566
566
|
point.y = point.y + pin.centerOffset.y - (pin.bounds.size.height / 2.0f);
|
|
@@ -720,7 +720,7 @@ RCT_EXPORT_METHOD(getAddressFromCoordinates:(nonnull NSNumber *)reactTag
|
|
|
720
720
|
- (void)handleMapDoubleTap:(UIPanGestureRecognizer*)recognizer {
|
|
721
721
|
AIRMap *map = (AIRMap *)recognizer.view;
|
|
722
722
|
if (!map.onDoublePress) return;
|
|
723
|
-
|
|
723
|
+
|
|
724
724
|
CGPoint touchPoint = [recognizer locationInView:map];
|
|
725
725
|
CLLocationCoordinate2D coord = [map convertPoint:touchPoint toCoordinateFromView:map];
|
|
726
726
|
map.onDoublePress(@{
|
|
@@ -733,7 +733,7 @@ RCT_EXPORT_METHOD(getAddressFromCoordinates:(nonnull NSNumber *)reactTag
|
|
|
733
733
|
@"y": @(touchPoint.y),
|
|
734
734
|
},
|
|
735
735
|
});
|
|
736
|
-
|
|
736
|
+
|
|
737
737
|
}
|
|
738
738
|
|
|
739
739
|
|
|
@@ -925,15 +925,15 @@ static int kDragCenterContext;
|
|
|
925
925
|
@"heading": @(location.location.course),
|
|
926
926
|
}
|
|
927
927
|
};
|
|
928
|
-
|
|
928
|
+
|
|
929
929
|
if (mapView.onUserLocationChange) {
|
|
930
930
|
mapView.onUserLocationChange(event);
|
|
931
931
|
}
|
|
932
|
-
|
|
933
|
-
if (mapView.
|
|
932
|
+
|
|
933
|
+
if (mapView.followsUserLocation) {
|
|
934
934
|
[mapView setCenterCoordinate:location.coordinate animated:YES];
|
|
935
935
|
}
|
|
936
|
-
|
|
936
|
+
|
|
937
937
|
}
|
|
938
938
|
|
|
939
939
|
- (void)mapView:(AIRMap *)mapView regionWillChangeAnimated:(BOOL)animated
|
|
@@ -1171,7 +1171,7 @@ static int kDragCenterContext;
|
|
|
1171
1171
|
// flyover maps don't use mercator projection so we can't calculate their zoom level.
|
|
1172
1172
|
if (mapView.mapType == MKMapTypeHybridFlyover || mapView.mapType == MKMapTypeSatelliteFlyover) {
|
|
1173
1173
|
return;
|
|
1174
|
-
}
|
|
1174
|
+
}
|
|
1175
1175
|
|
|
1176
1176
|
CGFloat zoomLevel = [mapView getZoomLevel];
|
|
1177
1177
|
|
|
@@ -70,6 +70,14 @@ NSInteger const AIR_CALLOUT_OPEN_ZINDEX_BASELINE = 999;
|
|
|
70
70
|
[super insertReactSubview:(UIView *)subview atIndex:atIndex];
|
|
71
71
|
}
|
|
72
72
|
}
|
|
73
|
+
- (void) setFrame:(CGRect)frame {
|
|
74
|
+
// hack to ignore call by react transactions when it shouldn't
|
|
75
|
+
if (!CGPointEqualToPoint(self.frame.origin, CGPointZero) &&
|
|
76
|
+
CGPointEqualToPoint(frame.origin, CGPointZero)){
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
[super setFrame:frame];
|
|
80
|
+
}
|
|
73
81
|
|
|
74
82
|
- (void)removeReactSubview:(id<RCTComponent>)subview {
|
|
75
83
|
if ([subview isKindOfClass:[AIRMapCallout class]] && self.calloutView == subview) {
|
|
@@ -84,7 +92,7 @@ NSInteger const AIR_CALLOUT_OPEN_ZINDEX_BASELINE = 999;
|
|
|
84
92
|
if ([self shouldUsePinView]) {
|
|
85
93
|
// In this case, we want to render a platform "default" legacy marker.
|
|
86
94
|
|
|
87
|
-
|
|
95
|
+
|
|
88
96
|
if (_pinView == nil && _useLegacyPinView) {
|
|
89
97
|
_pinView = [[MKPinAnnotationView alloc] initWithAnnotation:self reuseIdentifier: nil];
|
|
90
98
|
[self addGestureRecognizerToView:_pinView];
|
|
@@ -99,8 +107,8 @@ NSInteger const AIR_CALLOUT_OPEN_ZINDEX_BASELINE = 999;
|
|
|
99
107
|
|
|
100
108
|
return _pinView;
|
|
101
109
|
}
|
|
102
|
-
|
|
103
|
-
|
|
110
|
+
|
|
111
|
+
|
|
104
112
|
|
|
105
113
|
if (_markerView == nil && !_useLegacyPinView) {
|
|
106
114
|
_markerView = [[MKMarkerAnnotationView alloc] initWithAnnotation:self reuseIdentifier: nil];
|
|
@@ -14,5 +14,6 @@
|
|
|
14
14
|
+ (MKMapCamera*)MKMapCamera:(id)json;
|
|
15
15
|
+ (MKMapCamera*)MKMapCameraWithDefaults:(id)json existingCamera:(MKMapCamera*)camera;
|
|
16
16
|
+ (MKMapType)MKMapType:(id)json;
|
|
17
|
-
|
|
17
|
+
+ (NSDictionary*) dictonaryFromString:(NSString *) str;
|
|
18
|
+
+ (NSArray*) arrayFromString:(NSString *) str;
|
|
18
19
|
@end
|
|
@@ -33,6 +33,22 @@
|
|
|
33
33
|
return [RCTConvert MKMapCameraWithDefaults:json existingCamera:nil];
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
+
+ (NSDictionary*) dictonaryFromString:(NSString *) str {
|
|
37
|
+
NSError *jsonError;
|
|
38
|
+
NSData *objectData = [str dataUsingEncoding:NSUTF8StringEncoding];
|
|
39
|
+
return [NSJSONSerialization JSONObjectWithData:objectData
|
|
40
|
+
options:NSJSONReadingMutableContainers
|
|
41
|
+
error:&jsonError];
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
+ (NSArray*) arrayFromString:(NSString *) str {
|
|
45
|
+
NSError *jsonError;
|
|
46
|
+
NSData *objectData = [str dataUsingEncoding:NSUTF8StringEncoding];
|
|
47
|
+
return [NSJSONSerialization JSONObjectWithData:objectData
|
|
48
|
+
options:NSJSONReadingMutableContainers
|
|
49
|
+
error:&jsonError];
|
|
50
|
+
}
|
|
51
|
+
|
|
36
52
|
+ (MKMapCamera*)MKMapCameraWithDefaults:(id)json existingCamera:(MKMapCamera*)camera
|
|
37
53
|
{
|
|
38
54
|
json = [self NSDictionary:json];
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// RCTNativeLocalStorage.h
|
|
2
|
+
// TurboModuleExample
|
|
3
|
+
|
|
4
|
+
#import <Foundation/Foundation.h>
|
|
5
|
+
#import <RNMapsSpecs/RNMapsSpecs.h>
|
|
6
|
+
|
|
7
|
+
NS_ASSUME_NONNULL_BEGIN
|
|
8
|
+
|
|
9
|
+
@interface RNMapsAirModule : NSObject <NativeAirMapsModuleSpec>
|
|
10
|
+
|
|
11
|
+
@end
|
|
12
|
+
|
|
13
|
+
NS_ASSUME_NONNULL_END
|
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
//
|
|
2
|
+
// RNMapsMarkerManager.m
|
|
3
|
+
// AirMaps
|
|
4
|
+
//
|
|
5
|
+
// Created by Salah Ghanim on 23.11.24.
|
|
6
|
+
// Copyright © 2024 react-native-maps. All rights reserved.
|
|
7
|
+
//
|
|
8
|
+
|
|
9
|
+
#import "RNMapsAirModule.h"
|
|
10
|
+
#import <React/RCTUIManager.h>
|
|
11
|
+
#import <React/RCTViewManager.h>
|
|
12
|
+
#import "RNMapsMapView.h"
|
|
13
|
+
#import "AIRMap.h"
|
|
14
|
+
#import "AIRMapSnapshot.h"
|
|
15
|
+
#import <MapKit/MapKit.h>
|
|
16
|
+
#import "RCTConvert+AirMap.h"
|
|
17
|
+
|
|
18
|
+
@implementation RNMapsAirModule
|
|
19
|
+
|
|
20
|
+
@synthesize viewRegistry_DEPRECATED = _viewRegistry_DEPRECATED;
|
|
21
|
+
|
|
22
|
+
- (void)executeWithMapView:(double)tag
|
|
23
|
+
success:(void (^)(AIRMap *mapView))success
|
|
24
|
+
reject:(RCTPromiseRejectBlock)reject {
|
|
25
|
+
dispatch_async(dispatch_get_main_queue(), ^{
|
|
26
|
+
id view = [_viewRegistry_DEPRECATED viewForReactTag:[NSNumber numberWithDouble:tag]];
|
|
27
|
+
if (![view isKindOfClass:[RNMapsMapView class]]) {
|
|
28
|
+
reject(@"Invalid argument", [NSString stringWithFormat:@"Invalid view returned from registry, expecting RNMapsMapView, got: %@", view], NULL);
|
|
29
|
+
} else {
|
|
30
|
+
AIRMap *mapView = [view mapView];
|
|
31
|
+
success(mapView);
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
- (void)getCamera:(double)tag
|
|
37
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
38
|
+
reject:(RCTPromiseRejectBlock)reject {
|
|
39
|
+
[self executeWithMapView:tag success:^(AIRMap *mapView) {
|
|
40
|
+
MKMapCamera *camera = [mapView camera];
|
|
41
|
+
resolve(@{
|
|
42
|
+
@"center": @{
|
|
43
|
+
@"latitude": @(camera.centerCoordinate.latitude),
|
|
44
|
+
@"longitude": @(camera.centerCoordinate.longitude),
|
|
45
|
+
},
|
|
46
|
+
@"pitch": @(camera.pitch),
|
|
47
|
+
@"heading": @(camera.heading),
|
|
48
|
+
@"altitude": @(camera.altitude),
|
|
49
|
+
});
|
|
50
|
+
} reject:reject];
|
|
51
|
+
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
- (void)getMarkersFrames:(double)tag
|
|
55
|
+
onlyVisible:(BOOL)onlyVisible
|
|
56
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
57
|
+
reject:(RCTPromiseRejectBlock)reject
|
|
58
|
+
{
|
|
59
|
+
[self executeWithMapView:tag success:^(AIRMap *mapView) {
|
|
60
|
+
resolve([mapView getMarkersFramesWithOnlyVisible:onlyVisible]);
|
|
61
|
+
} reject:reject];
|
|
62
|
+
}
|
|
63
|
+
- (void)getMapBoundaries:(double)tag
|
|
64
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
65
|
+
reject:(RCTPromiseRejectBlock)reject
|
|
66
|
+
{
|
|
67
|
+
[self executeWithMapView:tag success:^(AIRMap *mapView) {
|
|
68
|
+
resolve([mapView getMapBoundaries]);
|
|
69
|
+
} reject:reject];
|
|
70
|
+
}
|
|
71
|
+
- (void)takeSnapshot:(double)tag
|
|
72
|
+
config:(NSDictionary *)config
|
|
73
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
74
|
+
reject:(RCTPromiseRejectBlock)reject
|
|
75
|
+
{
|
|
76
|
+
|
|
77
|
+
[self executeWithMapView:tag success:^(AIRMap *mapView) {
|
|
78
|
+
|
|
79
|
+
MKMapSnapshotOptions *options = [[MKMapSnapshotOptions alloc] init];
|
|
80
|
+
|
|
81
|
+
options.mapType = mapView.mapType;
|
|
82
|
+
NSNumber *width = config[@"width"];
|
|
83
|
+
NSNumber *height = config[@"height"];
|
|
84
|
+
NSNumber *quality = config[@"quality"];
|
|
85
|
+
NSString*format =config[@"format"];
|
|
86
|
+
NSString*result =config[@"result"];
|
|
87
|
+
MKCoordinateRegion region = [RCTConvert MKCoordinateRegion:config[@"region"]];
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
options.region = (region.center.latitude && region.center.longitude) ? region : mapView.region;
|
|
91
|
+
options.size = CGSizeMake(
|
|
92
|
+
([width floatValue] == 0) ? mapView.bounds.size.width : [width floatValue],
|
|
93
|
+
([height floatValue] == 0) ? mapView.bounds.size.height : [height floatValue]
|
|
94
|
+
);
|
|
95
|
+
|
|
96
|
+
options.scale = [[UIScreen mainScreen] scale];
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
MKMapSnapshotter *snapshotter = [[MKMapSnapshotter alloc] initWithOptions:options];
|
|
100
|
+
|
|
101
|
+
[self takeMapSnapshot:mapView
|
|
102
|
+
snapshotter:snapshotter
|
|
103
|
+
format:format
|
|
104
|
+
quality:[quality floatValue]
|
|
105
|
+
result:result
|
|
106
|
+
callback:resolve];
|
|
107
|
+
|
|
108
|
+
} reject:reject];
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
}
|
|
112
|
+
- (void)getAddressFromCoordinates:(double)tag
|
|
113
|
+
coordinate:(JS::NativeAirMapsModule::LatLng &)coordinate
|
|
114
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
115
|
+
reject:(RCTPromiseRejectBlock)reject
|
|
116
|
+
{
|
|
117
|
+
double latitude = coordinate.latitude();
|
|
118
|
+
double longitude = coordinate.longitude();
|
|
119
|
+
|
|
120
|
+
[self executeWithMapView:tag success:^(AIRMap *mapView) {
|
|
121
|
+
CLLocation *location = [[CLLocation alloc] initWithLatitude:latitude
|
|
122
|
+
longitude:longitude];
|
|
123
|
+
CLGeocoder *geoCoder = [[CLGeocoder alloc] init];
|
|
124
|
+
[geoCoder reverseGeocodeLocation:location
|
|
125
|
+
completionHandler:^(NSArray *placemarks, NSError *error) {
|
|
126
|
+
if (error == nil && [placemarks count] > 0){
|
|
127
|
+
CLPlacemark *placemark = placemarks[0];
|
|
128
|
+
resolve(@{
|
|
129
|
+
@"name" : [NSString stringWithFormat:@"%@", placemark.name],
|
|
130
|
+
@"thoroughfare" : [NSString stringWithFormat:@"%@", placemark.thoroughfare],
|
|
131
|
+
@"subThoroughfare" : [NSString stringWithFormat:@"%@", placemark.subThoroughfare],
|
|
132
|
+
@"locality" : [NSString stringWithFormat:@"%@", placemark.locality],
|
|
133
|
+
@"subLocality" : [NSString stringWithFormat:@"%@", placemark.subLocality],
|
|
134
|
+
@"administrativeArea" : [NSString stringWithFormat:@"%@", placemark.administrativeArea],
|
|
135
|
+
@"subAdministrativeArea" : [NSString stringWithFormat:@"%@", placemark.subAdministrativeArea],
|
|
136
|
+
@"postalCode" : [NSString stringWithFormat:@"%@", placemark.postalCode],
|
|
137
|
+
@"countryCode" : [NSString stringWithFormat:@"%@", placemark.ISOcountryCode],
|
|
138
|
+
@"country" : [NSString stringWithFormat:@"%@", placemark.country],
|
|
139
|
+
});
|
|
140
|
+
} else {
|
|
141
|
+
reject(@"Invalid argument", [NSString stringWithFormat:@"Can not get address location"], NULL);
|
|
142
|
+
}
|
|
143
|
+
}];
|
|
144
|
+
|
|
145
|
+
} reject:reject];
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
- (void)getPointForCoordinate:(double)tag
|
|
149
|
+
coordinate:(JS::NativeAirMapsModule::LatLng &)coordinate
|
|
150
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
151
|
+
reject:(RCTPromiseRejectBlock)reject
|
|
152
|
+
{
|
|
153
|
+
double latitude = coordinate.latitude();
|
|
154
|
+
double longitude = coordinate.longitude();
|
|
155
|
+
|
|
156
|
+
[self executeWithMapView:tag success:^(AIRMap *mapView) {
|
|
157
|
+
|
|
158
|
+
CGPoint touchPoint = [mapView convertCoordinate:
|
|
159
|
+
CLLocationCoordinate2DMake(latitude,longitude)
|
|
160
|
+
toPointToView:mapView];
|
|
161
|
+
|
|
162
|
+
resolve(@{
|
|
163
|
+
@"x": @(touchPoint.x),
|
|
164
|
+
@"y": @(touchPoint.y),
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
} reject:reject];
|
|
168
|
+
|
|
169
|
+
}
|
|
170
|
+
- (void)getCoordinateForPoint:(double)tag
|
|
171
|
+
point:(JS::NativeAirMapsModule::Point &)point
|
|
172
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
173
|
+
reject:(RCTPromiseRejectBlock)reject
|
|
174
|
+
{
|
|
175
|
+
double x = point.x();
|
|
176
|
+
double y = point.y();
|
|
177
|
+
|
|
178
|
+
[self executeWithMapView:tag success:^(AIRMap *mapView) {
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
CLLocationCoordinate2D coordinate = [mapView convertPoint:CGPointMake(x,y)
|
|
182
|
+
toCoordinateFromView:mapView];
|
|
183
|
+
|
|
184
|
+
resolve(@{
|
|
185
|
+
@"latitude": @(coordinate.latitude),
|
|
186
|
+
@"longitude": @(coordinate.longitude),
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
} reject:reject];
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
|
|
195
|
+
(const facebook::react::ObjCTurboModule::InitParams &)params
|
|
196
|
+
{
|
|
197
|
+
return std::make_shared<facebook::react::NativeAirMapsModuleSpecJSI>(params);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
+ (NSString *)moduleName {
|
|
201
|
+
return nil;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
#pragma mark Take Snapshot
|
|
205
|
+
- (void)takeMapSnapshot:(AIRMap *)mapView
|
|
206
|
+
snapshotter:(MKMapSnapshotter *) snapshotter
|
|
207
|
+
format:(NSString *)format
|
|
208
|
+
quality:(CGFloat) quality
|
|
209
|
+
result:(NSString *)result
|
|
210
|
+
callback:(RCTPromiseResolveBlock) callback {
|
|
211
|
+
NSTimeInterval timeStamp = [[NSDate date] timeIntervalSince1970];
|
|
212
|
+
NSString *pathComponent = [NSString stringWithFormat:@"Documents/snapshot-%.20lf.%@", timeStamp, format];
|
|
213
|
+
NSString *filePath = [NSHomeDirectory() stringByAppendingPathComponent: pathComponent];
|
|
214
|
+
|
|
215
|
+
[snapshotter startWithQueue:dispatch_get_main_queue()
|
|
216
|
+
completionHandler:^(MKMapSnapshot *snapshot, NSError *error) {
|
|
217
|
+
if (error) {
|
|
218
|
+
callback(@[error]);
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
MKAnnotationView *pin = [[MKPinAnnotationView alloc] initWithAnnotation:nil reuseIdentifier:nil];
|
|
222
|
+
|
|
223
|
+
UIImage *image = snapshot.image;
|
|
224
|
+
UIGraphicsBeginImageContextWithOptions(image.size, YES, image.scale);
|
|
225
|
+
{
|
|
226
|
+
[image drawAtPoint:CGPointMake(0.0f, 0.0f)];
|
|
227
|
+
|
|
228
|
+
CGRect rect = CGRectMake(0.0f, 0.0f, image.size.width, image.size.height);
|
|
229
|
+
|
|
230
|
+
for (id <AIRMapSnapshot> overlay in mapView.overlays) {
|
|
231
|
+
if ([overlay respondsToSelector:@selector(drawToSnapshot:context:)]) {
|
|
232
|
+
[overlay drawToSnapshot:snapshot context:UIGraphicsGetCurrentContext()];
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
for (id <MKAnnotation> annotation in mapView.annotations) {
|
|
237
|
+
CGPoint point = [snapshot pointForCoordinate:annotation.coordinate];
|
|
238
|
+
|
|
239
|
+
MKAnnotationView* anView = [mapView viewForAnnotation: annotation];
|
|
240
|
+
|
|
241
|
+
if (anView){
|
|
242
|
+
pin = anView;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
if (CGRectContainsPoint(rect, point)) {
|
|
246
|
+
point.x = point.x + pin.centerOffset.x - (pin.bounds.size.width / 2.0f);
|
|
247
|
+
point.y = point.y + pin.centerOffset.y - (pin.bounds.size.height / 2.0f);
|
|
248
|
+
if (pin.image) {
|
|
249
|
+
[pin.image drawAtPoint:point];
|
|
250
|
+
} else {
|
|
251
|
+
CGRect pinRect = CGRectMake(point.x, point.y, pin.bounds.size.width, pin.bounds.size.height);
|
|
252
|
+
[pin drawViewHierarchyInRect:pinRect afterScreenUpdates:NO];
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
UIImage *compositeImage = UIGraphicsGetImageFromCurrentImageContext();
|
|
258
|
+
|
|
259
|
+
NSData *data;
|
|
260
|
+
if ([format isEqualToString:@"png"]) {
|
|
261
|
+
data = UIImagePNGRepresentation(compositeImage);
|
|
262
|
+
}
|
|
263
|
+
else if([format isEqualToString:@"jpg"]) {
|
|
264
|
+
data = UIImageJPEGRepresentation(compositeImage, quality);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
if ([result isEqualToString:@"file"]) {
|
|
268
|
+
[data writeToFile:filePath atomically:YES];
|
|
269
|
+
callback(filePath);
|
|
270
|
+
}
|
|
271
|
+
else if ([result isEqualToString:@"base64"]) {
|
|
272
|
+
callback([data base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithCarriageReturn]);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
UIGraphicsEndImageContext();
|
|
276
|
+
}];
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
@end
|
|
280
|
+
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
//
|
|
2
|
+
// RNMapsMarker.h
|
|
3
|
+
// AirMaps
|
|
4
|
+
//
|
|
5
|
+
// Created by Salah Ghanim on 23.11.24.
|
|
6
|
+
// Copyright © 2024 react-native-maps. All rights reserved.
|
|
7
|
+
//
|
|
8
|
+
|
|
9
|
+
#import <React/RCTViewComponentView.h>
|
|
10
|
+
#import <UIKit/UIKit.h>
|
|
11
|
+
@class AIRMap;
|
|
12
|
+
|
|
13
|
+
NS_ASSUME_NONNULL_BEGIN
|
|
14
|
+
|
|
15
|
+
@interface RNMapsMapView : RCTViewComponentView
|
|
16
|
+
|
|
17
|
+
- (AIRMap *) mapView;
|
|
18
|
+
|
|
19
|
+
@end
|
|
20
|
+
|
|
21
|
+
NS_ASSUME_NONNULL_END
|