@lugg/maps 0.2.0-alpha.22 → 0.2.0-alpha.24

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 (32) hide show
  1. package/README.md +5 -0
  2. package/android/src/main/java/com/luggmaps/LuggMapView.kt +241 -0
  3. package/android/src/main/java/com/luggmaps/{LuggGoogleMapViewManager.kt → LuggMapViewManager.kt} +36 -31
  4. package/android/src/main/java/com/luggmaps/LuggPackage.kt +1 -4
  5. package/android/src/main/java/com/luggmaps/{LuggGoogleMapView.kt → core/GoogleMapProvider.kt} +172 -212
  6. package/android/src/main/java/com/luggmaps/core/MapProviderDelegate.kt +53 -0
  7. package/android/src/main/java/com/luggmaps/core/PolylineAnimator.kt +32 -26
  8. package/ios/LuggMapView.h +9 -0
  9. package/ios/LuggMapView.mm +285 -0
  10. package/ios/core/AppleMapProvider.h +15 -0
  11. package/ios/{LuggAppleMapView.mm → core/AppleMapProvider.mm} +310 -421
  12. package/ios/core/GMSPolylineAnimator.m +16 -4
  13. package/ios/core/GoogleMapProvider.h +13 -0
  14. package/ios/{LuggGoogleMapView.mm → core/GoogleMapProvider.mm} +178 -238
  15. package/ios/core/MapProviderDelegate.h +68 -0
  16. package/lib/module/MapView.js +5 -11
  17. package/lib/module/MapView.js.map +1 -1
  18. package/lib/module/fabric/{LuggGoogleMapViewNativeComponent.ts → LuggMapViewNativeComponent.ts} +2 -1
  19. package/lib/typescript/src/MapView.d.ts +0 -1
  20. package/lib/typescript/src/MapView.d.ts.map +1 -1
  21. package/lib/typescript/src/fabric/{LuggGoogleMapViewNativeComponent.d.ts → LuggMapViewNativeComponent.d.ts} +2 -1
  22. package/lib/typescript/src/fabric/LuggMapViewNativeComponent.d.ts.map +1 -0
  23. package/package.json +3 -4
  24. package/src/MapView.tsx +8 -21
  25. package/src/fabric/{LuggGoogleMapViewNativeComponent.ts → LuggMapViewNativeComponent.ts} +2 -1
  26. package/ios/LuggAppleMapView.h +0 -16
  27. package/ios/LuggGoogleMapView.h +0 -13
  28. package/lib/module/fabric/LuggAppleMapViewNativeComponent.ts +0 -85
  29. package/lib/typescript/src/fabric/LuggAppleMapViewNativeComponent.d.ts +0 -55
  30. package/lib/typescript/src/fabric/LuggAppleMapViewNativeComponent.d.ts.map +0 -1
  31. package/lib/typescript/src/fabric/LuggGoogleMapViewNativeComponent.d.ts.map +0 -1
  32. package/src/fabric/LuggAppleMapViewNativeComponent.ts +0 -85
@@ -1,22 +1,8 @@
1
- #import "LuggAppleMapView.h"
2
- #import "LuggMapWrapperView.h"
3
- #import "LuggMarkerView.h"
4
- #import "LuggPolylineView.h"
5
- #import "core/MKPolylineAnimator.h"
6
- #import "events/CameraIdleEvent.h"
7
- #import "events/CameraMoveEvent.h"
8
- #import "events/ReadyEvent.h"
9
- #import "extensions/MKMapView+Zoom.h"
10
-
11
- #import <react/renderer/components/RNMapsSpec/ComponentDescriptors.h>
12
- #import <react/renderer/components/RNMapsSpec/EventEmitters.h>
13
- #import <react/renderer/components/RNMapsSpec/Props.h>
14
- #import <react/renderer/components/RNMapsSpec/RCTComponentViewHelpers.h>
15
-
16
- #import "RCTFabricComponentsPlugins.h"
17
-
18
- using namespace facebook::react;
19
- using namespace luggmaps::events;
1
+ #import "AppleMapProvider.h"
2
+ #import "../LuggMarkerView.h"
3
+ #import "../LuggPolylineView.h"
4
+ #import "../extensions/MKMapView+Zoom.h"
5
+ #import "MKPolylineAnimator.h"
20
6
 
21
7
  @interface AppleMarkerAnnotation : NSObject <MKAnnotation>
22
8
  @property(nonatomic, assign) CLLocationCoordinate2D coordinate;
@@ -32,14 +18,12 @@ using namespace luggmaps::events;
32
18
  @implementation LuggAppleMapViewContent
33
19
  @end
34
20
 
35
- @interface LuggAppleMapView () <RCTLuggAppleMapViewViewProtocol,
36
- MKMapViewDelegate, LuggMarkerViewDelegate,
21
+ @interface AppleMapProvider () <LuggMarkerViewDelegate,
37
22
  LuggPolylineViewDelegate>
38
23
  @end
39
24
 
40
- @implementation LuggAppleMapView {
25
+ @implementation AppleMapProvider {
41
26
  LuggAppleMapViewContent *_mapView;
42
- LuggMapWrapperView *_mapWrapperView;
43
27
  BOOL _isMapReady;
44
28
  BOOL _isDragging;
45
29
  double _minZoom;
@@ -47,179 +31,122 @@ using namespace luggmaps::events;
47
31
  NSMapTable<id<MKOverlay>, LuggPolylineView *> *_overlayToPolylineMap;
48
32
  }
49
33
 
50
- + (ComponentDescriptorProvider)componentDescriptorProvider {
51
- return concreteComponentDescriptorProvider<
52
- LuggAppleMapViewComponentDescriptor>();
53
- }
34
+ @synthesize delegate = _delegate;
54
35
 
55
- - (instancetype)initWithFrame:(CGRect)frame {
56
- if (self = [super initWithFrame:frame]) {
57
- static const auto defaultProps =
58
- std::make_shared<const LuggAppleMapViewProps>();
59
- _props = defaultProps;
36
+ - (instancetype)init {
37
+ if (self = [super init]) {
60
38
  _overlayToPolylineMap = [NSMapTable strongToWeakObjectsMapTable];
61
39
  }
62
-
63
40
  return self;
64
41
  }
65
42
 
66
- #pragma mark - View Lifecycle
43
+ - (BOOL)isMapReady {
44
+ return _isMapReady;
45
+ }
67
46
 
68
- - (void)mountChildComponentView:
69
- (UIView<RCTComponentViewProtocol> *)childComponentView
70
- index:(NSInteger)index {
71
- [super mountChildComponentView:childComponentView index:index];
47
+ - (MKMapView *)mapView {
48
+ return _mapView;
49
+ }
72
50
 
73
- if ([childComponentView isKindOfClass:[LuggMapWrapperView class]]) {
74
- _mapWrapperView = (LuggMapWrapperView *)childComponentView;
75
- } else if ([childComponentView isKindOfClass:[LuggMarkerView class]]) {
76
- LuggMarkerView *markerView = (LuggMarkerView *)childComponentView;
77
- markerView.delegate = self;
51
+ #pragma mark - MapProvider
78
52
 
79
- AppleMarkerAnnotation *annotation = [[AppleMarkerAnnotation alloc] init];
80
- annotation.markerView = markerView;
81
- markerView.marker = annotation;
53
+ - (void)initializeMapInView:(UIView *)wrapperView
54
+ initialCoordinate:(CLLocationCoordinate2D)coordinate
55
+ initialZoom:(double)zoom {
56
+ if (_mapView)
57
+ return;
82
58
 
83
- if (_mapView) {
84
- [_mapView addAnnotation:annotation];
85
- }
59
+ _mapView = [[LuggAppleMapViewContent alloc] initWithFrame:wrapperView.bounds];
60
+ _mapView.autoresizingMask =
61
+ UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
62
+ _mapView.delegate = self;
63
+ _mapView.insetsLayoutMarginsFromSafeArea = NO;
86
64
 
87
- [self markerViewDidUpdate:markerView];
88
- } else if ([childComponentView isKindOfClass:[LuggPolylineView class]]) {
89
- LuggPolylineView *polylineView = (LuggPolylineView *)childComponentView;
90
- polylineView.delegate = self;
91
- [self addPolylineViewToMap:polylineView];
92
- }
93
- }
65
+ [self applyZoomRange];
94
66
 
95
- - (void)unmountChildComponentView:
96
- (UIView<RCTComponentViewProtocol> *)childComponentView
97
- index:(NSInteger)index {
98
- if ([childComponentView isKindOfClass:[LuggMarkerView class]]) {
99
- LuggMarkerView *markerView = (LuggMarkerView *)childComponentView;
100
- markerView.delegate = nil;
67
+ [wrapperView addSubview:_mapView];
101
68
 
102
- AppleMarkerAnnotation *annotation =
103
- (AppleMarkerAnnotation *)markerView.marker;
69
+ MKCoordinateRegion region = [_mapView regionForCenterCoordinate:coordinate
70
+ zoomLevel:zoom];
71
+ [_mapView setRegion:region animated:NO];
104
72
 
105
- if (annotation) {
106
- annotation.annotationView.transform = CGAffineTransformIdentity;
107
- annotation.markerView = nil;
108
- annotation.annotationView = nil;
109
- [_mapView removeAnnotation:annotation];
110
- markerView.marker = nil;
111
- }
112
- [markerView resetIconViewTransform];
113
- } else if ([childComponentView isKindOfClass:[LuggPolylineView class]]) {
114
- LuggPolylineView *polylineView = (LuggPolylineView *)childComponentView;
115
- polylineView.delegate = nil;
116
- MKPolyline *polyline = (MKPolyline *)polylineView.polyline;
117
- if (polyline) {
118
- [_overlayToPolylineMap removeObjectForKey:polyline];
119
- [_mapView removeOverlay:polyline];
120
- polylineView.polyline = nil;
121
- }
122
- }
73
+ _isMapReady = YES;
123
74
 
124
- [super unmountChildComponentView:childComponentView index:index];
75
+ [_delegate mapProviderDidReady];
125
76
  }
126
77
 
127
- - (void)didMoveToWindow {
128
- [super didMoveToWindow];
129
- if (self.window && !_mapView && _mapWrapperView) {
130
- [self initializeMap];
131
- }
132
- }
133
-
134
- - (void)prepareForRecycle {
135
- [super prepareForRecycle];
136
-
78
+ - (void)destroy {
137
79
  [_mapView removeFromSuperview];
138
80
  _mapView = nil;
139
- _mapWrapperView = nil;
140
81
  _isMapReady = NO;
141
82
  }
142
83
 
143
- #pragma mark - Map Initialization
84
+ #pragma mark - Props
144
85
 
145
- - (void)initializeMap {
146
- if (_mapView || !_mapWrapperView) {
147
- return;
148
- }
86
+ - (void)setZoomEnabled:(BOOL)enabled {
87
+ _mapView.zoomEnabled = enabled;
88
+ }
149
89
 
150
- const auto &viewProps =
151
- *std::static_pointer_cast<LuggAppleMapViewProps const>(_props);
90
+ - (void)setScrollEnabled:(BOOL)enabled {
91
+ _mapView.scrollEnabled = enabled;
92
+ }
152
93
 
153
- _mapView =
154
- [[LuggAppleMapViewContent alloc] initWithFrame:_mapWrapperView.bounds];
155
- _mapView.autoresizingMask =
156
- UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
157
- _mapView.delegate = self;
158
- _mapView.insetsLayoutMarginsFromSafeArea = NO;
159
- _mapView.zoomEnabled = viewProps.zoomEnabled;
160
- _mapView.scrollEnabled = viewProps.scrollEnabled;
161
- _mapView.rotateEnabled = viewProps.rotateEnabled;
162
- _mapView.pitchEnabled = viewProps.pitchEnabled;
163
- _mapView.showsUserLocation = viewProps.userLocationEnabled;
94
+ - (void)setRotateEnabled:(BOOL)enabled {
95
+ _mapView.rotateEnabled = enabled;
96
+ }
164
97
 
165
- if (viewProps.theme == LuggAppleMapViewTheme::Dark) {
98
+ - (void)setPitchEnabled:(BOOL)enabled {
99
+ _mapView.pitchEnabled = enabled;
100
+ }
101
+
102
+ - (void)setUserLocationEnabled:(BOOL)enabled {
103
+ _mapView.showsUserLocation = enabled;
104
+ }
105
+
106
+ - (void)setTheme:(NSString *)theme {
107
+ if ([theme isEqualToString:@"dark"]) {
166
108
  _mapView.overrideUserInterfaceStyle = UIUserInterfaceStyleDark;
167
- } else if (viewProps.theme == LuggAppleMapViewTheme::Light) {
109
+ } else if ([theme isEqualToString:@"light"]) {
168
110
  _mapView.overrideUserInterfaceStyle = UIUserInterfaceStyleLight;
169
111
  } else {
170
112
  _mapView.overrideUserInterfaceStyle = UIUserInterfaceStyleUnspecified;
171
113
  }
114
+ }
172
115
 
173
- _minZoom = viewProps.minZoom;
174
- _maxZoom = viewProps.maxZoom;
116
+ - (void)setMinZoom:(double)minZoom {
117
+ _minZoom = minZoom;
175
118
  [self applyZoomRange];
119
+ }
176
120
 
177
- _mapView.layoutMargins =
178
- UIEdgeInsetsMake(viewProps.padding.top, viewProps.padding.left,
179
- viewProps.padding.bottom, viewProps.padding.right);
180
-
181
- [_mapWrapperView addSubview:_mapView];
182
-
183
- CLLocationCoordinate2D center =
184
- CLLocationCoordinate2DMake(viewProps.initialCoordinate.latitude,
185
- viewProps.initialCoordinate.longitude);
186
- MKCoordinateRegion region =
187
- [_mapView regionForCenterCoordinate:center
188
- zoomLevel:viewProps.initialZoom];
189
- [_mapView setRegion:region animated:NO];
121
+ - (void)setMaxZoom:(double)maxZoom {
122
+ _maxZoom = maxZoom;
123
+ [self applyZoomRange];
124
+ }
190
125
 
191
- // Add annotations for any markers that were mounted before map was ready
192
- for (UIView *subview in self.subviews) {
193
- if ([subview isKindOfClass:[LuggMarkerView class]]) {
194
- LuggMarkerView *markerView = (LuggMarkerView *)subview;
195
- AppleMarkerAnnotation *annotation =
196
- (AppleMarkerAnnotation *)markerView.marker;
197
- if (annotation) {
198
- [_mapView addAnnotation:annotation];
199
- }
200
- } else if ([subview isKindOfClass:[LuggPolylineView class]]) {
201
- LuggPolylineView *polylineView = (LuggPolylineView *)subview;
202
- [self addPolylineViewToMap:polylineView];
203
- }
204
- }
126
+ - (void)setPadding:(UIEdgeInsets)padding oldPadding:(UIEdgeInsets)oldPadding {
127
+ CGFloat oldOffsetX = (oldPadding.left - oldPadding.right) / 2.0;
128
+ CGFloat oldOffsetY = (oldPadding.top - oldPadding.bottom) / 2.0;
129
+ CGFloat newOffsetX = (padding.left - padding.right) / 2.0;
130
+ CGFloat newOffsetY = (padding.top - padding.bottom) / 2.0;
205
131
 
206
- _isMapReady = YES;
132
+ CGFloat deltaX = newOffsetX - oldOffsetX;
133
+ CGFloat deltaY = newOffsetY - oldOffsetY;
207
134
 
208
- ReadyEvent::emit<LuggAppleMapViewEventEmitter>(_eventEmitter);
209
- }
135
+ _mapView.layoutMargins = padding;
210
136
 
211
- - (void)setCameraWithLatitude:(double)latitude
212
- longitude:(double)longitude
213
- zoom:(double)zoom
214
- animated:(BOOL)animated {
215
- CLLocationCoordinate2D center =
216
- CLLocationCoordinate2DMake(latitude, longitude);
217
- [_mapView setCenterCoordinate:center zoomLevel:zoom animated:animated];
137
+ if (deltaX != 0 || deltaY != 0) {
138
+ CLLocationCoordinate2D currentCenter = _mapView.centerCoordinate;
139
+ CGPoint centerPoint = [_mapView convertCoordinate:currentCenter
140
+ toPointToView:_mapView];
141
+ CGPoint newPoint =
142
+ CGPointMake(centerPoint.x - deltaX, centerPoint.y - deltaY);
143
+ CLLocationCoordinate2D newCenter = [_mapView convertPoint:newPoint
144
+ toCoordinateFromView:_mapView];
145
+ [_mapView setCenterCoordinate:newCenter animated:NO];
146
+ }
218
147
  }
219
148
 
220
149
  - (CLLocationDistance)cameraDistanceForZoomLevel:(double)zoomLevel {
221
- // Approximate conversion: at zoom 0, altitude ~128M km
222
- // Each zoom level halves the altitude
223
150
  return 128000000.0 / pow(2, zoomLevel);
224
151
  }
225
152
 
@@ -238,88 +165,189 @@ using namespace luggmaps::events;
238
165
  _mapView.cameraZoomRange = zoomRange;
239
166
  }
240
167
 
241
- - (MKMapView *)mapView {
242
- return _mapView;
168
+ #pragma mark - MKMapViewDelegate
169
+
170
+ - (BOOL)isUserInteracting {
171
+ UIView *mapContainerView = _mapView.subviews.firstObject;
172
+ for (UIGestureRecognizer *gesture in mapContainerView.gestureRecognizers) {
173
+ if (gesture.state == UIGestureRecognizerStateBegan ||
174
+ gesture.state == UIGestureRecognizerStateChanged) {
175
+ return YES;
176
+ }
177
+ }
178
+ return NO;
243
179
  }
244
180
 
245
- #pragma mark - Property Setters
181
+ - (void)mapView:(MKMapView *)mapView regionWillChangeAnimated:(BOOL)animated {
182
+ _isDragging = [self isUserInteracting];
183
+ if (_isDragging) {
184
+ for (LuggPolylineView *polylineView in _overlayToPolylineMap
185
+ .objectEnumerator) {
186
+ MKPolylineAnimator *renderer =
187
+ (MKPolylineAnimator *)polylineView.renderer;
188
+ [renderer pause];
189
+ }
190
+ }
191
+ }
246
192
 
247
- - (void)updateProps:(Props::Shared const &)props
248
- oldProps:(Props::Shared const &)oldProps {
249
- const auto &oldViewProps =
250
- *std::static_pointer_cast<LuggAppleMapViewProps const>(oldProps);
251
- const auto &newViewProps =
252
- *std::static_pointer_cast<LuggAppleMapViewProps const>(props);
193
+ - (void)mapViewDidChangeVisibleRegion:(MKMapView *)mapView {
194
+ [_delegate mapProviderDidMoveCamera:mapView.centerCoordinate.latitude
195
+ longitude:mapView.centerCoordinate.longitude
196
+ zoom:mapView.zoomLevel
197
+ gesture:_isDragging];
198
+ }
253
199
 
254
- if (_mapView) {
255
- _mapView.zoomEnabled = newViewProps.zoomEnabled;
256
- _mapView.scrollEnabled = newViewProps.scrollEnabled;
257
- _mapView.rotateEnabled = newViewProps.rotateEnabled;
258
- _mapView.pitchEnabled = newViewProps.pitchEnabled;
259
- _mapView.showsUserLocation = newViewProps.userLocationEnabled;
260
-
261
- if (oldViewProps.theme != newViewProps.theme) {
262
- if (newViewProps.theme == LuggAppleMapViewTheme::Dark) {
263
- _mapView.overrideUserInterfaceStyle = UIUserInterfaceStyleDark;
264
- } else if (newViewProps.theme == LuggAppleMapViewTheme::Light) {
265
- _mapView.overrideUserInterfaceStyle = UIUserInterfaceStyleLight;
266
- } else {
267
- _mapView.overrideUserInterfaceStyle = UIUserInterfaceStyleUnspecified;
268
- }
200
+ - (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated {
201
+ BOOL wasDragging = _isDragging;
202
+ _isDragging = NO;
203
+ if (wasDragging) {
204
+ for (LuggPolylineView *polylineView in _overlayToPolylineMap
205
+ .objectEnumerator) {
206
+ MKPolylineAnimator *renderer =
207
+ (MKPolylineAnimator *)polylineView.renderer;
208
+ [renderer resume];
269
209
  }
210
+ }
211
+ [_delegate mapProviderDidIdleCamera:mapView.centerCoordinate.latitude
212
+ longitude:mapView.centerCoordinate.longitude
213
+ zoom:mapView.zoomLevel
214
+ gesture:wasDragging];
215
+ }
270
216
 
271
- // Check if padding changed
272
- BOOL paddingChanged =
273
- oldViewProps.padding.top != newViewProps.padding.top ||
274
- oldViewProps.padding.left != newViewProps.padding.left ||
275
- oldViewProps.padding.bottom != newViewProps.padding.bottom ||
276
- oldViewProps.padding.right != newViewProps.padding.right;
277
-
278
- if (paddingChanged) {
279
- // Calculate the offset difference to keep visual center stable
280
- CGFloat oldOffsetX =
281
- (oldViewProps.padding.left - oldViewProps.padding.right) / 2.0;
282
- CGFloat oldOffsetY =
283
- (oldViewProps.padding.top - oldViewProps.padding.bottom) / 2.0;
284
- CGFloat newOffsetX =
285
- (newViewProps.padding.left - newViewProps.padding.right) / 2.0;
286
- CGFloat newOffsetY =
287
- (newViewProps.padding.top - newViewProps.padding.bottom) / 2.0;
288
-
289
- CGFloat deltaX = newOffsetX - oldOffsetX;
290
- CGFloat deltaY = newOffsetY - oldOffsetY;
291
-
292
- // Apply new padding first
293
- _mapView.layoutMargins = UIEdgeInsetsMake(
294
- newViewProps.padding.top, newViewProps.padding.left,
295
- newViewProps.padding.bottom, newViewProps.padding.right);
296
-
297
- // Convert pixel offset to coordinate offset
298
- if (deltaX != 0 || deltaY != 0) {
299
- CLLocationCoordinate2D currentCenter = _mapView.centerCoordinate;
300
- CGPoint centerPoint = [_mapView convertCoordinate:currentCenter
301
- toPointToView:_mapView];
302
- CGPoint newPoint =
303
- CGPointMake(centerPoint.x - deltaX, centerPoint.y - deltaY);
304
- CLLocationCoordinate2D newCenter = [_mapView convertPoint:newPoint
305
- toCoordinateFromView:_mapView];
306
- [_mapView setCenterCoordinate:newCenter animated:NO];
217
+ - (MKAnnotationView *)mapView:(MKMapView *)mapView
218
+ viewForAnnotation:(id<MKAnnotation>)annotation {
219
+ if (![annotation isKindOfClass:[AppleMarkerAnnotation class]]) {
220
+ return nil;
221
+ }
222
+
223
+ AppleMarkerAnnotation *markerAnnotation = (AppleMarkerAnnotation *)annotation;
224
+ LuggMarkerView *markerView = markerAnnotation.markerView;
225
+
226
+ if (!markerView || !markerView.hasCustomView) {
227
+ return nil;
228
+ }
229
+
230
+ MKAnnotationView *annotationView =
231
+ [[MKAnnotationView alloc] initWithAnnotation:annotation
232
+ reuseIdentifier:nil];
233
+ annotationView.canShowCallout = YES;
234
+ annotationView.displayPriority = MKFeatureDisplayPriorityRequired;
235
+ annotationView.layer.zPosition = markerView.zIndex;
236
+ annotationView.zPriority = markerView.zIndex;
237
+
238
+ if (!markerView.rasterize) {
239
+ UIView *iconView = markerView.iconView;
240
+ [iconView removeFromSuperview];
241
+ [annotationView addSubview:iconView];
242
+ }
243
+
244
+ [self applyMarkerStyle:markerView annotationView:annotationView];
245
+ markerAnnotation.annotationView = annotationView;
246
+
247
+ return annotationView;
248
+ }
249
+
250
+ - (MKOverlayRenderer *)mapView:(MKMapView *)mapView
251
+ rendererForOverlay:(id<MKOverlay>)overlay {
252
+ if ([overlay isKindOfClass:[MKPolyline class]]) {
253
+ LuggPolylineView *polylineView =
254
+ [_overlayToPolylineMap objectForKey:overlay];
255
+ MKPolyline *polyline = (MKPolyline *)overlay;
256
+
257
+ if (polylineView) {
258
+ NSArray<UIColor *> *colors = polylineView.strokeColors;
259
+
260
+ MKPolylineAnimator *renderer =
261
+ [[MKPolylineAnimator alloc] initWithPolyline:polyline];
262
+ renderer.lineWidth = polylineView.strokeWidth;
263
+ renderer.strokeColor = colors.firstObject;
264
+ if (colors.count > 1) {
265
+ renderer.strokeColors = colors;
307
266
  }
308
- } else {
309
- _mapView.layoutMargins = UIEdgeInsetsMake(
310
- newViewProps.padding.top, newViewProps.padding.left,
311
- newViewProps.padding.bottom, newViewProps.padding.right);
267
+ renderer.animatedOptions = polylineView.animatedOptions;
268
+ renderer.animated = polylineView.animated;
269
+ polylineView.renderer = renderer;
270
+ return renderer;
312
271
  }
313
272
 
314
- _minZoom = newViewProps.minZoom;
315
- _maxZoom = newViewProps.maxZoom;
316
- [self applyZoomRange];
273
+ MKPolylineRenderer *renderer =
274
+ [[MKPolylineRenderer alloc] initWithPolyline:polyline];
275
+ return renderer;
317
276
  }
277
+ return nil;
278
+ }
279
+
280
+ #pragma mark - MarkerViewDelegate
281
+
282
+ - (void)markerViewDidLayout:(LuggMarkerView *)markerView {
283
+ AppleMarkerAnnotation *annotation =
284
+ (AppleMarkerAnnotation *)markerView.marker;
285
+ if (annotation) {
286
+ [self updateAnnotationViewFrame:annotation];
287
+ }
288
+ }
289
+
290
+ - (void)markerViewDidUpdate:(LuggMarkerView *)markerView {
291
+ AppleMarkerAnnotation *annotation =
292
+ (AppleMarkerAnnotation *)markerView.marker;
293
+
294
+ if (!annotation)
295
+ return;
296
+
297
+ annotation.coordinate = markerView.coordinate;
298
+ annotation.title = markerView.title;
299
+ annotation.subtitle = markerView.markerDescription;
300
+
301
+ MKAnnotationView *annotationView = annotation.annotationView;
302
+ if (annotationView) {
303
+ annotationView.layer.zPosition = markerView.zIndex;
304
+ annotationView.zPriority = markerView.zIndex;
305
+ }
306
+
307
+ [self updateAnnotationViewFrame:annotation];
308
+ }
309
+
310
+ #pragma mark - PolylineViewDelegate
311
+
312
+ - (void)polylineViewDidUpdate:(LuggPolylineView *)polylineView {
313
+ [self syncPolylineView:polylineView];
314
+ }
315
+
316
+ #pragma mark - Marker Management
317
+
318
+ - (void)addMarkerView:(LuggMarkerView *)markerView {
319
+ markerView.delegate = self;
320
+
321
+ AppleMarkerAnnotation *annotation = [[AppleMarkerAnnotation alloc] init];
322
+ annotation.markerView = markerView;
323
+ markerView.marker = annotation;
324
+
325
+ if (_mapView) {
326
+ [_mapView addAnnotation:annotation];
327
+ }
328
+
329
+ [self markerViewDidUpdate:markerView];
330
+ }
331
+
332
+ - (void)removeMarkerView:(LuggMarkerView *)markerView {
333
+ markerView.delegate = nil;
318
334
 
319
- [super updateProps:props oldProps:oldProps];
335
+ AppleMarkerAnnotation *annotation =
336
+ (AppleMarkerAnnotation *)markerView.marker;
337
+
338
+ if (annotation) {
339
+ annotation.annotationView.transform = CGAffineTransformIdentity;
340
+ annotation.markerView = nil;
341
+ annotation.annotationView = nil;
342
+ [_mapView removeAnnotation:annotation];
343
+ markerView.marker = nil;
344
+ }
345
+ [markerView resetIconViewTransform];
320
346
  }
321
347
 
322
- #pragma mark - Annotation Helpers
348
+ - (void)syncMarkerView:(LuggMarkerView *)markerView {
349
+ [self markerViewDidUpdate:markerView];
350
+ }
323
351
 
324
352
  - (void)applyMarkerStyle:(LuggMarkerView *)markerView
325
353
  annotationView:(MKAnnotationView *)annotationView {
@@ -357,55 +385,36 @@ using namespace luggmaps::events;
357
385
  MKAnnotationView *annotationView = annotation.annotationView;
358
386
  LuggMarkerView *markerView = annotation.markerView;
359
387
 
360
- if (!annotationView || !markerView) {
388
+ if (!annotationView || !markerView)
361
389
  return;
362
- }
363
390
 
364
391
  [self applyMarkerStyle:markerView annotationView:annotationView];
365
392
  }
366
393
 
367
- #pragma mark - PolylineViewDelegate
368
-
369
- - (void)polylineViewDidUpdate:(LuggPolylineView *)polylineView {
370
- [self syncPolylineView:polylineView];
371
- }
372
-
373
394
  #pragma mark - Polyline Management
374
395
 
375
- - (void)addPolylineViewToMap:(LuggPolylineView *)polylineView {
376
- if (!_mapView) {
377
- return;
378
- }
396
+ - (void)addPolylineView:(LuggPolylineView *)polylineView {
397
+ polylineView.delegate = self;
398
+ [self addPolylineOverlayToMap:polylineView];
399
+ }
379
400
 
380
- NSArray<CLLocation *> *coordinates = polylineView.coordinates;
381
- if (coordinates.count == 0) {
382
- return;
401
+ - (void)removePolylineView:(LuggPolylineView *)polylineView {
402
+ polylineView.delegate = nil;
403
+ MKPolyline *polyline = (MKPolyline *)polylineView.polyline;
404
+ if (polyline) {
405
+ [_overlayToPolylineMap removeObjectForKey:polyline];
406
+ [_mapView removeOverlay:polyline];
407
+ polylineView.polyline = nil;
383
408
  }
384
-
385
- CLLocationCoordinate2D *coords = (CLLocationCoordinate2D *)malloc(
386
- sizeof(CLLocationCoordinate2D) * coordinates.count);
387
- for (NSUInteger i = 0; i < coordinates.count; i++) {
388
- coords[i] = coordinates[i].coordinate;
389
- }
390
-
391
- MKPolyline *polyline = [MKPolyline polylineWithCoordinates:coords
392
- count:coordinates.count];
393
- free(coords);
394
-
395
- polylineView.polyline = polyline;
396
- [_overlayToPolylineMap setObject:polylineView forKey:polyline];
397
- [self insertOverlay:polyline withZIndex:polylineView.zIndex];
398
409
  }
399
410
 
400
411
  - (void)syncPolylineView:(LuggPolylineView *)polylineView {
401
- if (!_mapView) {
412
+ if (!_mapView)
402
413
  return;
403
- }
404
414
 
405
415
  MKPolylineAnimator *renderer = (MKPolylineAnimator *)polylineView.renderer;
406
416
  MKPolyline *oldPolyline = (MKPolyline *)polylineView.polyline;
407
417
 
408
- // Build new polyline from coordinates
409
418
  NSArray<CLLocation *> *coordinates = polylineView.coordinates;
410
419
  if (coordinates.count == 0) {
411
420
  if (renderer) {
@@ -432,7 +441,6 @@ using namespace luggmaps::events;
432
441
  polylineView.polyline = newPolyline;
433
442
  [_overlayToPolylineMap setObject:polylineView forKey:newPolyline];
434
443
 
435
- // If we have an existing renderer, update it in place
436
444
  if (renderer && oldPolyline) {
437
445
  [_overlayToPolylineMap removeObjectForKey:oldPolyline];
438
446
  [_mapView removeOverlay:oldPolyline];
@@ -447,7 +455,6 @@ using namespace luggmaps::events;
447
455
  return;
448
456
  }
449
457
 
450
- // Otherwise do full add
451
458
  if (oldPolyline) {
452
459
  [_overlayToPolylineMap removeObjectForKey:oldPolyline];
453
460
  [_mapView removeOverlay:oldPolyline];
@@ -455,6 +462,29 @@ using namespace luggmaps::events;
455
462
  [self insertOverlay:newPolyline withZIndex:polylineView.zIndex];
456
463
  }
457
464
 
465
+ - (void)addPolylineOverlayToMap:(LuggPolylineView *)polylineView {
466
+ if (!_mapView)
467
+ return;
468
+
469
+ NSArray<CLLocation *> *coordinates = polylineView.coordinates;
470
+ if (coordinates.count == 0)
471
+ return;
472
+
473
+ CLLocationCoordinate2D *coords = (CLLocationCoordinate2D *)malloc(
474
+ sizeof(CLLocationCoordinate2D) * coordinates.count);
475
+ for (NSUInteger i = 0; i < coordinates.count; i++) {
476
+ coords[i] = coordinates[i].coordinate;
477
+ }
478
+
479
+ MKPolyline *polyline = [MKPolyline polylineWithCoordinates:coords
480
+ count:coordinates.count];
481
+ free(coords);
482
+
483
+ polylineView.polyline = polyline;
484
+ [_overlayToPolylineMap setObject:polylineView forKey:polyline];
485
+ [self insertOverlay:polyline withZIndex:polylineView.zIndex];
486
+ }
487
+
458
488
  - (void)insertOverlay:(id<MKOverlay>)overlay withZIndex:(NSInteger)zIndex {
459
489
  if (zIndex == 0) {
460
490
  [_mapView addOverlay:overlay];
@@ -466,7 +496,7 @@ using namespace luggmaps::events;
466
496
 
467
497
  for (NSInteger i = 0; i < overlays.count; i++) {
468
498
  LuggPolylineView *existingPolylineView =
469
- [self findPolylineViewForOverlay:overlays[i]];
499
+ [_overlayToPolylineMap objectForKey:overlays[i]];
470
500
  if (existingPolylineView && existingPolylineView.zIndex > zIndex) {
471
501
  insertIndex = i;
472
502
  break;
@@ -476,172 +506,40 @@ using namespace luggmaps::events;
476
506
  [_mapView insertOverlay:overlay atIndex:insertIndex];
477
507
  }
478
508
 
479
- - (LuggPolylineView *)findPolylineViewForOverlay:(id<MKOverlay>)overlay {
480
- return [_overlayToPolylineMap objectForKey:overlay];
481
- }
509
+ #pragma mark - Lifecycle
482
510
 
483
- #pragma mark - MarkerViewDelegate
484
-
485
- - (void)markerViewDidLayout:(LuggMarkerView *)markerView {
486
- AppleMarkerAnnotation *annotation =
487
- (AppleMarkerAnnotation *)markerView.marker;
488
- if (annotation) {
489
- [self updateAnnotationViewFrame:annotation];
511
+ - (void)pauseAnimations {
512
+ for (LuggPolylineView *polylineView in _overlayToPolylineMap
513
+ .objectEnumerator) {
514
+ MKPolylineAnimator *renderer = (MKPolylineAnimator *)polylineView.renderer;
515
+ [renderer pause];
490
516
  }
491
517
  }
492
518
 
493
- - (void)markerViewDidUpdate:(LuggMarkerView *)markerView {
494
- AppleMarkerAnnotation *annotation =
495
- (AppleMarkerAnnotation *)markerView.marker;
496
-
497
- if (!annotation) {
498
- RCTLogWarn(@"markerViewDidUpdate called without annotation");
499
- return;
500
- }
501
-
502
- annotation.coordinate = markerView.coordinate;
503
- annotation.title = markerView.title;
504
- annotation.subtitle = markerView.markerDescription;
505
-
506
- MKAnnotationView *annotationView = annotation.annotationView;
507
- if (annotationView) {
508
- annotationView.layer.zPosition = markerView.zIndex;
509
- annotationView.zPriority = markerView.zIndex;
510
- }
511
-
512
- [self updateAnnotationViewFrame:annotation];
513
- }
514
-
515
- #pragma mark - MKMapViewDelegate
516
-
517
- - (void)mapView:(MKMapView *)mapView regionWillChangeAnimated:(BOOL)animated {
518
- _isDragging = [self isUserInteracting:mapView];
519
- if (_isDragging) {
520
- for (UIView *subview in self.subviews) {
521
- if ([subview isKindOfClass:[LuggPolylineView class]]) {
522
- MKPolylineAnimator *renderer =
523
- (MKPolylineAnimator *)((LuggPolylineView *)subview).renderer;
524
- [renderer pause];
525
- }
526
- }
519
+ - (void)resumeAnimations {
520
+ for (LuggPolylineView *polylineView in _overlayToPolylineMap
521
+ .objectEnumerator) {
522
+ MKPolylineAnimator *renderer = (MKPolylineAnimator *)polylineView.renderer;
523
+ [renderer resume];
527
524
  }
528
525
  }
529
526
 
530
- - (BOOL)isUserInteracting:(MKMapView *)mapView {
531
- UIView *mapContainerView = mapView.subviews.firstObject;
532
- for (UIGestureRecognizer *gesture in mapContainerView.gestureRecognizers) {
533
- if (gesture.state == UIGestureRecognizerStateBegan ||
534
- gesture.state == UIGestureRecognizerStateChanged) {
535
- return YES;
536
- }
537
- }
538
- return NO;
539
- }
540
-
541
- - (void)mapViewDidChangeVisibleRegion:(MKMapView *)mapView {
542
- CameraMoveEvent{mapView.centerCoordinate.latitude,
543
- mapView.centerCoordinate.longitude, mapView.zoomLevel,
544
- _isDragging}
545
- .emit<LuggAppleMapViewEventEmitter>(_eventEmitter);
546
- }
547
-
548
- - (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated {
549
- BOOL wasDragging = _isDragging;
550
- _isDragging = NO;
551
- if (wasDragging) {
552
- for (UIView *subview in self.subviews) {
553
- if ([subview isKindOfClass:[LuggPolylineView class]]) {
554
- MKPolylineAnimator *renderer =
555
- (MKPolylineAnimator *)((LuggPolylineView *)subview).renderer;
556
- [renderer resume];
557
- }
558
- }
559
- }
560
- CameraIdleEvent{mapView.centerCoordinate.latitude,
561
- mapView.centerCoordinate.longitude, mapView.zoomLevel,
562
- static_cast<bool>(wasDragging)}
563
- .emit<LuggAppleMapViewEventEmitter>(_eventEmitter);
564
- }
565
-
566
- - (MKAnnotationView *)mapView:(MKMapView *)mapView
567
- viewForAnnotation:(id<MKAnnotation>)annotation {
568
- if (![annotation isKindOfClass:[AppleMarkerAnnotation class]]) {
569
- return nil;
570
- }
571
-
572
- AppleMarkerAnnotation *markerAnnotation = (AppleMarkerAnnotation *)annotation;
573
- LuggMarkerView *markerView = markerAnnotation.markerView;
574
-
575
- if (!markerView || !markerView.hasCustomView) {
576
- return nil;
577
- }
578
-
579
- MKAnnotationView *annotationView =
580
- [[MKAnnotationView alloc] initWithAnnotation:annotation
581
- reuseIdentifier:nil];
582
- annotationView.canShowCallout = YES;
583
- annotationView.displayPriority = MKFeatureDisplayPriorityRequired;
584
- annotationView.layer.zPosition = markerView.zIndex;
585
- annotationView.zPriority = markerView.zIndex;
586
-
587
- if (!markerView.rasterize) {
588
- UIView *iconView = markerView.iconView;
589
- [iconView removeFromSuperview];
590
- [annotationView addSubview:iconView];
591
- }
592
-
593
- [self applyMarkerStyle:markerView annotationView:annotationView];
594
- markerAnnotation.annotationView = annotationView;
595
-
596
- return annotationView;
597
- }
598
-
599
- - (MKOverlayRenderer *)mapView:(MKMapView *)mapView
600
- rendererForOverlay:(id<MKOverlay>)overlay {
601
- if ([overlay isKindOfClass:[MKPolyline class]]) {
602
- LuggPolylineView *polylineView = [self findPolylineViewForOverlay:overlay];
603
- MKPolyline *polyline = (MKPolyline *)overlay;
604
-
605
- if (polylineView) {
606
- NSArray<UIColor *> *colors = polylineView.strokeColors;
607
-
608
- MKPolylineAnimator *renderer =
609
- [[MKPolylineAnimator alloc] initWithPolyline:polyline];
610
- renderer.lineWidth = polylineView.strokeWidth;
611
- renderer.strokeColor = colors.firstObject;
612
- if (colors.count > 1) {
613
- renderer.strokeColors = colors;
614
- }
615
- renderer.animatedOptions = polylineView.animatedOptions;
616
- renderer.animated = polylineView.animated;
617
- polylineView.renderer = renderer;
618
- return renderer;
619
- }
620
-
621
- MKPolylineRenderer *renderer =
622
- [[MKPolylineRenderer alloc] initWithPolyline:polyline];
623
- return renderer;
624
- }
625
- return nil;
626
- }
627
-
628
527
  #pragma mark - Commands
629
528
 
630
529
  - (void)moveCamera:(double)latitude
631
530
  longitude:(double)longitude
632
531
  zoom:(double)zoom
633
532
  duration:(double)duration {
634
- if (!_mapView) {
533
+ if (!_mapView)
635
534
  return;
636
- }
637
535
 
638
536
  double targetZoom = zoom > 0 ? zoom : _mapView.zoomLevel;
639
537
 
640
538
  if (duration < 0) {
641
- [self setCameraWithLatitude:latitude
642
- longitude:longitude
643
- zoom:targetZoom
644
- animated:YES];
539
+ [_mapView
540
+ setCenterCoordinate:CLLocationCoordinate2DMake(latitude, longitude)
541
+ zoomLevel:targetZoom
542
+ animated:YES];
645
543
  } else if (duration > 0) {
646
544
  CLLocationCoordinate2D center =
647
545
  CLLocationCoordinate2DMake(latitude, longitude);
@@ -652,10 +550,10 @@ using namespace luggmaps::events;
652
550
  [self->_mapView setRegion:region animated:NO];
653
551
  }];
654
552
  } else {
655
- [self setCameraWithLatitude:latitude
656
- longitude:longitude
657
- zoom:targetZoom
658
- animated:NO];
553
+ [_mapView
554
+ setCenterCoordinate:CLLocationCoordinate2DMake(latitude, longitude)
555
+ zoomLevel:targetZoom
556
+ animated:NO];
659
557
  }
660
558
  }
661
559
 
@@ -665,9 +563,8 @@ using namespace luggmaps::events;
665
563
  paddingBottom:(double)paddingBottom
666
564
  paddingRight:(double)paddingRight
667
565
  duration:(double)duration {
668
- if (!_mapView || coordinates.count == 0) {
566
+ if (!_mapView || coordinates.count == 0)
669
567
  return;
670
- }
671
568
 
672
569
  CLLocationCoordinate2D *coords = (CLLocationCoordinate2D *)malloc(
673
570
  sizeof(CLLocationCoordinate2D) * coordinates.count);
@@ -702,12 +599,4 @@ using namespace luggmaps::events;
702
599
  }
703
600
  }
704
601
 
705
- - (void)handleCommand:(const NSString *)commandName args:(const NSArray *)args {
706
- RCTLuggAppleMapViewHandleCommand(self, commandName, args);
707
- }
708
-
709
- Class<RCTComponentViewProtocol> LuggAppleMapViewCls(void) {
710
- return LuggAppleMapView.class;
711
- }
712
-
713
602
  @end