@rnmapbox/maps 10.0.0-beta.54 → 10.0.0-beta.57

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 (33) hide show
  1. package/android/rctmgl/build.gradle +1 -0
  2. package/android/rctmgl/src/main/java-v10/com/mapbox/rctmgl/components/annotation/RCTMGLMarkerView.kt +5 -1
  3. package/android/rctmgl/src/main/java-v10/com/mapbox/rctmgl/components/annotation/RCTMGLMarkerViewManager.kt +28 -0
  4. package/android/rctmgl/src/main/java-v10/com/mapbox/rctmgl/components/mapview/RCTMGLMapView.kt +5 -0
  5. package/android/rctmgl/src/main/java-v10/com/mapbox/rctmgl/components/mapview/RCTMGLMapViewManager.kt +2 -1
  6. package/index.d.ts +1 -0
  7. package/ios/RCTMGL-v10/RCTMGLCamera.swift +2 -2
  8. package/ios/RCTMGL-v10/RCTMGLCircleLayer.swift +1 -20
  9. package/ios/RCTMGL-v10/RCTMGLImages.swift +1 -1
  10. package/ios/RCTMGL-v10/RCTMGLInteractiveElement.swift +4 -12
  11. package/ios/RCTMGL-v10/RCTMGLLayer.swift +2 -1
  12. package/ios/RCTMGL-v10/RCTMGLLocationModule.swift +19 -5
  13. package/ios/RCTMGL-v10/RCTMGLMapView.swift +71 -28
  14. package/ios/RCTMGL-v10/RCTMGLMapViewManager.m +3 -0
  15. package/ios/RCTMGL-v10/RCTMGLMapViewManager.swift +5 -5
  16. package/ios/RCTMGL-v10/RCTMGLMarkerView.swift +1 -1
  17. package/ios/RCTMGL-v10/RCTMGLPointAnnotation.swift +1 -1
  18. package/ios/RCTMGL-v10/RCTMGLSingletonLayer.swift +2 -2
  19. package/ios/RCTMGL-v10/RCTMGLSource.swift +23 -1
  20. package/ios/RCTMGL-v10/RCTMGLStyleValue.swift +1 -1
  21. package/ios/RCTMGL-v10/RCTMGLVectorLayer.swift +0 -44
  22. package/javascript/components/MapView.js +5 -0
  23. package/lib/commonjs/components/MapView.js +4 -0
  24. package/lib/commonjs/components/MapView.js.map +1 -1
  25. package/lib/commonjs/web/utils/Logger.js.map +1 -1
  26. package/lib/module/components/MapView.js +4 -0
  27. package/lib/module/components/MapView.js.map +1 -1
  28. package/lib/module/web/utils/Logger.js.map +1 -1
  29. package/package.json +3 -2
  30. package/plugin/build/withMapbox.d.ts +2 -0
  31. package/plugin/build/withMapbox.js +50 -21
  32. package/plugin/src/withMapbox.ts +69 -22
  33. package/setup-jest.js +125 -0
@@ -132,6 +132,7 @@ dependencies {
132
132
  else if (safeExtGet("RNMapboxMapsImpl", defaultMapboxMapsImpl) == "mapbox") {
133
133
  implementation 'com.mapbox.maps:android:10.9.0'
134
134
  implementation 'com.mapbox.mapboxsdk:mapbox-sdk-turf:6.8.0'
135
+ implementation 'androidx.asynclayoutinflater:asynclayoutinflater:1.0.0'
135
136
  }
136
137
  }
137
138
 
@@ -5,6 +5,7 @@ import android.os.Handler
5
5
  import android.os.Looper
6
6
  import android.util.Log
7
7
  import android.view.View
8
+ import android.view.ViewGroup
8
9
  import android.widget.FrameLayout
9
10
  import com.mapbox.geojson.Point
10
11
  import com.mapbox.maps.ViewAnnotationAnchor
@@ -142,7 +143,10 @@ class RCTMGLMarkerView(context: Context?, private val mManager: RCTMGLMarkerView
142
143
  this.removeOnLayoutChangeListener(this)
143
144
 
144
145
  mView?.let { view ->
145
- mapView.endViewTransition(view) // https://github.com/mapbox/mapbox-maps-android/issues/1723
146
+ val parent = view.parent
147
+ if (parent is ViewGroup) {
148
+ parent.endViewTransition(view) // https://github.com/mapbox/mapbox-maps-android/issues/1723
149
+ }
146
150
  val removed = mapView.viewAnnotationManager?.removeViewAnnotation(view)
147
151
  if (removed == false) {
148
152
  Logger.w("RCTMGLMarkerView", "Unable to remove view")
@@ -1,6 +1,7 @@
1
1
  package com.mapbox.rctmgl.components.annotation
2
2
 
3
3
  import android.view.View
4
+ import android.widget.FrameLayout
4
5
  import com.mapbox.rctmgl.utils.GeoJSONUtils.toPointGeometry
5
6
  import com.facebook.react.bridge.ReactApplicationContext
6
7
  import com.mapbox.rctmgl.components.AbstractEventEmitter
@@ -8,6 +9,10 @@ import com.facebook.react.uimanager.annotations.ReactProp
8
9
  import com.facebook.react.bridge.ReadableMap
9
10
  import com.facebook.react.common.MapBuilder
10
11
  import com.facebook.react.uimanager.ThemedReactContext
12
+ import com.mapbox.maps.ScreenCoordinate
13
+ import com.mapbox.maps.viewannotation.OnViewAnnotationUpdatedListener
14
+ import com.mapbox.maps.viewannotation.ViewAnnotationManager
15
+ import com.mapbox.rctmgl.components.mapview.RCTMGLMapView
11
16
 
12
17
  class RCTMGLMarkerViewManager(reactApplicationContext: ReactApplicationContext?) :
13
18
  AbstractEventEmitter<RCTMGLMarkerView?>(reactApplicationContext) {
@@ -46,5 +51,28 @@ class RCTMGLMarkerViewManager(reactApplicationContext: ReactApplicationContext?)
46
51
 
47
52
  companion object {
48
53
  const val REACT_CLASS = "RCTMGLMarkerView"
54
+
55
+ fun markerViewContainerSizeFixer(mapView: RCTMGLMapView, viewAnnotationManager: ViewAnnotationManager) {
56
+ // see https://github.com/rnmapbox/maps/issues/2376
57
+ viewAnnotationManager.addOnViewAnnotationUpdatedListener(object :
58
+ OnViewAnnotationUpdatedListener {
59
+ override fun onViewAnnotationVisibilityUpdated(view: View, visible: Boolean) {
60
+ val parent = view.parent
61
+ if (parent is FrameLayout) {
62
+ if ((parent.width == 0 && parent.height == 0) && (mapView.width != 0 || mapView.height != 0)) {
63
+ parent.layout(0,0,mapView.width, mapView.height)
64
+ }
65
+ }
66
+ }
67
+
68
+ override fun onViewAnnotationPositionUpdated(
69
+ view: View,
70
+ leftTopCoordinate: ScreenCoordinate,
71
+ width: Int,
72
+ height: Int
73
+ ) {
74
+ }
75
+ })
76
+ }
49
77
  }
50
78
  }
@@ -43,6 +43,7 @@ import com.mapbox.maps.plugin.scalebar.scalebar
43
43
  import com.mapbox.rctmgl.R
44
44
  import com.mapbox.rctmgl.components.AbstractMapFeature
45
45
  import com.mapbox.rctmgl.components.annotation.RCTMGLMarkerView
46
+ import com.mapbox.rctmgl.components.annotation.RCTMGLMarkerViewManager
46
47
  import com.mapbox.rctmgl.components.annotation.RCTMGLPointAnnotation
47
48
  import com.mapbox.rctmgl.components.camera.RCTMGLCamera
48
49
  import com.mapbox.rctmgl.components.images.RCTMGLImages
@@ -900,6 +901,8 @@ open class RCTMGLMapView(private val mContext: Context, var mManager: RCTMGLMapV
900
901
  images.sendImageMissingEvent(id, mMap)
901
902
  }
902
903
  })
904
+
905
+ RCTMGLMarkerViewManager.markerViewContainerSizeFixer(this, viewAnnotationManager)
903
906
  }
904
907
 
905
908
  // region Ornaments
@@ -1184,12 +1187,14 @@ open class RCTMGLMapView(private val mContext: Context, var mManager: RCTMGLMapV
1184
1187
 
1185
1188
  override fun onDestroy() {
1186
1189
  removeAllFeatures()
1190
+ viewAnnotationManager.removeAllViewAnnotations()
1187
1191
  lifecycleOwner?.handleLifecycleEvent(Lifecycle.Event.ON_DESTROY)
1188
1192
  super.onDestroy()
1189
1193
  }
1190
1194
 
1191
1195
  fun onDropViewInstance() {
1192
1196
  removeAllFeatures()
1197
+ viewAnnotationManager.removeAllViewAnnotations()
1193
1198
  lifecycleOwner?.handleLifecycleEvent(Lifecycle.Event.ON_DESTROY)
1194
1199
  }
1195
1200
 
@@ -269,11 +269,12 @@ open class RCTMGLMapViewManager(context: ReactApplicationContext?) :
269
269
  );
270
270
  }
271
271
  METHOD_QUERY_FEATURES_RECT -> {
272
+ val layerIds = ConvertUtils.toStringList(args!!.getArray(3))
272
273
  mapView.queryRenderedFeaturesInRect(
273
274
  args!!.getString(0),
274
275
  ConvertUtils.toRectF(args.getArray(1)),
275
276
  ExpressionParser.from(args!!.getArray(2)),
276
- ConvertUtils.toStringList(args!!.getArray(3))
277
+ if (layerIds.size == 0) null else layerIds
277
278
  );
278
279
  }
279
280
  METHOD_VISIBLE_BOUNDS -> {
package/index.d.ts CHANGED
@@ -568,6 +568,7 @@ export interface MapViewProps extends ViewProps {
568
568
  compassPosition?: OrnamentPosition;
569
569
  compassViewPosition?: number;
570
570
  compassViewMargins?: Point;
571
+ compassImage?: string;
571
572
  scaleBarEnabled?: boolean;
572
573
  scaleBarPosition?: OrnamentPosition;
573
574
  surfaceView?: boolean;
@@ -65,10 +65,10 @@ class CameraUpdateQueue {
65
65
  }
66
66
 
67
67
  open class RCTMGLMapComponentBase : UIView, RCTMGLMapComponent {
68
- private var _map: RCTMGLMapView! = nil
68
+ private weak var _map: RCTMGLMapView! = nil
69
69
  private var _mapCallbacks: [(RCTMGLMapView) -> Void] = []
70
70
 
71
- var map : RCTMGLMapView? {
71
+ weak var map : RCTMGLMapView? {
72
72
  return _map;
73
73
  }
74
74
 
@@ -6,7 +6,7 @@ class RCTMGLCircleLayer: RCTMGLVectorLayer {
6
6
  typealias LayerType = CircleLayer
7
7
 
8
8
  override func makeLayer(style: Style) throws -> Layer {
9
- let vectorSource : VectorSource = try self.layerWithSourceID(in: style)
9
+ let _ : VectorSource = try self.layerWithSourceID(in: style)
10
10
  var layer = LayerType(id: self.id!)
11
11
  layer.sourceLayer = self.sourceLayerID
12
12
  layer.source = sourceID
@@ -44,23 +44,4 @@ class RCTMGLCircleLayer: RCTMGLVectorLayer {
44
44
  func isAddedToMap() -> Bool {
45
45
  return true
46
46
  }
47
- /*
48
- - (MGLCircleStyleLayer*)makeLayer:(MGLStyle*)style
49
- {
50
- MGLSource *source = [self layerWithSourceIDInStyle:style];
51
- if (source == nil) { return nil; }
52
- MGLCircleStyleLayer *layer = [[MGLCircleStyleLayer alloc] initWithIdentifier:self.id source:source];
53
- layer.sourceLayerIdentifier = self.sourceLayerID;
54
- return layer;
55
- }
56
-
57
- - (void)addStyles
58
- {
59
- RCTMGLStyle *style = [[RCTMGLStyle alloc] initWithMGLStyle:self.style];
60
- style.bridge = self.bridge;
61
- [style circleLayer:(MGLCircleStyleLayer*)self.styleLayer withReactStyle:self.reactStyle isValid:^{
62
- return [self isAddedToMap];
63
- }];
64
- }*/
65
-
66
47
  }
@@ -2,7 +2,7 @@ import MapboxMaps
2
2
 
3
3
  class RCTMGLImages : UIView, RCTMGLMapComponent {
4
4
 
5
- var bridge : RCTBridge! = nil
5
+ weak var bridge : RCTBridge! = nil
6
6
  var remoteImages : [String:String] = [:]
7
7
 
8
8
  @objc
@@ -1,12 +1,10 @@
1
- @_spi(Experimental) import MapboxMaps
1
+ import MapboxMaps
2
2
 
3
3
  @objc
4
4
  class RCTMGLInteractiveElement : UIView, RCTMGLMapComponent {
5
5
 
6
- var map : RCTMGLMapView? = nil
7
-
8
- var layers: [RCTMGLSourceConsumer] = []
9
-
6
+ weak var map : RCTMGLMapView? = nil
7
+
10
8
  static let hitboxDefault = 44.0
11
9
 
12
10
  @objc var draggable: Bool = false
@@ -25,13 +23,7 @@ class RCTMGLInteractiveElement : UIView, RCTMGLMapComponent {
25
23
  @objc var onPress: RCTBubblingEventBlock? = nil
26
24
 
27
25
  func getLayerIDs() -> [String] {
28
- layers.compactMap {
29
- if let layer = $0 as? RCTMGLLayer {
30
- return layer.id
31
- } else {
32
- return nil
33
- }
34
- }
26
+ return []
35
27
  }
36
28
 
37
29
  func isDraggable() -> Bool {
@@ -7,11 +7,12 @@ protocol RCTMGLSourceConsumer {
7
7
 
8
8
  @objc(RCTMGLLayer)
9
9
  class RCTMGLLayer : UIView, RCTMGLMapComponent, RCTMGLSourceConsumer {
10
- var bridge : RCTBridge? = nil
10
+ weak var bridge : RCTBridge? = nil
11
11
 
12
12
  @objc var sourceLayerID : String? = nil {
13
13
  didSet { self.optionsChanged() }
14
14
  }
15
+
15
16
  @objc var reactStyle : Dictionary<String, Any>? = nil {
16
17
  didSet {
17
18
  DispatchQueue.main.async {
@@ -27,8 +27,16 @@ typealias RCTMGLLocationBlock = (RCTMGLLocation?) -> Void
27
27
 
28
28
  let RCT_MAPBOX_USER_LOCATION_UPDATE = "MapboxUserLocationUpdate";
29
29
 
30
+ /// This implementation of LocationProviderDelegate is used by `LocationManager` to work around
31
+ /// the fact that the `LocationProvider` API does not allow the delegate to be set to `nil`.
32
+ internal class EmptyLocationProviderDelegate: LocationProviderDelegate {
33
+ func locationProvider(_ provider: LocationProvider, didFailWithError error: Error) {}
34
+ func locationProvider(_ provider: LocationProvider, didUpdateHeading newHeading: CLHeading) {}
35
+ func locationProvider(_ provider: LocationProvider, didUpdateLocations locations: [CLLocation]) {}
36
+ func locationProviderDidChangeAuthorization(_ provider: LocationProvider) {}
37
+ }
30
38
 
31
- protocol RCTMGLLocationManagerDelegate {
39
+ protocol RCTMGLLocationManagerDelegate : AnyObject {
32
40
  func locationManager(_ locationManager: RCTMGLLocationManager, didUpdateLocation: RCTMGLLocation)
33
41
  }
34
42
 
@@ -38,8 +46,8 @@ class RCTMGLLocationManager : LocationProviderDelegate {
38
46
  var lastKnownLocation : CLLocation?
39
47
  var lastKnownHeading : CLHeading?
40
48
 
41
- var delegate: RCTMGLLocationManagerDelegate?
42
- var locationProviderDelage: LocationProviderDelegate?
49
+ weak var delegate: RCTMGLLocationManagerDelegate?
50
+ weak var locationProviderDelage: LocationProviderDelegate?
43
51
 
44
52
  var listeners: [RCTMGLLocationBlock] = []
45
53
 
@@ -60,6 +68,12 @@ class RCTMGLLocationManager : LocationProviderDelegate {
60
68
  provider.startUpdatingLocation()
61
69
  }
62
70
 
71
+ func stop() {
72
+ provider.stopUpdatingHeading()
73
+ provider.stopUpdatingLocation()
74
+ provider.setDelegate(EmptyLocationProviderDelegate())
75
+ }
76
+
63
77
  func _convertToMapboxLocation(_ location: CLLocation?) -> RCTMGLLocation {
64
78
  guard let location = location else {
65
79
  return RCTMGLLocation()
@@ -192,7 +206,7 @@ extension RCTMGLLocationManager: LocationProvider {
192
206
  @objc(RCTMGLLocationModule)
193
207
  class RCTMGLLocationModule: RCTEventEmitter, RCTMGLLocationManagerDelegate {
194
208
 
195
- static var shared : RCTMGLLocationModule? = nil
209
+ static weak var shared : RCTMGLLocationModule? = nil
196
210
 
197
211
  var locationManager : RCTMGLLocationManager
198
212
  var hasListener = false
@@ -233,7 +247,7 @@ class RCTMGLLocationModule: RCTEventEmitter, RCTMGLLocationManagerDelegate {
233
247
  }
234
248
 
235
249
  @objc func stop() {
236
- print("TODO implement RCTMGLLocationModule.stop!")
250
+ locationManager.stop()
237
251
  }
238
252
 
239
253
  @objc func getLastKnownLocation() -> RCTMGLLocation? {
@@ -8,21 +8,22 @@ open class RCTMGLMapView : MapView {
8
8
 
9
9
  var compassEnabled: Bool = false
10
10
  var compassFadeWhenNorth: Bool = false
11
+ var compassImage: String?
12
+
11
13
  var reactOnPress : RCTBubblingEventBlock?
12
14
  var reactOnLongPress : RCTBubblingEventBlock?
13
15
  var reactOnMapChange : RCTBubblingEventBlock?
14
16
 
15
17
  var styleLoaded: Bool = false
16
18
  var styleLoadWaiters : [(MapboxMap)->Void] = []
19
+ var onStyleLoadedComponents: [RCTMGLMapComponent] = []
17
20
 
18
- var reactCamera : RCTMGLCamera?
21
+ weak var reactCamera : RCTMGLCamera?
19
22
  var images : [RCTMGLImages] = []
20
23
  var sources : [RCTMGLInteractiveElement] = []
21
24
 
22
25
  var handleMapChangedEvents = Set<RCTMGLEvent.EventType>()
23
-
24
- var onStyleLoadedComponents: [RCTMGLMapComponent] = []
25
-
26
+
26
27
  private var isPendingInitialLayout = true
27
28
  private var wasGestureActive = false
28
29
  private var isGestureActive = false
@@ -80,7 +81,7 @@ open class RCTMGLMapView : MapView {
80
81
  super.insertReactSubview(subview, at: atIndex)
81
82
  }
82
83
 
83
- @objc open override func removeReactSubview(_ subview:UIView!) {
84
+ @objc open override func removeReactSubview(_ subview: UIView!) {
84
85
  removeFromMap(subview)
85
86
  super.removeReactSubview(subview)
86
87
  }
@@ -138,7 +139,7 @@ open class RCTMGLMapView : MapView {
138
139
 
139
140
  @objc func setReactProjection(_ value: String?) {
140
141
  if let value = value {
141
- var projection = StyleProjection(name: value == "globe" ? .globe : .mercator)
142
+ let projection = StyleProjection(name: value == "globe" ? .globe : .mercator)
142
143
  try! self.mapboxMap.style.setProjection(projection)
143
144
  }
144
145
  }
@@ -148,7 +149,7 @@ open class RCTMGLMapView : MapView {
148
149
  mapView.ornaments.options.attributionButton.visibility = value ? .visible : .hidden
149
150
  }
150
151
 
151
- @objc func setReactAttributionPosition(_ position: [String: Int]!) {
152
+ @objc func setReactAttributionPosition(_ position: [String: NSNumber]) {
152
153
  if let ornamentOptions = self.getOrnamentOptionsFromPosition(position) {
153
154
  mapView.ornaments.options.attributionButton.position = ornamentOptions.position
154
155
  mapView.ornaments.options.attributionButton.margins = ornamentOptions.margins
@@ -159,7 +160,7 @@ open class RCTMGLMapView : MapView {
159
160
  mapView.ornaments.options.logo.visibility = value ? .visible : .hidden
160
161
  }
161
162
 
162
- @objc func setReactLogoPosition(_ position: [String: Int]!) {
163
+ @objc func setReactLogoPosition(_ position: [String: NSNumber]) {
163
164
  if let ornamentOptions = self.getOrnamentOptionsFromPosition(position) {
164
165
  mapView.ornaments.options.logo.position = ornamentOptions.position
165
166
  mapView.ornaments.options.logo.margins = ornamentOptions.margins
@@ -168,17 +169,25 @@ open class RCTMGLMapView : MapView {
168
169
 
169
170
  @objc func setReactCompassEnabled(_ value: Bool) {
170
171
  compassEnabled = value
171
- mapView.ornaments.options.compass.visibility = value ? compassFadeWhenNorth ? .adaptive : .visible : .hidden
172
+ refreshCompassVisibility()
172
173
  }
173
174
 
174
175
  @objc func setReactCompassFadeWhenNorth(_ value: Bool) {
175
176
  compassFadeWhenNorth = value
176
- if (compassEnabled) {
177
- mapView.ornaments.options.compass.visibility = value ? .adaptive : .visible
177
+ refreshCompassVisibility()
178
+ }
179
+
180
+ private func refreshCompassVisibility() {
181
+ var visibility: OrnamentVisibility = .hidden
182
+ if compassEnabled {
183
+ visibility = compassFadeWhenNorth ? .adaptive : .visible
178
184
  }
185
+ mapView.ornaments.options.compass.visibility = visibility
186
+
187
+ refreshCompassImage()
179
188
  }
180
189
 
181
- @objc func setReactCompassPosition(_ position: [String: Int]!) {
190
+ @objc func setReactCompassPosition(_ position: [String: NSNumber]) {
182
191
  if let ornamentOptions = self.getOrnamentOptionsFromPosition(position) {
183
192
  mapView.ornaments.options.compass.position = ornamentOptions.position
184
193
  mapView.ornaments.options.compass.margins = ornamentOptions.margins
@@ -208,19 +217,37 @@ open class RCTMGLMapView : MapView {
208
217
  }
209
218
  }
210
219
 
211
- @objc func setReactCompassViewPosition(_ position: Int) {
212
- mapView.ornaments.options.compass.position = toOrnamentPositon(position)
220
+ @objc func setReactCompassViewPosition(_ position: NSNumber) {
221
+ mapView.ornaments.options.compass.position = toOrnamentPositon(Int(truncating: position))
213
222
  }
214
223
 
215
224
  @objc func setReactCompassViewMargins(_ margins: CGPoint) {
216
225
  mapView.ornaments.options.compass.margins = margins;
217
226
  }
218
227
 
228
+ @objc func setReactCompassImage(_ image: String) {
229
+ compassImage = image.isEmpty ? nil : image
230
+ refreshCompassImage()
231
+ }
232
+
233
+ private func refreshCompassImage() {
234
+ if let compassImage = compassImage {
235
+ onMapStyleLoaded { map in
236
+ let img = map.style.image(withId: compassImage)
237
+ self.mapView.ornaments.options.compass.image = img
238
+ }
239
+ } else {
240
+ // Does not currently reset the image to the default.
241
+ // See https://github.com/mapbox/mapbox-maps-ios/issues/1673.
242
+ self.mapView.ornaments.options.compass.image = nil
243
+ }
244
+ }
245
+
219
246
  @objc func setReactScaleBarEnabled(_ value: Bool) {
220
247
  self.mapView.ornaments.options.scaleBar.visibility = value ? .visible : .hidden
221
248
  }
222
249
 
223
- @objc func setReactScaleBarPosition(_ position: [String: Int]!) {
250
+ @objc func setReactScaleBarPosition(_ position: [String: NSNumber]) {
224
251
  if let ornamentOptions = self.getOrnamentOptionsFromPosition(position) {
225
252
  mapView.ornaments.options.scaleBar.position = ornamentOptions.position
226
253
  mapView.ornaments.options.scaleBar.margins = ornamentOptions.margins
@@ -259,20 +286,20 @@ open class RCTMGLMapView : MapView {
259
286
  }
260
287
  }
261
288
 
262
- private func getOrnamentOptionsFromPosition(_ position: [String: Int]) -> (position: OrnamentPosition, margins: CGPoint)? {
289
+ private func getOrnamentOptionsFromPosition(_ position: [String: NSNumber]) -> (position: OrnamentPosition, margins: CGPoint)? {
263
290
  let left = position["left"]
264
291
  let right = position["right"]
265
292
  let top = position["top"]
266
293
  let bottom = position["bottom"]
267
294
 
268
295
  if let left = left, let top = top {
269
- return (OrnamentPosition.topLeading, CGPoint(x: left, y: top))
296
+ return (OrnamentPosition.topLeading, CGPoint(x: Int(truncating: left), y: Int(truncating: top)))
270
297
  } else if let right = right, let top = top {
271
- return (OrnamentPosition.topTrailing, CGPoint(x: right, y: top))
298
+ return (OrnamentPosition.topTrailing, CGPoint(x: Int(truncating: right), y: Int(truncating: top)))
272
299
  } else if let bottom = bottom, let right = right {
273
- return (OrnamentPosition.bottomTrailing, CGPoint(x: right, y: bottom))
300
+ return (OrnamentPosition.bottomTrailing, CGPoint(x: Int(truncating: right), y: Int(truncating: bottom)))
274
301
  } else if let bottom = bottom, let left = left {
275
- return (OrnamentPosition.bottomLeading, CGPoint(x: left, y: bottom))
302
+ return (OrnamentPosition.bottomLeading, CGPoint(x: Int(truncating: left), y: Int(truncating: bottom)))
276
303
  }
277
304
 
278
305
  return nil
@@ -282,10 +309,26 @@ open class RCTMGLMapView : MapView {
282
309
  // MARK: - event handlers
283
310
 
284
311
  extension RCTMGLMapView {
312
+ private func onEvery<Payload>(event: MapEvents.Event<Payload>, handler: @escaping (RCTMGLMapView, MapEvent<Payload>) -> Void) {
313
+ self.mapView.mapboxMap.onEvery(event: event) { [weak self](mapEvent) in
314
+ guard let self = self else { return }
315
+
316
+ handler(self, mapEvent)
317
+ }
318
+ }
319
+
320
+ private func onNext<Payload>(event: MapEvents.Event<Payload>, handler: @escaping (RCTMGLMapView, MapEvent<Payload>) -> Void) {
321
+ self.mapView.mapboxMap.onNext(event: event) { [weak self](mapEvent) in
322
+ guard let self = self else { return }
323
+
324
+ handler(self, mapEvent)
325
+ }
326
+ }
327
+
285
328
  @objc func setReactOnMapChange(_ value: @escaping RCTBubblingEventBlock) {
286
329
  self.reactOnMapChange = value
287
330
 
288
- self.mapView.mapboxMap.onEvery(event: .cameraChanged, handler: { cameraEvent in
331
+ self.onEvery(event: .cameraChanged, handler: { (self, cameraEvent) in
289
332
  self.wasGestureActive = self.isGestureActive
290
333
  if self.handleMapChangedEvents.contains(.regionIsChanging) {
291
334
  let event = RCTMGLEvent(type:.regionIsChanging, payload: self.buildRegionObject());
@@ -296,7 +339,7 @@ extension RCTMGLMapView {
296
339
  }
297
340
  })
298
341
 
299
- self.mapView.mapboxMap.onEvery(event: .mapIdle, handler: { cameraEvent in
342
+ self.onEvery(event: .mapIdle, handler: { (self, cameraEvent) in
300
343
  if self.handleMapChangedEvents.contains(.regionDidChange) {
301
344
  let event = RCTMGLEvent(type:.regionDidChange, payload: self.buildRegionObject());
302
345
  self.fireEvent(event: event, callback: self.reactOnMapChange)
@@ -367,7 +410,7 @@ extension RCTMGLMapView {
367
410
  }
368
411
 
369
412
  public func setupEvents() {
370
- self.mapboxMap.onEvery(event: .mapLoadingError, handler: {(event) in
413
+ self.onEvery(event: .mapLoadingError, handler: {(self, event) in
371
414
  if let message = event.payload.error.errorDescription {
372
415
  Logger.log(level: .error, message: "MapLoad error \(message)")
373
416
  } else {
@@ -375,7 +418,7 @@ extension RCTMGLMapView {
375
418
  }
376
419
  })
377
420
 
378
- self.mapboxMap.onEvery(event: .styleImageMissing) { (event) in
421
+ self.onEvery(event: .styleImageMissing) { (self, event) in
379
422
  let imageName = event.payload.id
380
423
 
381
424
  self.images.forEach {
@@ -389,7 +432,7 @@ extension RCTMGLMapView {
389
432
  }
390
433
  }
391
434
 
392
- self.mapboxMap.onEvery(event: .renderFrameFinished, handler: { (event) in
435
+ self.onEvery(event: .renderFrameFinished, handler: { (self, event) in
393
436
  var type = RCTMGLEvent.EventType.didFinishRendering
394
437
  if event.payload.renderMode == .full {
395
438
  type = .didFinishRenderingFully
@@ -403,16 +446,16 @@ extension RCTMGLMapView {
403
446
  self.fireEvent(event: event, callback: self.reactOnMapChange)
404
447
  })
405
448
 
406
- self.mapboxMap.onNext(event: .mapLoaded, handler: { (event) in
449
+ self.onNext(event: .mapLoaded, handler: { (self, event) in
407
450
  let event = RCTMGLEvent(type:.didFinishLoadingMap, payload: nil);
408
451
  self.fireEvent(event: event, callback: self.reactOnMapChange)
409
452
  })
410
453
 
411
- self.mapboxMap.onEvery(event: .styleLoaded, handler: { (event) in
454
+ self.onEvery(event: .styleLoaded, handler: { (self, event) in
412
455
  self.onStyleLoadedComponents.forEach { (component) in
413
456
  component.addToMap(self, style: self.mapboxMap.style)
414
457
  }
415
-
458
+
416
459
  if !self.styleLoaded {
417
460
  self.styleLoaded = true
418
461
  if let mapboxMap = self.mapboxMap {
@@ -5,13 +5,16 @@
5
5
 
6
6
  RCT_REMAP_VIEW_PROPERTY(attributionEnabled, reactAttributionEnabled, BOOL)
7
7
  RCT_REMAP_VIEW_PROPERTY(attributionPosition, reactAttributionPosition, NSDictionary)
8
+
8
9
  RCT_REMAP_VIEW_PROPERTY(logoEnabled, reactLogoEnabled, BOOL)
9
10
  RCT_REMAP_VIEW_PROPERTY(logoPosition, reactLogoPosition, NSDictionary)
11
+
10
12
  RCT_REMAP_VIEW_PROPERTY(compassEnabled, reactCompassEnabled, BOOL)
11
13
  RCT_REMAP_VIEW_PROPERTY(compassFadeWhenNorth, reactCompassFadeWhenNorth, BOOL)
12
14
  RCT_REMAP_VIEW_PROPERTY(compassPosition, reactCompassPosition, NSDictionary)
13
15
  RCT_REMAP_VIEW_PROPERTY(compassViewPosition, reactCompassViewPosition, NSInteger)
14
16
  RCT_REMAP_VIEW_PROPERTY(compassViewMargins, reactCompassViewMargins, CGPoint)
17
+ RCT_REMAP_VIEW_PROPERTY(compassImage, reactCompassImage, NSString)
15
18
 
16
19
  RCT_REMAP_VIEW_PROPERTY(scaleBarEnabled, reactScaleBarEnabled, BOOL)
17
20
  RCT_REMAP_VIEW_PROPERTY(scaleBarPosition, reactScaleBarPosition, NSDictionary)
@@ -215,13 +215,13 @@ extension RCTMGLMapViewManager {
215
215
  resolver: @escaping RCTPromiseResolveBlock,
216
216
  rejecter: @escaping RCTPromiseRejectBlock) -> Void {
217
217
  withMapView(reactTag, name:"queryRenderedFeaturesInRect", rejecter: rejecter) { mapView in
218
- let left = bbox.isEmpty ? 0.0 : CGFloat(bbox[0].floatValue)
219
- let bottom = bbox.isEmpty ? 0.0 : CGFloat(bbox[1].floatValue)
220
- let right = bbox.isEmpty ? 0.0 : CGFloat(bbox[2].floatValue)
221
- let top = bbox.isEmpty ? 0.0 : CGFloat(bbox[3].floatValue)
218
+ let top = bbox.isEmpty ? 0.0 : CGFloat(bbox[0].floatValue)
219
+ let right = bbox.isEmpty ? 0.0 : CGFloat(bbox[1].floatValue)
220
+ let bottom = bbox.isEmpty ? 0.0 : CGFloat(bbox[2].floatValue)
221
+ let left = bbox.isEmpty ? 0.0 : CGFloat(bbox[3].floatValue)
222
222
  let rect = bbox.isEmpty ? CGRect(x: 0.0, y: 0.0, width: mapView.bounds.size.width, height: mapView.bounds.size.height) : CGRect(x: [left,right].min()!, y: [top,bottom].min()!, width: abs(right-left), height: abs(bottom-top))
223
223
  logged("queryRenderedFeaturesInRect.option", rejecter: rejecter) {
224
- let options = try RenderedQueryOptions(layerIds: layerIDs, filter: filter?.asExpression())
224
+ let options = try RenderedQueryOptions(layerIds: layerIDs?.isEmpty ?? true ? nil : layerIDs, filter: filter?.asExpression())
225
225
  mapView.mapboxMap.queryRenderedFeatures(with: rect, options: options) { result in
226
226
  switch result {
227
227
  case .success(let features):
@@ -7,7 +7,7 @@ class RCTMGLMarkerView: UIView, RCTMGLMapComponent {
7
7
  static let key = "RCTMGLMarkerView"
8
8
  let id: String = "marker-\(UUID().uuidString)"
9
9
 
10
- var map: RCTMGLMapView?
10
+ weak var map: RCTMGLMapView?
11
11
 
12
12
  var didAddToMap = false
13
13
 
@@ -14,7 +14,7 @@ class RCTMGLPointAnnotation : RCTMGLInteractiveElement {
14
14
  static var gid = 0;
15
15
 
16
16
  var annotation : PointAnnotation! = nil
17
- var callout: RCTMGLCallout? = nil
17
+ weak var callout: RCTMGLCallout? = nil
18
18
  var calloutId : String?
19
19
  var image : UIImage? = nil
20
20
  var reactSubviews : [UIView] = []
@@ -3,8 +3,8 @@ import MapboxMaps
3
3
  /// RCTMGLSingletonLayer is absract superclass for Light, Atmosphere, Terrain
4
4
  @objc
5
5
  class RCTMGLSingletonLayer : UIView {
6
- var bridge : RCTBridge? = nil
7
- var map : RCTMGLMapView? = nil
6
+ weak var bridge : RCTBridge? = nil
7
+ weak var map : RCTMGLMapView? = nil
8
8
  var style: Style? = nil
9
9
 
10
10
  @objc var reactStyle : Dictionary<String, Any>? = nil {
@@ -2,11 +2,22 @@
2
2
 
3
3
  @objc
4
4
  class RCTMGLSource : RCTMGLInteractiveElement {
5
-
5
+ var layers: [RCTMGLSourceConsumer] = []
6
+
6
7
  var source : Source? = nil
7
8
 
8
9
  var ownsSource : Bool = false
9
10
 
11
+ override func getLayerIDs() -> [String] {
12
+ layers.compactMap {
13
+ if let layer = $0 as? RCTMGLLayer {
14
+ return layer.id
15
+ } else {
16
+ return nil
17
+ }
18
+ }
19
+ }
20
+
10
21
  func makeSource() -> Source {
11
22
  fatalError("Subclasses should override makeSource")
12
23
  }
@@ -15,6 +26,8 @@ class RCTMGLSource : RCTMGLInteractiveElement {
15
26
  fatalError("Subclasses should override makeSource")
16
27
  }
17
28
 
29
+ // MARK: - UIView+React
30
+
18
31
  @objc override func insertReactSubview(_ subview: UIView!, at atIndex: Int) {
19
32
  if let layer : RCTMGLSourceConsumer = subview as? RCTMGLSourceConsumer {
20
33
  if let map = map {
@@ -22,6 +35,15 @@ class RCTMGLSource : RCTMGLInteractiveElement {
22
35
  }
23
36
  layers.append(layer)
24
37
  }
38
+ super.insertReactSubview(subview, at: atIndex)
39
+ }
40
+
41
+ @objc override func removeReactSubview(_ subview: UIView!) {
42
+ super.removeReactSubview(subview)
43
+ }
44
+
45
+ @objc override func didUpdateReactSubviews() {
46
+ // do nothing to prevent inserting layers to UIView hierarchy
25
47
  }
26
48
 
27
49
  // MARK: - RCTMGLInteractiveElement
@@ -225,7 +225,7 @@ class RCTMGLStyleValue {
225
225
  red: CGFloat((Float((rgbValue & 0xff0000) >> 16)) / 255.0),
226
226
  green: CGFloat((Float((rgbValue & 0x00ff00) >> 8)) / 255.0),
227
227
  blue: CGFloat((Float((rgbValue & 0x0000ff) >> 0)) / 255.0),
228
- alpha: 1.0)
228
+ alpha: CGFloat((rgbValue & 0xFF000000) >> 24) / 0xFF)
229
229
  }
230
230
 
231
231
  func mglStyleValueColor() -> Value<StyleColor> {