@lugg/maps 1.0.0-beta.2 → 1.0.0-beta.21

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 (206) hide show
  1. package/README.md +3 -0
  2. package/android/src/main/java/com/luggmaps/LuggCalloutView.kt +9 -2
  3. package/android/src/main/java/com/luggmaps/LuggCalloutViewManager.kt +4 -3
  4. package/android/src/main/java/com/luggmaps/LuggCircleView.kt +85 -0
  5. package/android/src/main/java/com/luggmaps/LuggCircleViewManager.kt +79 -0
  6. package/android/src/main/java/com/luggmaps/LuggGroundOverlayView.kt +81 -0
  7. package/android/src/main/java/com/luggmaps/LuggGroundOverlayViewManager.kt +82 -0
  8. package/android/src/main/java/com/luggmaps/LuggMapView.kt +90 -0
  9. package/android/src/main/java/com/luggmaps/LuggMapViewManager.kt +45 -0
  10. package/android/src/main/java/com/luggmaps/LuggMapWrapperView.kt +27 -2
  11. package/android/src/main/java/com/luggmaps/LuggMarkerView.kt +30 -2
  12. package/android/src/main/java/com/luggmaps/LuggMarkerViewManager.kt +13 -0
  13. package/android/src/main/java/com/luggmaps/LuggPackage.kt +4 -1
  14. package/android/src/main/java/com/luggmaps/LuggPolylineView.kt +3 -23
  15. package/android/src/main/java/com/luggmaps/LuggTileOverlayView.kt +92 -0
  16. package/android/src/main/java/com/luggmaps/LuggTileOverlayViewManager.kt +80 -0
  17. package/android/src/main/java/com/luggmaps/core/GoogleMapProvider.kt +737 -37
  18. package/android/src/main/java/com/luggmaps/core/MapProviderDelegate.kt +15 -0
  19. package/android/src/main/java/com/luggmaps/core/PolylineAnimator.kt +65 -11
  20. package/android/src/main/java/com/luggmaps/events/CirclePressEvent.kt +12 -0
  21. package/android/src/main/java/com/luggmaps/events/GroundOverlayPressEvent.kt +12 -0
  22. package/android/src/main/java/com/luggmaps/events/TileOverlayPressEvent.kt +12 -0
  23. package/android/src/main/java/com/luggmaps/extensions/ViewExtensions.kt +11 -0
  24. package/ios/LuggCalloutView.h +1 -1
  25. package/ios/LuggCalloutView.mm +21 -11
  26. package/ios/LuggCircleView.h +31 -0
  27. package/ios/LuggCircleView.mm +133 -0
  28. package/ios/LuggGroundOverlayView.h +30 -0
  29. package/ios/LuggGroundOverlayView.mm +125 -0
  30. package/ios/LuggMapView.mm +254 -4
  31. package/ios/LuggMapWrapperView.h +5 -0
  32. package/ios/LuggMapWrapperView.mm +18 -0
  33. package/ios/LuggMarkerView.h +3 -0
  34. package/ios/LuggMarkerView.mm +25 -0
  35. package/ios/LuggTileOverlayView.h +31 -0
  36. package/ios/LuggTileOverlayView.mm +130 -0
  37. package/ios/core/AppleMapProvider.h +8 -0
  38. package/ios/core/AppleMapProvider.mm +663 -29
  39. package/ios/core/AppleStaticMapProvider.h +14 -0
  40. package/ios/core/AppleStaticMapProvider.mm +159 -0
  41. package/ios/core/GMSPolylineAnimator.m +46 -18
  42. package/ios/core/GoogleMapProvider.h +10 -0
  43. package/ios/core/GoogleMapProvider.mm +430 -51
  44. package/ios/core/GoogleStaticMapProvider.h +21 -0
  45. package/ios/core/GoogleStaticMapProvider.mm +213 -0
  46. package/ios/core/MKPolylineAnimator.m +67 -43
  47. package/ios/core/MapProviderDelegate.h +27 -1
  48. package/ios/core/StaticMapProviderBase.h +75 -0
  49. package/ios/core/StaticMapProviderBase.mm +845 -0
  50. package/ios/events/CameraIdleEvent.h +4 -2
  51. package/ios/events/CameraMoveEvent.h +4 -2
  52. package/ios/events/CirclePressEvent.h +22 -0
  53. package/ios/events/GroundOverlayPressEvent.h +22 -0
  54. package/ios/events/LongPressEvent.h +4 -2
  55. package/ios/events/MarkerDragEvent.h +12 -6
  56. package/ios/events/MarkerPressEvent.h +4 -2
  57. package/ios/events/PolygonPressEvent.h +4 -2
  58. package/ios/events/PressEvent.h +4 -2
  59. package/ios/events/ReadyEvent.h +4 -2
  60. package/ios/events/TileOverlayPressEvent.h +22 -0
  61. package/ios/extensions/MKMapView+Zoom.h +20 -0
  62. package/ios/extensions/MKMapView+Zoom.m +28 -18
  63. package/ios/extensions/UIView+Snapshot.h +16 -0
  64. package/ios/extensions/UIView+Snapshot.m +27 -0
  65. package/lib/module/MapProvider.web.js +4 -1
  66. package/lib/module/MapProvider.web.js.map +1 -1
  67. package/lib/module/MapView.js +19 -1
  68. package/lib/module/MapView.js.map +1 -1
  69. package/lib/module/MapView.web.js +30 -22
  70. package/lib/module/MapView.web.js.map +1 -1
  71. package/lib/module/components/Circle.js +46 -0
  72. package/lib/module/components/Circle.js.map +1 -0
  73. package/lib/module/components/Circle.types.js +4 -0
  74. package/lib/module/components/Circle.types.js.map +1 -0
  75. package/lib/module/components/Circle.web.js +79 -0
  76. package/lib/module/components/Circle.web.js.map +1 -0
  77. package/lib/module/components/GeoJson.js +3 -3
  78. package/lib/module/components/GeoJson.js.map +1 -1
  79. package/lib/module/components/GroundOverlay.js +45 -0
  80. package/lib/module/components/GroundOverlay.js.map +1 -0
  81. package/lib/module/components/GroundOverlay.types.js +4 -0
  82. package/lib/module/components/GroundOverlay.types.js.map +1 -0
  83. package/lib/module/components/GroundOverlay.web.js +77 -0
  84. package/lib/module/components/GroundOverlay.web.js.map +1 -0
  85. package/lib/module/components/Marker.js +22 -4
  86. package/lib/module/components/Marker.js.map +1 -1
  87. package/lib/module/components/Marker.web.js +23 -10
  88. package/lib/module/components/Marker.web.js.map +1 -1
  89. package/lib/module/components/Polygon.web.js +3 -3
  90. package/lib/module/components/Polygon.web.js.map +1 -1
  91. package/lib/module/components/Polyline.web.js +6 -12
  92. package/lib/module/components/Polyline.web.js.map +1 -1
  93. package/lib/module/components/TileOverlay.js +44 -0
  94. package/lib/module/components/TileOverlay.js.map +1 -0
  95. package/lib/module/components/TileOverlay.types.js +4 -0
  96. package/lib/module/components/TileOverlay.types.js.map +1 -0
  97. package/lib/module/components/TileOverlay.web.js +69 -0
  98. package/lib/module/components/TileOverlay.web.js.map +1 -0
  99. package/lib/module/components/index.js +3 -0
  100. package/lib/module/components/index.js.map +1 -1
  101. package/lib/module/components/index.web.js +3 -0
  102. package/lib/module/components/index.web.js.map +1 -1
  103. package/lib/module/fabric/LuggCalloutViewNativeComponent.ts +1 -1
  104. package/lib/module/fabric/LuggCircleViewNativeComponent.ts +25 -0
  105. package/lib/module/fabric/LuggGroundOverlayViewNativeComponent.ts +29 -0
  106. package/lib/module/fabric/LuggMapViewNativeComponent.ts +16 -5
  107. package/lib/module/fabric/LuggMarkerViewNativeComponent.ts +14 -2
  108. package/lib/module/fabric/LuggTileOverlayViewNativeComponent.ts +30 -0
  109. package/lib/module/index.js +3 -0
  110. package/lib/module/index.js.map +1 -1
  111. package/lib/module/index.web.js +3 -0
  112. package/lib/module/index.web.js.map +1 -1
  113. package/lib/typescript/src/MapProvider.web.d.ts +3 -2
  114. package/lib/typescript/src/MapProvider.web.d.ts.map +1 -1
  115. package/lib/typescript/src/MapView.d.ts +1 -1
  116. package/lib/typescript/src/MapView.d.ts.map +1 -1
  117. package/lib/typescript/src/MapView.types.d.ts +60 -1
  118. package/lib/typescript/src/MapView.types.d.ts.map +1 -1
  119. package/lib/typescript/src/MapView.web.d.ts +1 -1
  120. package/lib/typescript/src/MapView.web.d.ts.map +1 -1
  121. package/lib/typescript/src/components/Circle.d.ts +10 -0
  122. package/lib/typescript/src/components/Circle.d.ts.map +1 -0
  123. package/lib/typescript/src/components/Circle.types.d.ts +33 -0
  124. package/lib/typescript/src/components/Circle.types.d.ts.map +1 -0
  125. package/lib/typescript/src/components/Circle.web.d.ts +3 -0
  126. package/lib/typescript/src/components/Circle.web.d.ts.map +1 -0
  127. package/lib/typescript/src/components/GeoJson.d.ts +2 -1
  128. package/lib/typescript/src/components/GeoJson.d.ts.map +1 -1
  129. package/lib/typescript/src/components/GroundOverlay.d.ts +10 -0
  130. package/lib/typescript/src/components/GroundOverlay.d.ts.map +1 -0
  131. package/lib/typescript/src/components/GroundOverlay.types.d.ts +35 -0
  132. package/lib/typescript/src/components/GroundOverlay.types.d.ts.map +1 -0
  133. package/lib/typescript/src/components/GroundOverlay.web.d.ts +3 -0
  134. package/lib/typescript/src/components/GroundOverlay.web.d.ts.map +1 -0
  135. package/lib/typescript/src/components/Marker.d.ts +6 -3
  136. package/lib/typescript/src/components/Marker.d.ts.map +1 -1
  137. package/lib/typescript/src/components/Marker.types.d.ts +18 -6
  138. package/lib/typescript/src/components/Marker.types.d.ts.map +1 -1
  139. package/lib/typescript/src/components/Marker.web.d.ts +3 -2
  140. package/lib/typescript/src/components/Marker.web.d.ts.map +1 -1
  141. package/lib/typescript/src/components/Polygon.web.d.ts +1 -1
  142. package/lib/typescript/src/components/Polygon.web.d.ts.map +1 -1
  143. package/lib/typescript/src/components/Polyline.web.d.ts +1 -1
  144. package/lib/typescript/src/components/Polyline.web.d.ts.map +1 -1
  145. package/lib/typescript/src/components/TileOverlay.d.ts +10 -0
  146. package/lib/typescript/src/components/TileOverlay.d.ts.map +1 -0
  147. package/lib/typescript/src/components/TileOverlay.types.d.ts +36 -0
  148. package/lib/typescript/src/components/TileOverlay.types.d.ts.map +1 -0
  149. package/lib/typescript/src/components/TileOverlay.web.d.ts +3 -0
  150. package/lib/typescript/src/components/TileOverlay.web.d.ts.map +1 -0
  151. package/lib/typescript/src/components/index.d.ts +7 -1
  152. package/lib/typescript/src/components/index.d.ts.map +1 -1
  153. package/lib/typescript/src/components/index.web.d.ts +6 -0
  154. package/lib/typescript/src/components/index.web.d.ts.map +1 -1
  155. package/lib/typescript/src/fabric/LuggCalloutViewNativeComponent.d.ts +1 -1
  156. package/lib/typescript/src/fabric/LuggCircleViewNativeComponent.d.ts +18 -0
  157. package/lib/typescript/src/fabric/LuggCircleViewNativeComponent.d.ts.map +1 -0
  158. package/lib/typescript/src/fabric/LuggGroundOverlayViewNativeComponent.d.ts +21 -0
  159. package/lib/typescript/src/fabric/LuggGroundOverlayViewNativeComponent.d.ts.map +1 -0
  160. package/lib/typescript/src/fabric/LuggMapViewNativeComponent.d.ts +13 -5
  161. package/lib/typescript/src/fabric/LuggMapViewNativeComponent.d.ts.map +1 -1
  162. package/lib/typescript/src/fabric/LuggMarkerViewNativeComponent.d.ts +8 -1
  163. package/lib/typescript/src/fabric/LuggMarkerViewNativeComponent.d.ts.map +1 -1
  164. package/lib/typescript/src/fabric/LuggTileOverlayViewNativeComponent.d.ts +21 -0
  165. package/lib/typescript/src/fabric/LuggTileOverlayViewNativeComponent.d.ts.map +1 -0
  166. package/lib/typescript/src/index.d.ts +9 -3
  167. package/lib/typescript/src/index.d.ts.map +1 -1
  168. package/lib/typescript/src/index.web.d.ts +7 -1
  169. package/lib/typescript/src/index.web.d.ts.map +1 -1
  170. package/lib/typescript/src/types.d.ts +0 -4
  171. package/lib/typescript/src/types.d.ts.map +1 -1
  172. package/package.json +17 -11
  173. package/src/MapProvider.web.tsx +5 -3
  174. package/src/MapView.tsx +19 -1
  175. package/src/MapView.types.ts +142 -1
  176. package/src/MapView.web.tsx +379 -340
  177. package/src/components/Circle.tsx +52 -0
  178. package/src/components/Circle.types.ts +33 -0
  179. package/src/components/Circle.web.tsx +95 -0
  180. package/src/components/GeoJson.tsx +3 -3
  181. package/src/components/GroundOverlay.tsx +47 -0
  182. package/src/components/GroundOverlay.types.ts +36 -0
  183. package/src/components/GroundOverlay.web.tsx +81 -0
  184. package/src/components/Marker.tsx +32 -6
  185. package/src/components/Marker.types.ts +19 -6
  186. package/src/components/Marker.web.tsx +196 -150
  187. package/src/components/Polygon.web.tsx +93 -89
  188. package/src/components/Polyline.web.tsx +235 -235
  189. package/src/components/TileOverlay.tsx +44 -0
  190. package/src/components/TileOverlay.types.ts +37 -0
  191. package/src/components/TileOverlay.web.tsx +97 -0
  192. package/src/components/index.ts +10 -0
  193. package/src/components/index.web.ts +9 -0
  194. package/src/fabric/LuggCalloutViewNativeComponent.ts +1 -1
  195. package/src/fabric/LuggCircleViewNativeComponent.ts +25 -0
  196. package/src/fabric/LuggGroundOverlayViewNativeComponent.ts +29 -0
  197. package/src/fabric/LuggMapViewNativeComponent.ts +16 -5
  198. package/src/fabric/LuggMarkerViewNativeComponent.ts +14 -2
  199. package/src/fabric/LuggTileOverlayViewNativeComponent.ts +30 -0
  200. package/src/index.ts +12 -1
  201. package/src/index.web.ts +15 -0
  202. package/src/types.ts +0 -5
  203. package/plugin/build/withMapsAndroid.d.ts +0 -5
  204. package/plugin/build/withMapsAndroid.js +0 -15
  205. package/plugin/build/withMapsIOS.d.ts +0 -5
  206. package/plugin/build/withMapsIOS.js +0 -27
@@ -0,0 +1,14 @@
1
+ #import "StaticMapProviderBase.h"
2
+
3
+ NS_ASSUME_NONNULL_BEGIN
4
+
5
+ /**
6
+ * Static Apple map rendered with MKMapSnapshotter. The base map renders
7
+ * fully asynchronously (no live MKMapView is ever created), so static maps
8
+ * keep loading while the user scrolls without blocking the main thread.
9
+ */
10
+ @interface AppleStaticMapProvider : StaticMapProviderBase
11
+
12
+ @end
13
+
14
+ NS_ASSUME_NONNULL_END
@@ -0,0 +1,159 @@
1
+ #import "AppleStaticMapProvider.h"
2
+
3
+ using facebook::react::LuggMapViewPoiFilterMode;
4
+ using facebook::react::LuggMapViewTheme;
5
+
6
+ #import "../extensions/MKMapView+Zoom.h"
7
+ #import "AppleMapProvider.h"
8
+ #import "LuggAnnotationView.h"
9
+
10
+ // Standard MKMarkerAnnotationView balloon size; standalone (off-map) views
11
+ // don't size themselves
12
+ static const CGSize kDefaultMarkerSize = {28, 33};
13
+
14
+ // The rect the snapshot renders: the region for the requested zoom, expanded
15
+ // on the short axis to the view's aspect ratio - the same fit MKMapView
16
+ // applies in setRegion, so static and live maps frame alike. Passing this
17
+ // exact rect to MKMapSnapshotter makes the projection exact.
18
+ static MKMapRect LuggStaticFittedMapRect(CLLocationCoordinate2D center,
19
+ double zoom, CGSize size) {
20
+ MKCoordinateSpan span = LuggCoordinateSpanForZoomLevel(MIN(zoom, 28), center);
21
+ MKMapPoint topLeft = MKMapPointForCoordinate(CLLocationCoordinate2DMake(
22
+ MIN(center.latitude + span.latitudeDelta / 2, 90.0),
23
+ center.longitude - span.longitudeDelta / 2));
24
+ MKMapPoint bottomRight = MKMapPointForCoordinate(CLLocationCoordinate2DMake(
25
+ MAX(center.latitude - span.latitudeDelta / 2, -90.0),
26
+ center.longitude + span.longitudeDelta / 2));
27
+ MKMapRect rect =
28
+ MKMapRectMake(topLeft.x, topLeft.y, bottomRight.x - topLeft.x,
29
+ bottomRight.y - topLeft.y);
30
+
31
+ double viewAspect = size.width / size.height;
32
+ double rectAspect = rect.size.width / rect.size.height;
33
+ if (rectAspect > viewAspect) {
34
+ double height = rect.size.width / viewAspect;
35
+ rect.origin.y -= (height - rect.size.height) / 2;
36
+ rect.size.height = height;
37
+ } else {
38
+ double width = rect.size.height * viewAspect;
39
+ rect.origin.x -= (width - rect.size.width) / 2;
40
+ rect.size.width = width;
41
+ }
42
+ return rect;
43
+ }
44
+
45
+ @implementation AppleStaticMapProvider {
46
+ MKMapSnapshotter *_snapshotter;
47
+
48
+ BOOL _poiEnabled;
49
+ LuggMapViewPoiFilterMode _poiFilterMode;
50
+ NSArray<NSString *> *_poiFilterCategories;
51
+ }
52
+
53
+ - (instancetype)init {
54
+ if (self = [super init]) {
55
+ _poiEnabled = YES;
56
+ _poiFilterMode = LuggMapViewPoiFilterMode::Including;
57
+ _poiFilterCategories = @[];
58
+ }
59
+ return self;
60
+ }
61
+
62
+ #pragma mark - StaticMapProviderBase
63
+
64
+ - (MKMapRect)mapRectForSize:(CGSize)size {
65
+ return LuggStaticFittedMapRect(self.coordinate, self.zoom, size);
66
+ }
67
+
68
+ - (UIView *)newDefaultMarkerOverlayView {
69
+ MKAnnotationView *pin =
70
+ [[LuggMarkerAnnotationView alloc] initWithAnnotation:nil
71
+ reuseIdentifier:nil];
72
+ pin.bounds =
73
+ CGRectMake(0, 0, kDefaultMarkerSize.width, kDefaultMarkerSize.height);
74
+ return pin;
75
+ }
76
+
77
+ // Inverse of LuggStaticFittedMapRect: the pre-fit rect is square in map
78
+ // points with side latitudeDelta * worldHeight / (360 * cos(lat)), and the
79
+ // aspect fit scales it to the view's short side
80
+ - (double)zoomForMapPointsPerPoint:(double)mapPointsPerPoint {
81
+ CGSize size = self.projectedSize;
82
+ double side = mapPointsPerPoint * MIN(size.width, size.height);
83
+ double latitudeDelta = side * 360.0 *
84
+ cos(self.coordinate.latitude * M_PI / 180.0) /
85
+ MKMapSizeWorld.height;
86
+ double zoom = 0.5 + log2(360.0 / latitudeDelta);
87
+ return MAX(MIN(zoom, 28.0), 0.0);
88
+ }
89
+
90
+ - (UITraitCollection *)snapshotTraitCollection {
91
+ UITraitCollection *base = self.wrapperView.traitCollection;
92
+ UIUserInterfaceStyle style;
93
+ switch (self.theme) {
94
+ case LuggMapViewTheme::Dark:
95
+ style = UIUserInterfaceStyleDark;
96
+ break;
97
+ case LuggMapViewTheme::Light:
98
+ style = UIUserInterfaceStyleLight;
99
+ break;
100
+ default:
101
+ return base;
102
+ }
103
+ return [UITraitCollection traitCollectionWithTraitsFromCollections:@[
104
+ base, [UITraitCollection traitCollectionWithUserInterfaceStyle:style]
105
+ ]];
106
+ }
107
+
108
+ - (void)renderBaseMap {
109
+ if (_snapshotter)
110
+ return;
111
+
112
+ MKMapSnapshotOptions *options = [[MKMapSnapshotOptions alloc] init];
113
+ options.mapRect = self.mapRect;
114
+ options.size = self.projectedSize;
115
+ options.mapType = LuggMKMapTypeFromMapType(self.mapType);
116
+ options.pointOfInterestFilter = LuggPointOfInterestFilter(
117
+ _poiEnabled, _poiFilterMode, _poiFilterCategories);
118
+ options.traitCollection = [self snapshotTraitCollection];
119
+
120
+ MKMapSnapshotter *snapshotter =
121
+ [[MKMapSnapshotter alloc] initWithOptions:options];
122
+ _snapshotter = snapshotter;
123
+
124
+ __weak AppleStaticMapProvider *weakSelf = self;
125
+ [snapshotter startWithQueue:dispatch_get_main_queue()
126
+ completionHandler:^(MKMapSnapshot *snapshot, NSError *error) {
127
+ AppleStaticMapProvider *strongSelf = weakSelf;
128
+ if (!strongSelf || strongSelf->_snapshotter != snapshotter)
129
+ return;
130
+ strongSelf->_snapshotter = nil;
131
+ if (error || !snapshot) {
132
+ // Keep the placeholder; resumeAnimations retries (e.g. back
133
+ // online)
134
+ return;
135
+ }
136
+ [strongSelf displayBaseImage:snapshot.image fromCache:NO];
137
+ }];
138
+ }
139
+
140
+ - (void)cancelBaseRender {
141
+ [_snapshotter cancel];
142
+ _snapshotter = nil;
143
+ }
144
+
145
+ #pragma mark - Props
146
+
147
+ - (void)setPoiEnabled:(BOOL)enabled {
148
+ _poiEnabled = enabled;
149
+ }
150
+
151
+ - (void)setPoiFilterMode:(LuggMapViewPoiFilterMode)mode {
152
+ _poiFilterMode = mode;
153
+ }
154
+
155
+ - (void)setPoiFilterCategories:(NSArray<NSString *> *)categories {
156
+ _poiFilterCategories = categories;
157
+ }
158
+
159
+ @end
@@ -2,6 +2,7 @@
2
2
  #import <QuartzCore/QuartzCore.h>
3
3
 
4
4
  static const NSUInteger kMaxAnimationSpans = 16;
5
+ static const NSUInteger kMaxGradientSpans = 512;
5
6
 
6
7
  @interface GMSDisplayLinkProxy : NSObject
7
8
  @property(nonatomic, weak) id target;
@@ -147,13 +148,25 @@ static const NSUInteger kMaxAnimationSpans = 16;
147
148
  }
148
149
 
149
150
  GMSMutablePath *path = [GMSMutablePath path];
150
- for (CLLocation *location in self.coordinates) {
151
- [path addCoordinate:location.coordinate];
151
+ CLLocationCoordinate2D lastCoord = self.coordinates.firstObject.coordinate;
152
+ [path addCoordinate:lastCoord];
153
+ for (NSUInteger i = 1; i < self.coordinates.count; i++) {
154
+ CLLocationCoordinate2D coord = self.coordinates[i].coordinate;
155
+ if (coord.latitude == lastCoord.latitude && coord.longitude == lastCoord.longitude) {
156
+ continue;
157
+ }
158
+ [path addCoordinate:coord];
159
+ lastCoord = coord;
152
160
  }
161
+
162
+ // Clear stale spans before swapping the path so Google Maps never rebuilds
163
+ // span models against a path with fewer segments (GMSModelStyleBuilder
164
+ // couldNotInstantiate -> EXC_BAD_ACCESS). Reassign spans once the new path is set.
165
+ _polyline.spans = nil;
153
166
  _polyline.path = path;
154
167
 
155
- if (self.strokeColors.count > 1) {
156
- _polyline.spans = [self createGradientSpans];
168
+ if (path.count > 1 && self.strokeColors.count > 1) {
169
+ _polyline.spans = [self createGradientSpansForSegmentCount:path.count - 1];
157
170
  } else {
158
171
  _polyline.strokeColor = self.strokeColors.firstObject ?: [UIColor blackColor];
159
172
  }
@@ -221,35 +234,44 @@ static const NSUInteger kMaxAnimationSpans = 16;
221
234
  }
222
235
 
223
236
  if (headDist <= tailDist) {
237
+ _polyline.spans = nil;
224
238
  _polyline.path = [GMSMutablePath path];
225
239
  return;
226
240
  }
227
241
 
228
- CGFloat visibleLength = headDist - tailDist;
229
242
  NSUInteger startIndex = [self indexForDistance:tailDist];
230
243
  NSUInteger endIndex = [self indexForDistance:headDist];
231
244
 
232
245
  GMSMutablePath *path = [GMSMutablePath path];
233
- NSMutableArray<GMSStyleSpan *> *spans = [NSMutableArray array];
234
246
 
235
- CLLocationCoordinate2D startCoord = [self coordinateAtDistance:tailDist];
236
- [path addCoordinate:startCoord];
247
+ CLLocationCoordinate2D lastCoord = [self coordinateAtDistance:tailDist];
248
+ [path addCoordinate:lastCoord];
237
249
 
238
250
  for (NSUInteger i = startIndex + 1; i <= endIndex; i++) {
239
- [path addCoordinate:self.coordinates[i].coordinate];
251
+ CLLocationCoordinate2D coord = self.coordinates[i].coordinate;
252
+ if (coord.latitude == lastCoord.latitude && coord.longitude == lastCoord.longitude) {
253
+ continue;
254
+ }
255
+ [path addCoordinate:coord];
256
+ lastCoord = coord;
240
257
  }
241
258
 
242
259
  CLLocationCoordinate2D endCoord = [self coordinateAtDistance:headDist];
243
- CLLocationCoordinate2D lastAdded =
244
- (endIndex < self.coordinates.count) ? self.coordinates[endIndex].coordinate : endCoord;
245
- if (endCoord.latitude != lastAdded.latitude || endCoord.longitude != lastAdded.longitude) {
260
+ if (endCoord.latitude != lastCoord.latitude || endCoord.longitude != lastCoord.longitude) {
246
261
  [path addCoordinate:endCoord];
247
262
  }
248
263
 
249
264
  NSUInteger pathCount = path.count;
250
- NSUInteger segmentCount = pathCount - 1;
265
+ NSUInteger segmentCount = (pathCount > 1) ? pathCount - 1 : 0;
266
+
267
+ if (segmentCount == 0) {
268
+ _polyline.spans = nil;
269
+ _polyline.path = path;
270
+ return;
271
+ }
251
272
 
252
273
  if (self.strokeColors.count <= 1) {
274
+ _polyline.spans = nil;
253
275
  _polyline.path = path;
254
276
  _polyline.strokeColor = self.strokeColors.firstObject ?: [UIColor blackColor];
255
277
  return;
@@ -258,6 +280,7 @@ static const NSUInteger kMaxAnimationSpans = 16;
258
280
  NSUInteger spanCount = MIN(segmentCount, kMaxAnimationSpans);
259
281
  double segmentsPerSpan = (double)segmentCount / spanCount;
260
282
 
283
+ NSMutableArray<GMSStyleSpan *> *spans = [NSMutableArray array];
261
284
  for (NSUInteger i = 0; i < spanCount; i++) {
262
285
  CGFloat gradientPos = ((CGFloat)i + 0.5) / spanCount;
263
286
  UIColor *color = [self colorAtGradientPosition:gradientPos];
@@ -265,19 +288,24 @@ static const NSUInteger kMaxAnimationSpans = 16;
265
288
  [spans addObject:[GMSStyleSpan spanWithStyle:style segments:segmentsPerSpan]];
266
289
  }
267
290
 
291
+ // Clear stale spans before swapping the path so Google Maps never rebuilds
292
+ // span models against a path with fewer segments (GMSModelStyleBuilder
293
+ // couldNotInstantiate -> EXC_BAD_ACCESS). Reassign spans once the new path is set.
294
+ _polyline.spans = nil;
268
295
  _polyline.path = path;
269
296
  _polyline.spans = spans;
270
297
  }
271
298
 
272
- - (NSArray<GMSStyleSpan *> *)createGradientSpans {
299
+ - (NSArray<GMSStyleSpan *> *)createGradientSpansForSegmentCount:(NSUInteger)segmentCount {
273
300
  NSMutableArray<GMSStyleSpan *> *spans = [NSMutableArray array];
274
- NSUInteger segmentCount = self.coordinates.count - 1;
301
+ NSUInteger spanCount = MIN(segmentCount, kMaxGradientSpans);
302
+ double segmentsPerSpan = (double)segmentCount / spanCount;
275
303
 
276
- for (NSUInteger i = 0; i < segmentCount; i++) {
277
- CGFloat position = (CGFloat)i / (CGFloat)segmentCount;
304
+ for (NSUInteger i = 0; i < spanCount; i++) {
305
+ CGFloat position = ((CGFloat)i + 0.5) / spanCount;
278
306
  UIColor *color = [self colorAtGradientPosition:position];
279
307
  GMSStrokeStyle *style = [GMSStrokeStyle solidColor:color];
280
- [spans addObject:[GMSStyleSpan spanWithStyle:style]];
308
+ [spans addObject:[GMSStyleSpan spanWithStyle:style segments:segmentsPerSpan]];
281
309
  }
282
310
 
283
311
  return spans;
@@ -3,6 +3,16 @@
3
3
 
4
4
  NS_ASSUME_NONNULL_BEGIN
5
5
 
6
+ /// Resolves a mapId prop value ("" or "DEMO_MAP_ID" -> demo map ID),
7
+ /// shared by the live and static Google providers.
8
+ GMSMapID *LuggGMSMapIDFromString(NSString *_Nullable mapId);
9
+
10
+ GMSMapViewType
11
+ LuggGMSMapTypeFromMapType(facebook::react::LuggMapViewMapType mapType);
12
+
13
+ UIUserInterfaceStyle
14
+ LuggInterfaceStyleFromTheme(facebook::react::LuggMapViewTheme theme);
15
+
6
16
  @interface GoogleMapProvider : NSObject <MapProvider, GMSMapViewDelegate>
7
17
 
8
18
  @property(nonatomic, copy, nullable) NSString *mapId;