@rnmapbox/maps 10.0.0-rc.6 → 10.0.0-rc.8

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 (22) hide show
  1. package/android/rctmgl/src/main/java-v10/com/mapbox/rctmgl/components/AbstractEventEmitter.kt +1 -1
  2. package/android/rctmgl/src/main/java-v10/com/mapbox/rctmgl/components/camera/RCTMGLCamera.kt +92 -9
  3. package/android/rctmgl/src/main/java-v10/com/mapbox/rctmgl/components/location/LocationComponentManager.kt +3 -2
  4. package/android/rctmgl/src/main/java-v10/com/mapbox/rctmgl/components/mapview/RCTMGLMapView.kt +59 -17
  5. package/android/rctmgl/src/main/java-v10/com/mapbox/rctmgl/components/mapview/RCTMGLMapViewManager.kt +8 -4
  6. package/android/rctmgl/src/main/java-v10/com/mapbox/rctmgl/events/AbstractEvent.kt +49 -0
  7. package/android/rctmgl/src/main/java-v10/com/mapbox/rctmgl/events/IEvent.kt +17 -0
  8. package/android/rctmgl/src/main/java-v10/com/mapbox/rctmgl/events/LocationEvent.kt +11 -16
  9. package/android/rctmgl/src/main/java-v10/com/mapbox/rctmgl/events/MapUserTrackingModeEvent.kt +10 -10
  10. package/android/rctmgl/src/main/java-v10/com/mapbox/rctmgl/events/constants/EventTypes.kt +44 -0
  11. package/android/rctmgl/src/main/java-v10/com/mapbox/rctmgl/modules/RCTMGLLocationModule.kt +36 -1
  12. package/ios/RCTMGL-v10/RCTMGLCamera.swift +1 -1
  13. package/ios/RCTMGL-v10/RCTMGLLocationModule.m +2 -2
  14. package/ios/install.md +7 -0
  15. package/lib/commonjs/components/Terrain.js +1 -1
  16. package/lib/module/components/Terrain.js +1 -1
  17. package/package.json +1 -1
  18. package/plugin/install.md +17 -0
  19. package/src/components/Terrain.tsx +1 -1
  20. package/android/rctmgl/src/main/java-v10/com/mapbox/rctmgl/events/AbstractEvent.java +0 -62
  21. package/android/rctmgl/src/main/java-v10/com/mapbox/rctmgl/events/IEvent.java +0 -18
  22. package/android/rctmgl/src/main/java-v10/com/mapbox/rctmgl/events/constants/EventTypes.java +0 -51
@@ -38,7 +38,7 @@ abstract class AbstractEventEmitter<T : ViewGroup?>(reactApplicationContext: Rea
38
38
  mRateLimitedEvents[eventCacheKey] = System.currentTimeMillis()
39
39
  mEventDispatcher!!.dispatchEvent(
40
40
  AbstractEvent(
41
- event.id,
41
+ event.iD,
42
42
  event.key,
43
43
  event.canCoalesce(),
44
44
  event.toJSON()
@@ -24,6 +24,9 @@ import com.mapbox.maps.plugin.viewport.ViewportStatusObserver
24
24
  import com.mapbox.maps.plugin.viewport.data.FollowPuckViewportStateBearing
25
25
  import com.mapbox.maps.plugin.viewport.data.FollowPuckViewportStateOptions
26
26
  import com.mapbox.maps.plugin.viewport.data.ViewportStatusChangeReason
27
+ import com.mapbox.maps.plugin.viewport.state.FollowPuckViewportState
28
+ import com.mapbox.maps.plugin.viewport.state.OverviewViewportState
29
+ import com.mapbox.maps.plugin.viewport.state.ViewportState
27
30
  import com.mapbox.maps.plugin.viewport.viewport
28
31
  import com.mapbox.rctmgl.components.RemovalReason
29
32
  import com.mapbox.rctmgl.components.camera.constants.CameraMode
@@ -31,6 +34,7 @@ import com.mapbox.rctmgl.components.location.*
31
34
  import com.mapbox.rctmgl.events.MapUserTrackingModeEvent
32
35
  import com.mapbox.rctmgl.location.*
33
36
  import com.mapbox.rctmgl.utils.Logger
37
+ import com.mapbox.rctmgl.utils.writableMapOf
34
38
 
35
39
 
36
40
  class RCTMGLCamera(private val mContext: Context, private val mManager: RCTMGLCameraManager) :
@@ -91,7 +95,7 @@ class RCTMGLCamera(private val mContext: Context, private val mManager: RCTMGLCa
91
95
  setInitialCamera()
92
96
  updateMaxBounds()
93
97
  mCameraStop?.let { updateCamera(it) }
94
- _observeViewportState(mapView)
98
+ _observeViewportState(mapView.mapView)
95
99
  _updateViewportState()
96
100
  }
97
101
 
@@ -281,27 +285,105 @@ class RCTMGLCamera(private val mContext: Context, private val mManager: RCTMGLCa
281
285
  }
282
286
  }
283
287
 
288
+ fun toFollowUserLocation(toStatus: ViewportStatus): Boolean {
289
+ when (toStatus) {
290
+ ViewportStatus.Idle -> return false
291
+ is ViewportStatus.State -> return true
292
+ is ViewportStatus.Transition -> return true
293
+ }
294
+ }
295
+
296
+ fun toFollowUserMode(state: ViewportState): String? {
297
+ if (state is FollowPuckViewportState) {
298
+ when (state.options.bearing) {
299
+ is FollowPuckViewportStateBearing.SyncWithLocationPuck ->
300
+ return "normal"
301
+ is FollowPuckViewportStateBearing.Constant ->
302
+ return "constant"
303
+ else -> {
304
+ Logger.w(LOG_TAG, "Unexpected bearing: ${state.options.bearing}")
305
+ return "normal"
306
+ }
307
+ }
308
+ } else if (state is OverviewViewportState) {
309
+ return "overview"
310
+ } else {
311
+ return "custom"
312
+ }
313
+ }
314
+
315
+ fun toFollowUserMode(status: ViewportStatus): String? {
316
+ when (status) {
317
+ ViewportStatus.Idle -> return null
318
+ is ViewportStatus.State ->
319
+ return toFollowUserMode(status)
320
+ is ViewportStatus.Transition ->
321
+ return toFollowUserMode(status.toState)
322
+ }
323
+ }
324
+
325
+ fun toReadableMap(status: ViewportStatus): ReadableMap {
326
+ when (status) {
327
+ ViewportStatus.Idle -> return writableMapOf("state" to "idle")
328
+ is ViewportStatus.State ->
329
+ return writableMapOf(
330
+ "state" to status.toString()
331
+ )
332
+ is ViewportStatus.Transition ->
333
+ return writableMapOf(
334
+ "transition" to status.toString()
335
+ )
336
+ }
337
+ }
338
+
284
339
  fun _observeViewportState(mapView: MapView) {
285
340
  mapView.viewport.addStatusObserver(object: ViewportStatusObserver {
286
341
  override fun onViewportStatusChanged(
287
- from: ViewportStatus,
288
- to: ViewportStatus,
342
+ fromStatus: ViewportStatus,
343
+ toStatus: ViewportStatus,
289
344
  reason: ViewportStatusChangeReason
290
345
  ) {
291
- if (to == ViewportStatus.Idle) {
292
- mManager.handleEvent(MapUserTrackingModeEvent(this@RCTMGLCamera, UserTrackingMode.NONE))
293
- } else if (to is ViewportStatus.Transition) {
346
+ if (reason == ViewportStatusChangeReason.USER_INTERACTION) {
347
+ val followUserLocation = toFollowUserLocation(toStatus)
348
+
294
349
 
295
- } else if (to is ViewportStatus.State){
296
- //mManager.handleEvent(MapUserTrackingModeEvent(this@RCTMGLCamera, UserTrackingMode.FOLLOW))
350
+
351
+ mManager.handleEvent(MapUserTrackingModeEvent(this@RCTMGLCamera, UserTrackingMode.NONE,
352
+ writableMapOf(
353
+ "followUserMode" to toFollowUserMode(toStatus),
354
+ "followUserLocation" to followUserLocation,
355
+ "fromViewportState" to toReadableMap(fromStatus),
356
+ "toViewportState" to toReadableMap(toStatus),
357
+ "reason" to toString(reason),
358
+ )
359
+ ))
297
360
  }
298
361
  }
299
362
  })
300
363
  }
301
364
 
365
+ fun toString(reason: ViewportStatusChangeReason): String {
366
+ when (reason) {
367
+ ViewportStatusChangeReason.IDLE_REQUESTED ->
368
+ return "idleRequested"
369
+ ViewportStatusChangeReason.TRANSITION_FAILED ->
370
+ return "transitionFailed"
371
+ ViewportStatusChangeReason.TRANSITION_STARTED ->
372
+ return "transitionStarted"
373
+ ViewportStatusChangeReason.TRANSITION_SUCCEEDED ->
374
+ return "transitionSucceeded"
375
+ ViewportStatusChangeReason.USER_INTERACTION ->
376
+ return "userInteraction"
377
+ else -> {
378
+ Logger.w(LOG_TAG, "toString; unkown reason: ${reason}")
379
+ return "unkown: $reason"
380
+ }
381
+ }
382
+ }
383
+
302
384
  fun _updateViewportState() {
303
385
  mMapView?.let {
304
- val map = it
386
+ val map = it.mapView
305
387
  val viewport = map.viewport;
306
388
 
307
389
  if (mLocationComponentManager == null) {
@@ -418,5 +500,6 @@ class RCTMGLCamera(private val mContext: Context, private val mManager: RCTMGLCa
418
500
  const val USER_LOCATION_CAMERA_MOVE_DURATION = 1000
419
501
  const val minimumZoomLevelForUserTracking = 10.5
420
502
  const val defaultZoomLevelForUserTracking = 14.0
503
+ const val LOG_TAG = "RCTMGLCamera"
421
504
  }
422
505
  }
@@ -64,6 +64,7 @@ class LocationComponentManager(mapView: RCTMGLMapView, context: Context) {
64
64
  }
65
65
 
66
66
  private fun applyStateChanges(map: RCTMGLMapView, oldState: State, newState: State, fullUpdate: Boolean) {
67
+ val mapView = map.mapView
67
68
  if (map.getLifecycleState() != Lifecycle.State.STARTED) {
68
69
  // In case lifecycle was already stopped, so we're part of shutdown, do not call updateSettings as it'll just restart
69
70
  // the loationComponent that will not be stopped. See https://github.com/mapbox/mapbox-maps-android/issues/2017
@@ -72,7 +73,7 @@ class LocationComponentManager(mapView: RCTMGLMapView, context: Context) {
72
73
  }
73
74
  return
74
75
  }
75
- map.location.updateSettings {
76
+ mapView.location.updateSettings {
76
77
  enabled = newState.enabled
77
78
 
78
79
  if (fullUpdate || (newState.hidden != oldState.hidden) || (newState.tintColor != oldState.tintColor) || (newState.bearingImage != oldState.bearingImage)) {
@@ -140,7 +141,7 @@ class LocationComponentManager(mapView: RCTMGLMapView, context: Context) {
140
141
  }
141
142
 
142
143
  private fun useMapLocationProvider(mapView: RCTMGLMapView) {
143
- val provider = mapView.location.getLocationProvider()
144
+ val provider = mapView.mapView.location.getLocationProvider()
144
145
  if (provider != null) {
145
146
  mLocationManager.provider = provider
146
147
  }
@@ -7,6 +7,7 @@ import android.graphics.RectF
7
7
  import android.util.Log
8
8
  import android.view.Gravity
9
9
  import android.view.View
10
+ import android.view.View.OnLayoutChangeListener
10
11
  import android.view.ViewGroup
11
12
  import android.widget.FrameLayout
12
13
  import androidx.lifecycle.Lifecycle
@@ -45,6 +46,7 @@ import com.mapbox.maps.plugin.logo.generated.LogoSettings
45
46
  import com.mapbox.maps.plugin.logo.logo
46
47
  import com.mapbox.maps.plugin.scalebar.generated.ScaleBarSettings
47
48
  import com.mapbox.maps.plugin.scalebar.scalebar
49
+ import com.mapbox.maps.viewannotation.ViewAnnotationManager
48
50
  import com.mapbox.rctmgl.R
49
51
  import com.mapbox.rctmgl.components.AbstractMapFeature
50
52
  import com.mapbox.rctmgl.components.RemovalReason
@@ -145,7 +147,7 @@ data class FeatureEntry(val feature: AbstractMapFeature?, val view: View?, var a
145
147
 
146
148
  }
147
149
 
148
- open class RCTMGLMapView(private val mContext: Context, var mManager: RCTMGLMapViewManager /*, MapboxMapOptions options*/) : MapView(mContext), OnMapClickListener, OnMapLongClickListener {
150
+ open class RCTMGLMapView(private val mContext: Context, var mManager: RCTMGLMapViewManager /*, MapboxMapOptions options*/) : FrameLayout(mContext), OnMapClickListener, OnMapLongClickListener, OnLayoutChangeListener {
149
151
  /**
150
152
  * `PointAnnotations` are rendered to a canvas, but the React Native `Image` component is
151
153
  * implemented on top of Fresco (https://frescolib.org), which does not load images for
@@ -170,6 +172,8 @@ open class RCTMGLMapView(private val mContext: Context, var mManager: RCTMGLMapV
170
172
  private val mCameraChangeTracker = CameraChangeTracker()
171
173
  private val mMap: MapboxMap?
172
174
 
175
+ private val mMapView: MapView
176
+
173
177
  var savedStyle: Style? = null
174
178
  private set
175
179
 
@@ -183,17 +187,24 @@ open class RCTMGLMapView(private val mContext: Context, var mManager: RCTMGLMapV
183
187
  private set
184
188
 
185
189
  val mapView: MapView
186
- get() = this
190
+ get() = this.mMapView
191
+
192
+ val viewAnnotationManager: ViewAnnotationManager
193
+ get() = mapView.viewAnnotationManager
194
+
195
+ fun getMapboxMap(): MapboxMap {
196
+ return mapView.getMapboxMap()
197
+ }
187
198
 
188
199
  val pointAnnotationManager: PointAnnotationManager?
189
200
  get() {
190
201
  if (mPointAnnotationManager == null) {
191
202
  val _this = this
192
- val gesturesPlugin: GesturesPlugin = this.gestures
203
+ val gesturesPlugin: GesturesPlugin = mapView.gestures
193
204
  gesturesPlugin.removeOnMapClickListener(_this)
194
205
  gesturesPlugin.removeOnMapLongClickListener(_this)
195
206
 
196
- mPointAnnotationManager = annotations.createPointAnnotationManager(AnnotationConfig(layerId = "rctmgl-mapview-annotations"))
207
+ mPointAnnotationManager = mapView.annotations.createPointAnnotationManager(AnnotationConfig(layerId = "rctmgl-mapview-annotations"))
197
208
  mPointAnnotationManager?.addClickListener(OnPointAnnotationClickListener { pointAnnotation ->
198
209
  onMarkerClick(pointAnnotation)
199
210
  false
@@ -272,7 +283,7 @@ open class RCTMGLMapView(private val mContext: Context, var mManager: RCTMGLMapV
272
283
  handleMapChangedEvent(EventTypes.MAP_IDLE);
273
284
  })
274
285
 
275
- val gesturesPlugin: GesturesPlugin = this.gestures
286
+ val gesturesPlugin: GesturesPlugin = mapView.gestures
276
287
  gesturesPlugin.addOnMapLongClickListener(_this)
277
288
  gesturesPlugin.addOnMapClickListener(_this)
278
289
 
@@ -581,7 +592,7 @@ open class RCTMGLMapView(private val mContext: Context, var mManager: RCTMGLMapV
581
592
  ScreenCoordinate(screenPoint.x + halfWidth,
582
593
  screenPoint.y + halfHeight)
583
594
  )
584
- getMapboxMap().queryRenderedFeatures(RenderedQueryGeometry(screenBox),
595
+ mapView.getMapboxMap().queryRenderedFeatures(RenderedQueryGeometry(screenBox),
585
596
  RenderedQueryOptions(
586
597
  source.layerIDs,
587
598
  null
@@ -814,7 +825,7 @@ open class RCTMGLMapView(private val mContext: Context, var mManager: RCTMGLMapV
814
825
  }
815
826
 
816
827
  fun getMapAsync(mapReady: OnMapReadyCallback) {
817
- mapReady.onMapReady(getMapboxMap())
828
+ mapReady.onMapReady(mapView.getMapboxMap())
818
829
  }
819
830
 
820
831
  //fun setTintColor(color: Int) {
@@ -938,7 +949,7 @@ open class RCTMGLMapView(private val mContext: Context, var mManager: RCTMGLMapV
938
949
  }
939
950
 
940
951
  fun takeSnap(callbackID: String?, writeToDisk: Boolean) {
941
- this.snapshot { snapshot ->
952
+ mapView.snapshot { snapshot ->
942
953
  if (snapshot == null) {
943
954
  Logger.e("takeSnap", "snapshot failed")
944
955
 
@@ -1030,7 +1041,13 @@ open class RCTMGLMapView(private val mContext: Context, var mManager: RCTMGLMapV
1030
1041
  offscreenAnnotationViewContainer?.setLayoutParams(p)
1031
1042
  addView(offscreenAnnotationViewContainer)
1032
1043
 
1033
- mMap = getMapboxMap()
1044
+ mMapView = MapView(mContext)
1045
+
1046
+ val matchParent = FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)
1047
+ mMapView.setLayoutParams(matchParent)
1048
+ addView(mMapView)
1049
+
1050
+ mMap = mapView.getMapboxMap()
1034
1051
  mSources = HashMap()
1035
1052
  mImages = ArrayList()
1036
1053
  mPointAnnotations = HashMap()
@@ -1050,7 +1067,9 @@ open class RCTMGLMapView(private val mContext: Context, var mManager: RCTMGLMapV
1050
1067
  }
1051
1068
  })
1052
1069
 
1053
- RCTMGLMarkerViewManager.markerViewContainerSizeFixer(this, this.viewAnnotationManager)
1070
+ RCTMGLMarkerViewManager.markerViewContainerSizeFixer(this, mapView.viewAnnotationManager)
1071
+
1072
+ this.addOnLayoutChangeListener(this)
1054
1073
  }
1055
1074
 
1056
1075
  // region Ornaments
@@ -1135,7 +1154,7 @@ open class RCTMGLMapView(private val mContext: Context, var mManager: RCTMGLMapV
1135
1154
  }
1136
1155
 
1137
1156
  private fun updateCompass() {
1138
- compass.updateSettings {
1157
+ mapView.compass.updateSettings {
1139
1158
  fadeWhenFacingNorth = mCompassFadeWhenNorth
1140
1159
  updateOrnament("compass", mCompassSettings, this.toGenericOrnamentSettings())
1141
1160
  }
@@ -1180,8 +1199,8 @@ open class RCTMGLMapView(private val mContext: Context, var mManager: RCTMGLMapV
1180
1199
  mapView.forceLayout();
1181
1200
 
1182
1201
  mapView.measure(
1183
- MeasureSpec.makeMeasureSpec(mapView.measuredWidth, MeasureSpec.EXACTLY),
1184
- MeasureSpec.makeMeasureSpec(mapView.measuredHeight, MeasureSpec.EXACTLY)
1202
+ MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
1203
+ MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY)
1185
1204
  );
1186
1205
  mapView.layout(mapView.left, mapView.top, mapView.right, mapView.bottom)
1187
1206
  }
@@ -1236,7 +1255,7 @@ open class RCTMGLMapView(private val mContext: Context, var mManager: RCTMGLMapV
1236
1255
  }
1237
1256
 
1238
1257
  private fun updateAttribution() {
1239
- attribution.updateSettings {
1258
+ mapView.attribution.updateSettings {
1240
1259
  updateOrnament("attribution", mAttributionSettings, this.toGenericOrnamentSettings())
1241
1260
  }
1242
1261
  workaroundToRelayoutChildOfMapView()
@@ -1271,7 +1290,7 @@ open class RCTMGLMapView(private val mContext: Context, var mManager: RCTMGLMapV
1271
1290
  }
1272
1291
 
1273
1292
  private fun updateLogo() {
1274
- logo.updateSettings {
1293
+ mapView.logo.updateSettings {
1275
1294
  updateOrnament("logo", mLogoSettings, this.toGenericOrnamentSettings())
1276
1295
  }
1277
1296
  workaroundToRelayoutChildOfMapView()
@@ -1290,18 +1309,21 @@ open class RCTMGLMapView(private val mContext: Context, var mManager: RCTMGLMapV
1290
1309
  super.onDetachedFromWindow();
1291
1310
  }
1292
1311
 
1312
+ /* FMTODO
1293
1313
  override fun onDestroy() {
1314
+ this.removeOnLayoutChangeListener(this)
1294
1315
  removeAllFeaturesFromMap(RemovalReason.ON_DESTROY)
1295
- viewAnnotationManager.removeAllViewAnnotations()
1316
+ mapView.viewAnnotationManager.removeAllViewAnnotations()
1296
1317
  mLocationComponentManager?.onDestroy();
1297
1318
 
1298
1319
  lifecycle.onDestroy()
1299
1320
  super.onDestroy()
1300
1321
  }
1322
+ */
1301
1323
 
1302
1324
  fun onDropViewInstance() {
1303
1325
  removeAllFeaturesFromMap(RemovalReason.ON_DESTROY)
1304
- viewAnnotationManager.removeAllViewAnnotations()
1326
+ mapView.viewAnnotationManager.removeAllViewAnnotations()
1305
1327
  lifecycle.onDestroy()
1306
1328
  }
1307
1329
 
@@ -1310,6 +1332,26 @@ open class RCTMGLMapView(private val mContext: Context, var mManager: RCTMGLMapV
1310
1332
  super.onAttachedToWindow()
1311
1333
  }
1312
1334
 
1335
+ override fun onLayoutChange(
1336
+ v: View?,
1337
+ left: Int,
1338
+ top: Int,
1339
+ right: Int,
1340
+ bottom: Int,
1341
+ oldLeft: Int,
1342
+ oldTop: Int,
1343
+ oldRight: Int,
1344
+ oldBottom: Int
1345
+ ) {
1346
+ mapView.post {
1347
+ mapView.measure(
1348
+ MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
1349
+ MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY)
1350
+ )
1351
+ mapView.layout(mapView.left, mapView.top, mapView.right, mapView.bottom)
1352
+ }
1353
+ }
1354
+
1313
1355
 
1314
1356
  // endregion
1315
1357
  }
@@ -117,24 +117,28 @@ open class RCTMGLMapViewManager(context: ReactApplicationContext) :
117
117
  }
118
118
 
119
119
  @ReactProp(name = "zoomEnabled")
120
- fun setZoomEnabled(mapView: RCTMGLMapView, zoomEnabled: Boolean) {
120
+ fun setZoomEnabled(map: RCTMGLMapView, zoomEnabled: Boolean) {
121
+ val mapView = map.mapView
121
122
  mapView.gestures.pinchToZoomEnabled = zoomEnabled
122
123
  mapView.gestures.doubleTouchToZoomOutEnabled = zoomEnabled
123
124
  mapView.gestures.doubleTapToZoomInEnabled = zoomEnabled
124
125
  }
125
126
 
126
127
  @ReactProp(name = "scrollEnabled")
127
- fun setScrollEnabled(mapView: RCTMGLMapView, scrollEnabled: Boolean) {
128
+ fun setScrollEnabled(map: RCTMGLMapView, scrollEnabled: Boolean) {
129
+ val mapView = map.mapView
128
130
  mapView.gestures.scrollEnabled = scrollEnabled
129
131
  }
130
132
 
131
133
  @ReactProp(name = "pitchEnabled")
132
- fun setPitchEnabled(mapView: RCTMGLMapView, pitchEnabled: Boolean) {
134
+ fun setPitchEnabled(map: RCTMGLMapView, pitchEnabled: Boolean) {
135
+ val mapView = map.mapView
133
136
  mapView.gestures.pitchEnabled = pitchEnabled
134
137
  }
135
138
 
136
139
  @ReactProp(name = "rotateEnabled")
137
- fun setRotateEnabled(mapView: RCTMGLMapView, rotateEnabled: Boolean) {
140
+ fun setRotateEnabled(map: RCTMGLMapView, rotateEnabled: Boolean) {
141
+ val mapView = map.mapView
138
142
  mapView.gestures.rotateEnabled = rotateEnabled
139
143
  }
140
144
 
@@ -0,0 +1,49 @@
1
+ package com.mapbox.rctmgl.events
2
+
3
+ import android.view.View
4
+ import com.facebook.react.bridge.Arguments
5
+ import com.facebook.react.bridge.WritableMap
6
+
7
+ abstract class AbstractEvent(view: View?, private val mEventType: String) : IEvent {
8
+ private var mTagID = 0
9
+ private val mTimestamp: Long
10
+
11
+ constructor(eventType: String) : this(null, eventType) {}
12
+
13
+ init {
14
+ if (view != null) {
15
+ mTagID = view.id
16
+ }
17
+ mTimestamp = System.currentTimeMillis()
18
+ }
19
+
20
+ override val iD
21
+ get() = mTagID
22
+
23
+ override val type
24
+ get() = mEventType
25
+
26
+ override fun equals(event: IEvent): Boolean {
27
+ return key == event.key && mEventType == event.type
28
+ }
29
+
30
+ override val payload
31
+ get() = Arguments.createMap()
32
+
33
+ override val timestamp
34
+ get() = mTimestamp
35
+
36
+ override fun toJSON(): WritableMap {
37
+ val map = Arguments.createMap()
38
+ map.putString("type", type)
39
+ val payloadClone = Arguments.createMap()
40
+ payloadClone.merge(payload)
41
+ map.putMap("payload", payloadClone)
42
+ return map
43
+ }
44
+
45
+ override fun canCoalesce(): Boolean {
46
+ // default behavior of com.facebook.react.uimanager.events.Event
47
+ return true
48
+ }
49
+ }
@@ -0,0 +1,17 @@
1
+ package com.mapbox.rctmgl.events
2
+
3
+ import com.facebook.react.bridge.WritableMap
4
+
5
+ /**
6
+ * Created by nickitaliano on 8/23/17.
7
+ */
8
+ interface IEvent {
9
+ val iD: Int
10
+ val key: String?
11
+ val type: String?
12
+ val timestamp: Long
13
+ fun equals(event: IEvent): Boolean
14
+ fun canCoalesce(): Boolean
15
+ val payload: WritableMap
16
+ fun toJSON(): WritableMap
17
+ }
@@ -3,10 +3,8 @@ package com.mapbox.rctmgl.events
3
3
  import android.location.Location
4
4
  import com.facebook.react.bridge.Arguments
5
5
  import com.mapbox.rctmgl.components.mapview.RCTMGLMapView
6
- import com.mapbox.rctmgl.events.IEvent
7
6
  import com.mapbox.rctmgl.events.constants.EventKeys
8
7
  import com.mapbox.rctmgl.events.constants.EventTypes
9
- import com.mapbox.rctmgl.events.LocationEvent
10
8
  import com.facebook.react.bridge.WritableMap
11
9
  import com.facebook.react.bridge.WritableNativeMap
12
10
  import java.util.*
@@ -20,21 +18,17 @@ class LocationEvent(private val location: Location, private val mapView: RCTMGLM
20
18
 
21
19
  constructor(location: Location) : this(location, null) {}
22
20
 
23
- override fun getID(): Int {
24
- return mapView?.id ?: -1
25
- }
21
+ override val iD
22
+ get() = mapView?.id ?: -1
26
23
 
27
- override fun getKey(): String {
28
- return EventKeys.USER_LOCATION_UPDATE
29
- }
24
+ override val key
25
+ get() = EventKeys.USER_LOCATION_UPDATE
30
26
 
31
- override fun getType(): String {
32
- return EventTypes.USER_LOCATION_UPDATED
33
- }
27
+ override val type
28
+ get() = EventTypes.USER_LOCATION_UPDATED
34
29
 
35
- override fun getTimestamp(): Long {
36
- return System.currentTimeMillis()
37
- }
30
+ override val timestamp
31
+ get() = System.currentTimeMillis()
38
32
 
39
33
  override fun equals(event: IEvent): Boolean {
40
34
  val other = event as LocationEvent
@@ -45,14 +39,15 @@ class LocationEvent(private val location: Location, private val mapView: RCTMGLM
45
39
  return uUID == event.uUID
46
40
  }
47
41
 
48
- override fun getPayload(): WritableMap {
42
+ override val payload: WritableMap
43
+ get() {
49
44
  val positionProperties: WritableMap = WritableNativeMap()
50
45
  val coords: WritableMap = WritableNativeMap()
51
46
  coords.putDouble("longitude", location.longitude)
52
47
  coords.putDouble("latitude", location.latitude)
53
48
  coords.putDouble("altitude", location.altitude)
54
49
  coords.putDouble("accuracy", location.accuracy.toDouble())
55
- // A better solution will be to pull the heading from the compass engine,
50
+ // A better solution will be to pull the heading from the compass engine,
56
51
  // unfortunately the api is not publicly available in the mapbox sdk
57
52
  coords.putDouble("heading", location.bearing.toDouble())
58
53
  coords.putDouble("course", location.bearing.toDouble())
@@ -7,15 +7,15 @@ import com.mapbox.rctmgl.components.location.UserTrackingMode
7
7
  import com.mapbox.rctmgl.events.constants.EventKeys
8
8
  import com.mapbox.rctmgl.events.constants.EventTypes
9
9
 
10
- class MapUserTrackingModeEvent(view: View?, val userTrackingMode: Int) : AbstractEvent(view, EventTypes.MAP_USER_TRACKING_MODE_CHANGE) {
11
- override fun getKey(): String {
12
- return EventKeys.MAP_USER_TRACKING_MODE_CHANGE;
13
- }
10
+ class MapUserTrackingModeEvent(view: View?, val userTrackingMode: Int, val basePayload: WritableMap? = null) : AbstractEvent(view, EventTypes.MAP_USER_TRACKING_MODE_CHANGE) {
11
+ override val key
12
+ get() = EventKeys.MAP_USER_TRACKING_MODE_CHANGE;
14
13
 
15
- override fun getPayload(): WritableMap {
16
- val payload = Arguments.createMap()
17
- payload.putBoolean("followUserLocation", userTrackingMode != UserTrackingMode.NONE)
18
- payload.putString("followUserMode", UserTrackingMode.toString(userTrackingMode))
19
- return payload
20
- }
14
+ override val payload : WritableMap
15
+ get() = {
16
+ val payload = basePayload?.copy() ?: Arguments.createMap()
17
+ payload.putBoolean("followUserLocation", userTrackingMode != UserTrackingMode.NONE)
18
+ payload.putString("followUserMode", UserTrackingMode.toString(userTrackingMode))
19
+ payload
20
+ }.invoke()
21
21
  }
@@ -0,0 +1,44 @@
1
+ package com.mapbox.rctmgl.events.constants
2
+
3
+ object EventTypes {
4
+ // map event types
5
+ const val MAP_CLICK = "press"
6
+ const val MAP_LONG_CLICK = "longpress"
7
+ const val MAP_USER_TRACKING_MODE_CHANGE = "usertrackingmodechange"
8
+ const val REGION_WILL_CHANGE = "regionwillchange"
9
+ const val REGION_IS_CHANGING = "regionischanging" // deprecated
10
+ const val CAMERA_CHANGED = "camerachanged"
11
+ const val REGION_DID_CHANGE = "regiondidchange"
12
+ const val MAP_IDLE = "mapidle"
13
+ const val USER_LOCATION_UPDATED = "userlocationdupdated"
14
+ const val WILL_START_LOADING_MAP = "willstartloadingmap"
15
+ const val DID_FINISH_LOADING_MAP = "didfinishloadingmap"
16
+ const val DID_FAIL_LOADING_MAP = "didfailloadingmap"
17
+ const val WILL_START_RENDERING_FRAME = "willstartrenderingframe"
18
+ const val DID_FINISH_RENDERING_FRAME = "didfinishrenderingframe"
19
+ const val DID_FINISH_RENDERING_FRAME_FULLY = "didfinishrenderingframefully"
20
+ const val WILL_START_RENDERING_MAP = "willstartrenderingmap"
21
+ const val DID_FINISH_RENDERING_MAP = "didfinishrenderingmap"
22
+ const val DID_FINISH_RENDERING_MAP_FULLY = "didfinishrenderingmapfully"
23
+ const val DID_FINISH_LOADING_STYLE = "didfinishloadingstyle"
24
+
25
+ // point annotation event types
26
+ const val ANNOTATION_SELECTED = "annotationselected"
27
+ const val ANNOTATION_DESELECTED = "annotationdeselected"
28
+ const val ANNOTATION_DRAG_START = "annotationdragstart"
29
+ const val ANNOTATION_DRAG = "annotationdrag"
30
+ const val ANNOTATION_DRAG_END = "annotationdragend"
31
+
32
+ // offline event types
33
+ const val OFFLINE_ERROR = "offlineerror"
34
+ const val OFFLINE_TILE_LIMIT = "offlinetilelimit"
35
+ const val OFFLINE_STATUS = "offlinestatus"
36
+
37
+ // shape source event types
38
+ const val SHAPE_SOURCE_LAYER_CLICK = "shapesourcelayerpress"
39
+ const val VECTOR_SOURCE_LAYER_CLICK = "vectorsourcelayerpress"
40
+ const val RASTER_SOURCE_LAYER_CLICK = "rastersourcelayerpress"
41
+
42
+ // image missing event type
43
+ const val IMAGES_MISSING = "imagesmissing"
44
+ }
@@ -12,6 +12,9 @@ import com.mapbox.rctmgl.events.EventEmitter
12
12
  import com.mapbox.rctmgl.location.LocationManager.Companion.getInstance
13
13
  import java.lang.Exception
14
14
 
15
+ data class LocationEventThrottle(var waitBetweenEvents: Double? = null, var lastSentTimestamp: Long? = null) {
16
+ }
17
+
15
18
  @ReactModule(name = RCTMGLLocationModule.REACT_CLASS)
16
19
  class RCTMGLLocationModule(reactContext: ReactApplicationContext) :
17
20
  ReactContextBaseJavaModule(reactContext) {
@@ -19,6 +22,7 @@ class RCTMGLLocationModule(reactContext: ReactApplicationContext) :
19
22
  private var mMinDisplacement = 0f
20
23
  private val locationManager: LocationManager? = getInstance(reactContext)
21
24
  private var mLastLocation: Location? = null
25
+ private var locationEventThrottle: LocationEventThrottle = LocationEventThrottle()
22
26
 
23
27
  private val lifecycleEventListener: LifecycleEventListener = object : LifecycleEventListener {
24
28
  override fun onHostResume() {
@@ -52,7 +56,7 @@ class RCTMGLLocationModule(reactContext: ReactApplicationContext) :
52
56
  }
53
57
  }
54
58
  mLastLocation = location
55
- if (changed && (location != null)) {
59
+ if (changed && (location != null) && shouldSendLocationEvent()) {
56
60
  val locationEvent = LocationEvent(location)
57
61
  val emitter = EventEmitter.getModuleEmitter(reactApplicationContext)
58
62
  emitter?.emit(LOCATION_UPDATE, locationEvent.payload)
@@ -145,6 +149,37 @@ class RCTMGLLocationModule(reactContext: ReactApplicationContext) :
145
149
  mLastLocation = null
146
150
  }
147
151
 
152
+ // region Location event throttle
153
+ @ReactMethod
154
+ fun setLocationEventThrottle(throttleValue: Double) {
155
+ if (throttleValue > 0) {
156
+ locationEventThrottle.waitBetweenEvents = throttleValue;
157
+ } else {
158
+ locationEventThrottle.waitBetweenEvents = null
159
+ }
160
+ }
161
+
162
+ fun shouldSendLocationEvent(): Boolean {
163
+ val waitBetweenEvents = locationEventThrottle.waitBetweenEvents
164
+ if (waitBetweenEvents == null) {
165
+ return true
166
+ }
167
+
168
+ val currentTimestamp = System.nanoTime()
169
+ val lastSentTimestamp = locationEventThrottle.lastSentTimestamp
170
+ if (lastSentTimestamp == null) {
171
+ return true
172
+ }
173
+
174
+ if ((currentTimestamp - lastSentTimestamp) > 1000.0*waitBetweenEvents) {
175
+ return true
176
+ }
177
+
178
+ return false
179
+ }
180
+ // endregion
181
+
182
+
148
183
  companion object {
149
184
  const val REACT_CLASS = "RCTMGLLocationModule"
150
185
  const val LOCATION_UPDATE = "MapboxUserLocationUpdate"
@@ -571,7 +571,7 @@ extension RCTMGLCamera : ViewportStatusObserver {
571
571
  if reason == .idleRequested {
572
572
  return "idleRequested"
573
573
  } else if reason == .transitionFailed {
574
- return "transitionFailied"
574
+ return "transitionFailed"
575
575
  } else if reason == .transitionStarted {
576
576
  return "transitionStarted"
577
577
  } else if reason == .transitionSucceeded {
@@ -12,9 +12,9 @@ RCT_EXTERN_METHOD(getLastKnownLocation)
12
12
  RCT_EXTERN_METHOD(setMinDisplacement:(CLLocationDistance)minDisplacement)
13
13
  RCT_EXTERN_METHOD(setRequestsAlwaysUse:(BOOL)requestsAlwaysUse)
14
14
 
15
- RCT_EXTERN_METHOD(setLocationEventThrottle:(NSNumber *)throttleValue)
15
+ RCT_EXTERN_METHOD(setLocationEventThrottle:(nonnull NSNumber *)throttleValue)
16
16
 
17
- RCT_EXTERN_METHOD(simulateHeading:(nonnull NSNumber)changesPerSecond increment:(nonnull NSNumber))
17
+ RCT_EXTERN_METHOD(simulateHeading:(nonnull NSNumber*)changesPerSecond increment:(nonnull NSNumber*))
18
18
 
19
19
 
20
20
  @end
package/ios/install.md CHANGED
@@ -39,6 +39,13 @@ cd ios
39
39
  pod install
40
40
  ```
41
41
 
42
+ If you want to show the user's current location on the map with the [UserLocation](../docs/UserLocation.md) component, you'll need to add the following property to your `Info.plist` (see [Mapbox iOS docs](https://docs.mapbox.com/ios/maps/guides/user-location/#request-temporary-access-to-full-accuracy-location) for more info):
43
+
44
+ ```
45
+ <key>NSLocationWhenInUseUsageDescription</key>
46
+ <string>Show current location on map.</string>
47
+ ```
48
+
42
49
  You are good to go!
43
50
 
44
51
  Read on if you want to edit your Mapbox version or flavor.
@@ -16,7 +16,7 @@ const Terrain = /*#__PURE__*/(0, _react.memo)(props => {
16
16
  style = {}
17
17
  } = props;
18
18
  if (props.exaggeration) {
19
- console.warn(`Tarrain: exaggeration property is deprecated pls use style.exaggeration instead!`);
19
+ console.warn(`Terrain: exaggeration property is deprecated pls use style.exaggeration instead!`);
20
20
  style = {
21
21
  exaggeration: props.exaggeration,
22
22
  ...style
@@ -7,7 +7,7 @@ export const Terrain = /*#__PURE__*/memo(props => {
7
7
  style = {}
8
8
  } = props;
9
9
  if (props.exaggeration) {
10
- console.warn(`Tarrain: exaggeration property is deprecated pls use style.exaggeration instead!`);
10
+ console.warn(`Terrain: exaggeration property is deprecated pls use style.exaggeration instead!`);
11
11
  style = {
12
12
  exaggeration: props.exaggeration,
13
13
  ...style
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@rnmapbox/maps",
3
3
  "description": "A Mapbox react native module for creating custom maps",
4
- "version": "10.0.0-rc.6",
4
+ "version": "10.0.0-rc.8",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
package/plugin/install.md CHANGED
@@ -50,6 +50,23 @@ For `mapbox` or `mapbox-gl` you'll need to provide `RNMapboxMapsDownloadToken` a
50
50
  }
51
51
  ```
52
52
 
53
+ If you want to show the user's current location on the map with the [UserLocation](../docs/UserLocation.md) component, you can use the [expo-location](https://docs.expo.dev/versions/latest/sdk/location/) plugin to configure the required `NSLocationWhenInUseUsageDescription` property. Install the plugin with `npx expo install expo-location` and add its config plugin to the plugins array of your `app.{json,config.js,config.ts}`:
54
+
55
+ ```json
56
+ {
57
+ "expo": {
58
+ "plugins": [
59
+ [
60
+ "expo-location",
61
+ {
62
+ "locationWhenInUsePermission": "Show current location on map."
63
+ }
64
+ ]
65
+ ]
66
+ }
67
+ }
68
+ ```
69
+
53
70
  Next, rebuild your app as described in the ["Adding custom native code"](https://docs.expo.io/workflow/customizing/) guide.
54
71
 
55
72
  ### Advanced Configuration
@@ -33,7 +33,7 @@ export const Terrain = memo((props: Props) => {
33
33
 
34
34
  if (props.exaggeration) {
35
35
  console.warn(
36
- `Tarrain: exaggeration property is deprecated pls use style.exaggeration instead!`,
36
+ `Terrain: exaggeration property is deprecated pls use style.exaggeration instead!`,
37
37
  );
38
38
  style = { exaggeration: props.exaggeration, ...style };
39
39
  }
@@ -1,62 +0,0 @@
1
- package com.mapbox.rctmgl.events;
2
-
3
- import android.view.View;
4
-
5
- import com.facebook.react.bridge.Arguments;
6
- import com.facebook.react.bridge.WritableMap;
7
-
8
- abstract public class AbstractEvent implements IEvent {
9
- private int mTagID;
10
- private String mEventType;
11
- private long mTimestamp;
12
-
13
- public AbstractEvent(String eventType) {
14
- this(null, eventType);
15
- }
16
-
17
- public AbstractEvent(View view, String eventType) {
18
- mEventType = eventType;
19
-
20
- if (view != null) {
21
- mTagID = view.getId();
22
- }
23
-
24
- mTimestamp = System.currentTimeMillis();
25
- }
26
-
27
- public int getID() {
28
- return mTagID;
29
- }
30
-
31
- public String getType() {
32
- return mEventType;
33
- }
34
-
35
- public boolean equals(IEvent event) {
36
- return getKey().equals(event.getKey()) && mEventType.equals(event.getType());
37
- }
38
-
39
- public WritableMap getPayload() {
40
- return Arguments.createMap();
41
- }
42
-
43
- public long getTimestamp() {
44
- return mTimestamp;
45
- }
46
-
47
- public WritableMap toJSON() {
48
- WritableMap map = Arguments.createMap();
49
- map.putString("type", getType());
50
-
51
- WritableMap payloadClone = Arguments.createMap();
52
- payloadClone.merge(getPayload());
53
- map.putMap("payload", payloadClone);
54
- return map;
55
- }
56
-
57
- @Override
58
- public boolean canCoalesce() {
59
- // default behavior of com.facebook.react.uimanager.events.Event
60
- return true;
61
- }
62
- }
@@ -1,18 +0,0 @@
1
- package com.mapbox.rctmgl.events;
2
-
3
- import com.facebook.react.bridge.WritableMap;
4
-
5
- /**
6
- * Created by nickitaliano on 8/23/17.
7
- */
8
-
9
- public interface IEvent {
10
- int getID();
11
- String getKey();
12
- String getType();
13
- long getTimestamp();
14
- boolean equals(IEvent event);
15
- boolean canCoalesce();
16
- WritableMap getPayload();
17
- WritableMap toJSON();
18
- }
@@ -1,51 +0,0 @@
1
- package com.mapbox.rctmgl.events.constants;
2
-
3
- public class EventTypes {
4
- // map event types
5
- public static final String MAP_CLICK = "press";
6
- public static final String MAP_LONG_CLICK = "longpress";
7
- public static final String MAP_USER_TRACKING_MODE_CHANGE = "usertrackingmodechange";
8
-
9
- public static final String REGION_WILL_CHANGE = "regionwillchange";
10
- public static final String REGION_IS_CHANGING = "regionischanging"; // deprecated
11
- public static final String CAMERA_CHANGED = "camerachanged";
12
- public static final String REGION_DID_CHANGE = "regiondidchange";
13
- public static final String MAP_IDLE = "mapidle";
14
- public static final String USER_LOCATION_UPDATED = "userlocationdupdated";
15
-
16
-
17
-
18
- public static final String WILL_START_LOADING_MAP = "willstartloadingmap";
19
- public static final String DID_FINISH_LOADING_MAP = "didfinishloadingmap";
20
- public static final String DID_FAIL_LOADING_MAP = "didfailloadingmap";
21
-
22
- public static final String WILL_START_RENDERING_FRAME = "willstartrenderingframe";
23
- public static final String DID_FINISH_RENDERING_FRAME = "didfinishrenderingframe";
24
- public static final String DID_FINISH_RENDERING_FRAME_FULLY = "didfinishrenderingframefully";
25
-
26
- public static final String WILL_START_RENDERING_MAP = "willstartrenderingmap";
27
- public static final String DID_FINISH_RENDERING_MAP = "didfinishrenderingmap";
28
- public static final String DID_FINISH_RENDERING_MAP_FULLY = "didfinishrenderingmapfully";
29
-
30
- public static final String DID_FINISH_LOADING_STYLE = "didfinishloadingstyle";
31
-
32
- // point annotation event types
33
- public static final String ANNOTATION_SELECTED = "annotationselected";
34
- public static final String ANNOTATION_DESELECTED = "annotationdeselected";
35
- public static final String ANNOTATION_DRAG_START = "annotationdragstart";
36
- public static final String ANNOTATION_DRAG = "annotationdrag";
37
- public static final String ANNOTATION_DRAG_END = "annotationdragend";
38
-
39
- // offline event types
40
- public static final String OFFLINE_ERROR = "offlineerror";
41
- public static final String OFFLINE_TILE_LIMIT = "offlinetilelimit";
42
- public static final String OFFLINE_STATUS = "offlinestatus";
43
-
44
- // shape source event types
45
- public static final String SHAPE_SOURCE_LAYER_CLICK = "shapesourcelayerpress";
46
- public static final String VECTOR_SOURCE_LAYER_CLICK = "vectorsourcelayerpress";
47
- public static final String RASTER_SOURCE_LAYER_CLICK = "rastersourcelayerpress";
48
-
49
- // image missing event type
50
- public static final String IMAGES_MISSING = "imagesmissing";
51
- }