@lugg/maps 1.0.0-beta.8 → 1.0.0

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 (62) hide show
  1. package/README.md +15 -100
  2. package/android/src/main/java/com/luggmaps/LuggCalloutView.kt +5 -0
  3. package/android/src/main/java/com/luggmaps/LuggMapView.kt +41 -0
  4. package/android/src/main/java/com/luggmaps/LuggMapViewManager.kt +14 -0
  5. package/android/src/main/java/com/luggmaps/LuggMapWrapperView.kt +27 -2
  6. package/android/src/main/java/com/luggmaps/LuggMarkerView.kt +7 -2
  7. package/android/src/main/java/com/luggmaps/LuggPolylineView.kt +3 -23
  8. package/android/src/main/java/com/luggmaps/core/GoogleMapProvider.kt +307 -41
  9. package/android/src/main/java/com/luggmaps/core/MapProviderDelegate.kt +1 -0
  10. package/android/src/main/java/com/luggmaps/core/PolylineAnimator.kt +65 -11
  11. package/ios/LuggMapView.mm +170 -2
  12. package/ios/LuggMapWrapperView.h +5 -0
  13. package/ios/LuggMapWrapperView.mm +18 -0
  14. package/ios/LuggMarkerView.mm +2 -0
  15. package/ios/core/AppleMapProvider.h +8 -0
  16. package/ios/core/AppleMapProvider.mm +48 -31
  17. package/ios/core/AppleStaticMapProvider.h +14 -0
  18. package/ios/core/AppleStaticMapProvider.mm +159 -0
  19. package/ios/core/GMSPolylineAnimator.m +46 -18
  20. package/ios/core/GoogleMapProvider.h +10 -0
  21. package/ios/core/GoogleMapProvider.mm +56 -44
  22. package/ios/core/GoogleStaticMapProvider.h +21 -0
  23. package/ios/core/GoogleStaticMapProvider.mm +213 -0
  24. package/ios/core/MKPolylineAnimator.m +67 -43
  25. package/ios/core/MapProviderDelegate.h +7 -0
  26. package/ios/core/StaticMapProviderBase.h +75 -0
  27. package/ios/core/StaticMapProviderBase.mm +845 -0
  28. package/ios/events/CameraIdleEvent.h +4 -2
  29. package/ios/events/CameraMoveEvent.h +4 -2
  30. package/ios/events/CirclePressEvent.h +4 -2
  31. package/ios/events/GroundOverlayPressEvent.h +4 -2
  32. package/ios/events/LongPressEvent.h +4 -2
  33. package/ios/events/MarkerDragEvent.h +12 -6
  34. package/ios/events/MarkerPressEvent.h +4 -2
  35. package/ios/events/PolygonPressEvent.h +4 -2
  36. package/ios/events/PressEvent.h +4 -2
  37. package/ios/events/ReadyEvent.h +4 -2
  38. package/ios/events/TileOverlayPressEvent.h +4 -2
  39. package/ios/extensions/MKMapView+Zoom.h +20 -0
  40. package/ios/extensions/MKMapView+Zoom.m +28 -18
  41. package/ios/extensions/UIView+Snapshot.h +16 -0
  42. package/ios/extensions/UIView+Snapshot.m +27 -0
  43. package/lib/module/MapView.js +7 -0
  44. package/lib/module/MapView.js.map +1 -1
  45. package/lib/module/MapView.web.js +9 -4
  46. package/lib/module/MapView.web.js.map +1 -1
  47. package/lib/module/fabric/LuggMapViewNativeComponent.ts +7 -4
  48. package/lib/typescript/src/MapView.d.ts.map +1 -1
  49. package/lib/typescript/src/MapView.types.d.ts +24 -0
  50. package/lib/typescript/src/MapView.types.d.ts.map +1 -1
  51. package/lib/typescript/src/MapView.web.d.ts.map +1 -1
  52. package/lib/typescript/src/fabric/LuggMapViewNativeComponent.d.ts +7 -4
  53. package/lib/typescript/src/fabric/LuggMapViewNativeComponent.d.ts.map +1 -1
  54. package/package.json +19 -12
  55. package/src/MapView.tsx +7 -0
  56. package/src/MapView.types.ts +24 -0
  57. package/src/MapView.web.tsx +15 -9
  58. package/src/fabric/LuggMapViewNativeComponent.ts +7 -4
  59. package/plugin/build/withMapsAndroid.d.ts +0 -5
  60. package/plugin/build/withMapsAndroid.js +0 -15
  61. package/plugin/build/withMapsIOS.d.ts +0 -5
  62. package/plugin/build/withMapsIOS.js +0 -27
@@ -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;
@@ -17,6 +17,39 @@ using facebook::react::LuggMapViewTheme;
17
17
 
18
18
  static NSString *const kDemoMapId = @"DEMO_MAP_ID";
19
19
 
20
+ GMSMapID *LuggGMSMapIDFromString(NSString *_Nullable mapId) {
21
+ if (mapId.length == 0 || [mapId isEqualToString:kDemoMapId]) {
22
+ return [GMSMapID demoMapID];
23
+ }
24
+ return [GMSMapID mapIDWithIdentifier:mapId];
25
+ }
26
+
27
+ GMSMapViewType
28
+ LuggGMSMapTypeFromMapType(facebook::react::LuggMapViewMapType mapType) {
29
+ switch (mapType) {
30
+ case LuggMapViewMapType::Satellite:
31
+ return kGMSTypeSatellite;
32
+ case LuggMapViewMapType::Terrain:
33
+ return kGMSTypeTerrain;
34
+ case LuggMapViewMapType::Hybrid:
35
+ return kGMSTypeHybrid;
36
+ default:
37
+ return kGMSTypeNormal;
38
+ }
39
+ }
40
+
41
+ UIUserInterfaceStyle
42
+ LuggInterfaceStyleFromTheme(facebook::react::LuggMapViewTheme theme) {
43
+ switch (theme) {
44
+ case LuggMapViewTheme::Dark:
45
+ return UIUserInterfaceStyleDark;
46
+ case LuggMapViewTheme::Light:
47
+ return UIUserInterfaceStyleLight;
48
+ default:
49
+ return UIUserInterfaceStyleUnspecified;
50
+ }
51
+ }
52
+
20
53
  @interface GoogleMapProvider () <
21
54
  LuggMarkerViewDelegate, LuggCalloutViewDelegate, LuggPolylineViewDelegate,
22
55
  LuggPolygonViewDelegate, LuggCircleViewDelegate,
@@ -53,6 +86,7 @@ static NSString *const kDemoMapId = @"DEMO_MAP_ID";
53
86
  }
54
87
 
55
88
  @synthesize delegate = _delegate;
89
+ @synthesize staticMode = _staticMode;
56
90
 
57
91
  - (instancetype)init {
58
92
  if (self = [super init]) {
@@ -89,13 +123,6 @@ static NSString *const kDemoMapId = @"DEMO_MAP_ID";
89
123
  if (_mapView)
90
124
  return;
91
125
 
92
- GMSMapID *gmsMapId;
93
- if ([_mapId isEqualToString:kDemoMapId] || _mapId.length == 0) {
94
- gmsMapId = [GMSMapID demoMapID];
95
- } else {
96
- gmsMapId = [GMSMapID mapIDWithIdentifier:_mapId];
97
- }
98
-
99
126
  GMSCameraPosition *camera =
100
127
  [GMSCameraPosition cameraWithLatitude:coordinate.latitude
101
128
  longitude:coordinate.longitude
@@ -104,7 +131,7 @@ static NSString *const kDemoMapId = @"DEMO_MAP_ID";
104
131
  GMSMapViewOptions *options = [[GMSMapViewOptions alloc] init];
105
132
  options.frame = wrapperView.bounds;
106
133
  options.camera = camera;
107
- options.mapID = gmsMapId;
134
+ options.mapID = LuggGMSMapIDFromString(_mapId);
108
135
 
109
136
  _mapView = [[GMSMapView alloc] initWithOptions:options];
110
137
  _mapView.autoresizingMask =
@@ -142,10 +169,18 @@ static NSString *const kDemoMapId = @"DEMO_MAP_ID";
142
169
  [_circleToViewMap removeAllObjects];
143
170
  [_markerToViewMap removeAllObjects];
144
171
  [_groundOverlayToViewMap removeAllObjects];
145
- [_mapView clear];
172
+ [self destroyMapView];
173
+ _isMapReady = NO;
174
+ }
175
+
176
+ - (void)destroyMapView {
177
+ if (!_mapView)
178
+ return;
179
+
180
+ _mapView.delegate = nil;
146
181
  [_mapView removeFromSuperview];
182
+ [_mapView clear];
147
183
  _mapView = nil;
148
- _isMapReady = NO;
149
184
  }
150
185
 
151
186
  #pragma mark - Props
@@ -166,6 +201,10 @@ static NSString *const kDemoMapId = @"DEMO_MAP_ID";
166
201
  _mapView.settings.tiltGestures = enabled;
167
202
  }
168
203
 
204
+ - (void)setCompassEnabled:(BOOL)enabled {
205
+ _mapView.settings.compassButton = enabled;
206
+ }
207
+
169
208
  - (void)setUserLocationEnabled:(BOOL)enabled {
170
209
  _mapView.myLocationEnabled = enabled;
171
210
  }
@@ -187,23 +226,7 @@ static NSString *const kDemoMapId = @"DEMO_MAP_ID";
187
226
  }
188
227
 
189
228
  - (void)setMapType:(LuggMapViewMapType)mapType {
190
- if (!_mapView)
191
- return;
192
-
193
- switch (mapType) {
194
- case LuggMapViewMapType::Satellite:
195
- _mapView.mapType = kGMSTypeSatellite;
196
- break;
197
- case LuggMapViewMapType::Terrain:
198
- _mapView.mapType = kGMSTypeTerrain;
199
- break;
200
- case LuggMapViewMapType::Hybrid:
201
- _mapView.mapType = kGMSTypeHybrid;
202
- break;
203
- default:
204
- _mapView.mapType = kGMSTypeNormal;
205
- break;
206
- }
229
+ _mapView.mapType = LuggGMSMapTypeFromMapType(mapType);
207
230
  }
208
231
 
209
232
  - (void)setTheme:(LuggMapViewTheme)theme {
@@ -212,20 +235,7 @@ static NSString *const kDemoMapId = @"DEMO_MAP_ID";
212
235
  }
213
236
 
214
237
  - (void)applyTheme {
215
- if (!_mapView)
216
- return;
217
-
218
- switch (_theme) {
219
- case LuggMapViewTheme::Dark:
220
- _mapView.overrideUserInterfaceStyle = UIUserInterfaceStyleDark;
221
- break;
222
- case LuggMapViewTheme::Light:
223
- _mapView.overrideUserInterfaceStyle = UIUserInterfaceStyleLight;
224
- break;
225
- default:
226
- _mapView.overrideUserInterfaceStyle = UIUserInterfaceStyleUnspecified;
227
- break;
228
- }
238
+ _mapView.overrideUserInterfaceStyle = LuggInterfaceStyleFromTheme(_theme);
229
239
  }
230
240
 
231
241
  - (void)setMinZoom:(double)minZoom {
@@ -1125,9 +1135,11 @@ static NSString *const kDemoMapId = @"DEMO_MAP_ID";
1125
1135
  return;
1126
1136
 
1127
1137
  float targetZoom = zoom > 0 ? (float)zoom : _mapView.camera.zoom;
1128
- GMSCameraPosition *camera = [GMSCameraPosition cameraWithLatitude:latitude
1129
- longitude:longitude
1130
- zoom:targetZoom];
1138
+ GMSCameraPosition *camera = [GMSCameraPosition
1139
+ cameraWithTarget:CLLocationCoordinate2DMake(latitude, longitude)
1140
+ zoom:targetZoom
1141
+ bearing:_mapView.camera.bearing
1142
+ viewingAngle:_mapView.camera.viewingAngle];
1131
1143
  if (duration < 0) {
1132
1144
  [_mapView animateToCameraPosition:camera];
1133
1145
  } else if (duration > 0) {
@@ -0,0 +1,21 @@
1
+ #import "StaticMapProviderBase.h"
2
+ #import <GoogleMaps/GoogleMaps.h>
3
+
4
+ NS_ASSUME_NONNULL_BEGIN
5
+
6
+ /**
7
+ * Static Google map. The Google Maps SDK has no async snapshotter, so the
8
+ * base map briefly warms up on a live, tiles-only GMSMapView inserted below
9
+ * the overlays, then is swapped with a rendered image and the map view is
10
+ * pooled for reuse. Markers and shapes are overlay views (shared with
11
+ * Apple static maps) that reveal with the base map, so the warmup map
12
+ * never renders its own markers. Warmup cost scales with how many static
13
+ * maps mount at once - bound that with list props (windowSize etc.).
14
+ */
15
+ @interface GoogleStaticMapProvider : StaticMapProviderBase <GMSMapViewDelegate>
16
+
17
+ @property(nonatomic, copy, nullable) NSString *mapId;
18
+
19
+ @end
20
+
21
+ NS_ASSUME_NONNULL_END