@rnmapbox/maps 10.2.7 → 10.2.9

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 (125) hide show
  1. package/android/build.gradle +9 -1
  2. package/android/src/main/java/com/rnmapbox/rnmbx/RNMBXPackage.kt +10 -0
  3. package/android/src/main/java/com/rnmapbox/rnmbx/components/location/RNMBXCustomLocationProvider.kt +7 -0
  4. package/android/src/main/java/com/rnmapbox/rnmbx/components/mapview/RNMBXMapView.kt +7 -1
  5. package/android/src/main/java/com/rnmapbox/rnmbx/components/styles/RNMBXStyleFactory.kt +180 -0
  6. package/android/src/main/java/com/rnmapbox/rnmbx/components/styles/RNMBXStyleValue.kt +4 -0
  7. package/android/src/main/java/com/rnmapbox/rnmbx/events/MapSteadyEvent.kt +50 -0
  8. package/android/src/main/java/com/rnmapbox/rnmbx/events/RNMBXCameraGestureObserver.kt +296 -0
  9. package/android/src/main/java/com/rnmapbox/rnmbx/events/RNMBXCameraGestureObserverManager.kt +74 -0
  10. package/android/src/main/java/com/rnmapbox/rnmbx/modules/RNMBXModule.kt +2 -2
  11. package/android/src/main/java/com/rnmapbox/rnmbx/modules/RNMBXOfflineModuleLegacy.kt +10 -0
  12. package/android/src/main/mapbox-v11-compat/v10/com/mapbox/maps/extension/style/layers/generated/RasterParticleLayer.kt +58 -0
  13. package/android/src/main/mapbox-v11-compat/v10/com/mapbox/maps/extension/style/sources/generated/RasterArraySource.kt +20 -0
  14. package/android/src/main/mapbox-v11-compat/v10/com/rnmapbox/rnmbx/components/styles/layers/RNMBXRasterParticleLayer.kt +22 -0
  15. package/android/src/main/mapbox-v11-compat/v10/com/rnmapbox/rnmbx/components/styles/layers/RNMBXRasterParticleLayerManager.kt +59 -0
  16. package/android/src/main/mapbox-v11-compat/v10/com/rnmapbox/rnmbx/components/styles/sources/RNMBXRasterArraySource.kt +16 -0
  17. package/android/src/main/mapbox-v11-compat/v10/com/rnmapbox/rnmbx/components/styles/sources/RNMBXRasterArraySourceManager.kt +59 -0
  18. package/android/src/main/mapbox-v11-compat/v10/com/rnmapbox/rnmbx/v11compat/StyleFactory.kt +45 -0
  19. package/android/src/main/mapbox-v11-compat/v11/com/rnmapbox/rnmbx/components/styles/layers/RNMBXRasterParticleLayer.kt +38 -0
  20. package/android/src/main/mapbox-v11-compat/v11/com/rnmapbox/rnmbx/components/styles/layers/RNMBXRasterParticleLayerManager.kt +85 -0
  21. package/android/src/main/mapbox-v11-compat/v11/com/rnmapbox/rnmbx/components/styles/sources/RNMBXRasterArraySource.kt +41 -0
  22. package/android/src/main/mapbox-v11-compat/v11/com/rnmapbox/rnmbx/components/styles/sources/RNMBXRasterArraySourceManager.kt +76 -0
  23. package/android/src/main/old-arch/com/facebook/react/viewmanagers/RNMBXCameraGestureObserverManagerDelegate.java +39 -0
  24. package/android/src/main/old-arch/com/facebook/react/viewmanagers/RNMBXCameraGestureObserverManagerInterface.java +18 -0
  25. package/android/src/main/old-arch/com/facebook/react/viewmanagers/RNMBXRasterArraySourceManagerDelegate.java +54 -0
  26. package/android/src/main/old-arch/com/facebook/react/viewmanagers/RNMBXRasterArraySourceManagerInterface.java +23 -0
  27. package/android/src/main/old-arch/com/facebook/react/viewmanagers/RNMBXRasterParticleLayerManagerDelegate.java +66 -0
  28. package/android/src/main/old-arch/com/facebook/react/viewmanagers/RNMBXRasterParticleLayerManagerInterface.java +27 -0
  29. package/ios/RNMBX/Offline/RNMBXOfflineModuleLegacy.m +2 -0
  30. package/ios/RNMBX/Offline/RNMBXOfflineModuleLegacy.swift +5 -0
  31. package/ios/RNMBX/RNMBXCamera.swift +88 -17
  32. package/ios/RNMBX/RNMBXCameraGestureObserver.swift +218 -0
  33. package/ios/RNMBX/RNMBXCameraGestureObserverComponentView.h +15 -0
  34. package/ios/RNMBX/RNMBXCameraGestureObserverComponentView.mm +119 -0
  35. package/ios/RNMBX/RNMBXCameraModule.h +3 -2
  36. package/ios/RNMBX/RNMBXCameraModule.mm +8 -16
  37. package/ios/RNMBX/RNMBXCustomLocationProvider.swift +22 -24
  38. package/ios/RNMBX/RNMBXImageModule.h +3 -2
  39. package/ios/RNMBX/RNMBXImageModule.mm +8 -16
  40. package/ios/RNMBX/RNMBXImages.swift +1 -4
  41. package/ios/RNMBX/RNMBXInteractiveElement.swift +22 -15
  42. package/ios/RNMBX/RNMBXMapView.swift +118 -12
  43. package/ios/RNMBX/RNMBXNativeUserLocation.swift +6 -6
  44. package/ios/RNMBX/RNMBXPointAnnotation.swift +6 -8
  45. package/ios/RNMBX/RNMBXPointAnnotationModule.h +3 -2
  46. package/ios/RNMBX/RNMBXPointAnnotationModule.mm +8 -16
  47. package/ios/RNMBX/RNMBXRasterArraySource.swift +47 -0
  48. package/ios/RNMBX/RNMBXRasterArraySourceComponentView.h +15 -0
  49. package/ios/RNMBX/RNMBXRasterArraySourceComponentView.mm +161 -0
  50. package/ios/RNMBX/RNMBXRasterArraySourceViewManager.swift +16 -0
  51. package/ios/RNMBX/RNMBXRasterParticleLayer.swift +100 -0
  52. package/ios/RNMBX/RNMBXRasterParticleLayerComponentView.h +15 -0
  53. package/ios/RNMBX/RNMBXRasterParticleLayerComponentView.mm +110 -0
  54. package/ios/RNMBX/RNMBXRasterParticleLayerViewManager.swift +17 -0
  55. package/ios/RNMBX/RNMBXShapeSource.swift +5 -4
  56. package/ios/RNMBX/RNMBXShapeSourceModule.h +3 -2
  57. package/ios/RNMBX/RNMBXShapeSourceModule.mm +8 -16
  58. package/ios/RNMBX/RNMBXSource.swift +51 -21
  59. package/ios/RNMBX/RNMBXStyle.swift +152 -27
  60. package/ios/RNMBX/RNMBXStyleValue.swift +27 -0
  61. package/ios/RNMBX/RNMBXViewport.swift +13 -13
  62. package/ios/RNMBX/RNMBXViewportModule.h +3 -2
  63. package/ios/RNMBX/RNMBXViewportModule.mm +8 -16
  64. package/lib/commonjs/plugin/build/withMapbox.js +1 -1
  65. package/lib/commonjs/plugin/src/withMapbox.ts +13 -3
  66. package/lib/module/Mapbox.native.js +4 -0
  67. package/lib/module/Mapbox.native.js.map +1 -1
  68. package/lib/module/RNMBXModule.js.map +1 -1
  69. package/lib/module/components/CameraGestureObserver.js +17 -0
  70. package/lib/module/components/CameraGestureObserver.js.map +1 -0
  71. package/lib/module/components/PointAnnotation.js.map +1 -1
  72. package/lib/module/components/RasterArraySource.js +67 -0
  73. package/lib/module/components/RasterArraySource.js.map +1 -0
  74. package/lib/module/components/RasterParticleLayer.js +40 -0
  75. package/lib/module/components/RasterParticleLayer.js.map +1 -0
  76. package/lib/module/modules/offline/offlineManagerLegacy.js +14 -0
  77. package/lib/module/modules/offline/offlineManagerLegacy.js.map +1 -1
  78. package/lib/module/specs/RNMBXCameraGestureObserverNativeComponent.ts +28 -0
  79. package/lib/module/specs/RNMBXRasterArraySourceNativeComponent.ts +22 -0
  80. package/lib/module/specs/RNMBXRasterParticleLayerNativeComponent.ts +39 -0
  81. package/lib/module/utils/MapboxStyles.js.map +1 -1
  82. package/lib/module/utils/styleMap.js +9 -0
  83. package/lib/module/utils/styleMap.js.map +1 -1
  84. package/lib/typescript/plugin/src/withMapbox.d.ts.map +1 -1
  85. package/lib/typescript/scripts/autogenHelpers/generateCodeWithEjs.d.mts.map +1 -1
  86. package/lib/typescript/scripts/autogenHelpers/globals.d.mts +1 -1
  87. package/lib/typescript/scripts/autogenHelpers/globals.d.mts.map +1 -1
  88. package/lib/typescript/src/Mapbox.native.d.ts +5 -1
  89. package/lib/typescript/src/Mapbox.native.d.ts.map +1 -1
  90. package/lib/typescript/src/RNMBXModule.d.ts.map +1 -1
  91. package/lib/typescript/src/components/CameraGestureObserver.d.ts +27 -0
  92. package/lib/typescript/src/components/CameraGestureObserver.d.ts.map +1 -0
  93. package/lib/typescript/src/components/PointAnnotation.d.ts +1 -1
  94. package/lib/typescript/src/components/PointAnnotation.d.ts.map +1 -1
  95. package/lib/typescript/src/components/RasterArraySource.d.ts +72 -0
  96. package/lib/typescript/src/components/RasterArraySource.d.ts.map +1 -0
  97. package/lib/typescript/src/components/RasterParticleLayer.d.ts +80 -0
  98. package/lib/typescript/src/components/RasterParticleLayer.d.ts.map +1 -0
  99. package/lib/typescript/src/modules/offline/offlineManagerLegacy.d.ts +11 -0
  100. package/lib/typescript/src/modules/offline/offlineManagerLegacy.d.ts.map +1 -1
  101. package/lib/typescript/src/specs/RNMBXCameraGestureObserverNativeComponent.d.ts +20 -0
  102. package/lib/typescript/src/specs/RNMBXCameraGestureObserverNativeComponent.d.ts.map +1 -0
  103. package/lib/typescript/src/specs/RNMBXRasterArraySourceNativeComponent.d.ts +16 -0
  104. package/lib/typescript/src/specs/RNMBXRasterArraySourceNativeComponent.d.ts.map +1 -0
  105. package/lib/typescript/src/specs/RNMBXRasterParticleLayerNativeComponent.d.ts +25 -0
  106. package/lib/typescript/src/specs/RNMBXRasterParticleLayerNativeComponent.d.ts.map +1 -0
  107. package/lib/typescript/src/utils/MapboxStyles.d.ts +44 -2
  108. package/lib/typescript/src/utils/MapboxStyles.d.ts.map +1 -1
  109. package/lib/typescript/src/utils/styleMap.d.ts.map +1 -1
  110. package/package.json +19 -2
  111. package/plugin/build/withMapbox.js +1 -1
  112. package/plugin/src/withMapbox.ts +13 -3
  113. package/rnmapbox-maps.podspec +1 -1
  114. package/src/Mapbox.native.ts +5 -0
  115. package/src/RNMBXModule.ts +1 -4
  116. package/src/components/CameraGestureObserver.tsx +37 -0
  117. package/src/components/PointAnnotation.tsx +2 -2
  118. package/src/components/RasterArraySource.tsx +134 -0
  119. package/src/components/RasterParticleLayer.tsx +117 -0
  120. package/src/modules/offline/offlineManagerLegacy.ts +14 -0
  121. package/src/specs/RNMBXCameraGestureObserverNativeComponent.ts +28 -0
  122. package/src/specs/RNMBXRasterArraySourceNativeComponent.ts +22 -0
  123. package/src/specs/RNMBXRasterParticleLayerNativeComponent.ts +39 -0
  124. package/src/utils/MapboxStyles.ts +47 -1
  125. package/src/utils/styleMap.ts +10 -0
@@ -1,5 +1,13 @@
1
1
  def defaultMapboxMapsImpl = "mapbox"
2
- def defaultMapboxMapsVersion = "11.15.2"
2
+
3
+ def getDefaultMapboxMapsVersion() {
4
+ def packageJson = new groovy.json.JsonSlurper().parseText(
5
+ new File(projectDir.getPath(), "../package.json").text
6
+ )
7
+ return packageJson.mapbox.android
8
+ }
9
+
10
+ def defaultMapboxMapsVersion = getDefaultMapboxMapsVersion()
3
11
 
4
12
  def safeExtGet(prop, fallback) {
5
13
  rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback
@@ -34,17 +34,20 @@ import com.rnmapbox.rnmbx.components.styles.layers.RNMBXHeatmapLayerManager
34
34
  import com.rnmapbox.rnmbx.components.styles.layers.RNMBXLineLayerManager
35
35
  import com.rnmapbox.rnmbx.components.styles.layers.RNMBXModelLayerManager
36
36
  import com.rnmapbox.rnmbx.components.styles.layers.RNMBXRasterLayerManager
37
+ import com.rnmapbox.rnmbx.components.styles.layers.RNMBXRasterParticleLayerManager
37
38
  import com.rnmapbox.rnmbx.components.styles.layers.RNMBXSkyLayerManager
38
39
  import com.rnmapbox.rnmbx.components.styles.layers.RNMBXSymbolLayerManager
39
40
  import com.rnmapbox.rnmbx.components.styles.light.RNMBXLightManager
40
41
  import com.rnmapbox.rnmbx.components.styles.model.RNMBXModelsManager
41
42
  import com.rnmapbox.rnmbx.components.styles.sources.RNMBXImageSourceManager
43
+ import com.rnmapbox.rnmbx.components.styles.sources.RNMBXRasterArraySourceManager
42
44
  import com.rnmapbox.rnmbx.components.styles.sources.RNMBXRasterDemSourceManager
43
45
  import com.rnmapbox.rnmbx.components.styles.sources.RNMBXRasterSourceManager
44
46
  import com.rnmapbox.rnmbx.components.styles.sources.RNMBXShapeSourceManager
45
47
  import com.rnmapbox.rnmbx.components.styles.sources.RNMBXShapeSourceModule
46
48
  import com.rnmapbox.rnmbx.components.styles.sources.RNMBXVectorSourceManager
47
49
  import com.rnmapbox.rnmbx.components.styles.terrain.RNMBXTerrainManager
50
+ import com.rnmapbox.rnmbx.events.RNMBXCameraGestureObserverManager
48
51
  import com.rnmapbox.rnmbx.modules.RNMBXLocationModule
49
52
  import com.rnmapbox.rnmbx.modules.RNMBXLogging
50
53
  import com.rnmapbox.rnmbx.modules.RNMBXModule
@@ -123,6 +126,7 @@ class RNMBXPackage : TurboReactPackage() {
123
126
  managers.add(RNMBXMapViewManager(reactApplicationContext, getViewTagResolver(reactApplicationContext, "RNMBXMapViewManager")))
124
127
  managers.add(RNMBXStyleImportManager(reactApplicationContext))
125
128
  managers.add(RNMBXModelsManager(reactApplicationContext))
129
+ managers.add(RNMBXCameraGestureObserverManager(reactApplicationContext))
126
130
 
127
131
  // annotations
128
132
  managers.add(RNMBXMarkerViewManager(reactApplicationContext))
@@ -140,6 +144,9 @@ class RNMBXPackage : TurboReactPackage() {
140
144
  ))
141
145
  managers.add(RNMBXRasterDemSourceManager(reactApplicationContext))
142
146
  managers.add(RNMBXRasterSourceManager(reactApplicationContext))
147
+ if (RNMBXRasterArraySourceManager.isImplemented) {
148
+ managers.add(RNMBXRasterArraySourceManager(reactApplicationContext))
149
+ }
143
150
  managers.add(RNMBXImageSourceManager())
144
151
 
145
152
  // images
@@ -154,6 +161,9 @@ class RNMBXPackage : TurboReactPackage() {
154
161
  managers.add(RNMBXCircleLayerManager())
155
162
  managers.add(RNMBXSymbolLayerManager())
156
163
  managers.add(RNMBXRasterLayerManager())
164
+ if (RNMBXRasterParticleLayerManager.isImplemented) {
165
+ managers.add(RNMBXRasterParticleLayerManager())
166
+ }
157
167
  managers.add(RNMBXSkyLayerManager())
158
168
  managers.add(RNMBXTerrainManager())
159
169
  managers.add(RNMBXAtmosphereManager())
@@ -87,6 +87,13 @@ class RNMBXCustomLocationProvider(context: Context) : AbstractMapFeature(context
87
87
  if (customLocationProvider == null) {
88
88
  customLocationProvider = object : LocationProvider {
89
89
  override fun registerLocationConsumer(locationConsumer: LocationConsumer) {
90
+ heading?.let {
91
+ locationConsumer.onBearingUpdated(it)
92
+ }
93
+ coordinate?.let {
94
+ val point = Point.fromLngLat(it.first, it.second)
95
+ locationConsumer.onLocationUpdated(point)
96
+ }
90
97
  locationConsumers.add(locationConsumer)
91
98
  }
92
99
 
@@ -917,7 +917,13 @@ open class RNMBXMapView(private val mContext: Context, var mManager: RNMBXMapVie
917
917
  Logger.e("queryRenderedFeaturesAtPoint", "mapbox map is null")
918
918
  return
919
919
  }
920
- val screenCoordinate = ScreenCoordinate(point.x.toDouble(), point.y.toDouble())
920
+ // JS sends point values in DIP (see getPointInView which divides by display density),
921
+ // but Mapbox core expects screen pixel coordinates. Convert back to px here.
922
+ val density: Float = getDisplayDensity()
923
+ val screenCoordinate = ScreenCoordinate(
924
+ (point.x * density).toDouble(),
925
+ (point.y * density).toDouble()
926
+ )
921
927
  val queryGeometry = RenderedQueryGeometry(screenCoordinate)
922
928
  val layers = layerIDs?.takeUnless { it.isEmpty() } ?: null;
923
929
  val queryOptions = RenderedQueryOptions(layers, filter)
@@ -13,6 +13,7 @@ import com.mapbox.maps.extension.style.layers.generated.SkyLayer
13
13
  // import com.mapbox.maps.extension.style.layers.generated.PropertyFactory
14
14
  // import com.mapbox.maps.extension.style.layers.generated.PropertyValue
15
15
  import com.mapbox.maps.extension.style.layers.generated.RasterLayer
16
+ import com.mapbox.maps.extension.style.layers.generated.RasterParticleLayer
16
17
  import com.mapbox.maps.extension.style.layers.generated.SymbolLayer
17
18
  import com.mapbox.maps.extension.style.layers.generated.HeatmapLayer
18
19
  import com.mapbox.maps.extension.style.layers.generated.HillshadeLayer
@@ -704,6 +705,44 @@ object RNMBXStyleFactory {
704
705
  }
705
706
  }
706
707
  }
708
+ fun setRasterParticleLayerStyle(layer: RasterParticleLayer, style: RNMBXStyle ) {
709
+ val styleKeys = style.allStyleKeys
710
+
711
+ if (styleKeys.isEmpty()) {
712
+ return
713
+ }
714
+
715
+ for (styleKey in styleKeys) {
716
+ try {
717
+ val styleValue = style.getStyleValueForKey(styleKey)
718
+
719
+ when (styleKey) {
720
+ "visibility" ->
721
+ setVisibility(layer, styleValue)
722
+ "rasterParticleArrayBand" ->
723
+ setRasterParticleArrayBand(layer, styleValue)
724
+ "rasterParticleCount" ->
725
+ setRasterParticleCount(layer, styleValue)
726
+ "rasterParticleColor" ->
727
+ setRasterParticleColor(layer, styleValue)
728
+ "rasterParticleMaxSpeed" ->
729
+ setRasterParticleMaxSpeed(layer, styleValue)
730
+ "rasterParticleSpeedFactor" ->
731
+ setRasterParticleSpeedFactor(layer, styleValue)
732
+ "rasterParticleSpeedFactorTransition" ->
733
+ setRasterParticleSpeedFactorTransition(layer, styleValue)
734
+ "rasterParticleFadeOpacityFactor" ->
735
+ setRasterParticleFadeOpacityFactor(layer, styleValue)
736
+ "rasterParticleFadeOpacityFactorTransition" ->
737
+ setRasterParticleFadeOpacityFactorTransition(layer, styleValue)
738
+ "rasterParticleResetRateFactor" ->
739
+ setRasterParticleResetRateFactor(layer, styleValue)
740
+ }
741
+ } catch (e: MapboxStyleException) {
742
+ Logger.e(LOG_TAG, "Failed to update: $styleKey ${e.message}")
743
+ }
744
+ }
745
+ }
707
746
  fun setHillshadeLayerStyle(layer: HillshadeLayer, style: RNMBXStyle ) {
708
747
  val styleKeys = style.allStyleKeys
709
748
 
@@ -4354,6 +4393,147 @@ object RNMBXStyleFactory {
4354
4393
  }
4355
4394
  }
4356
4395
 
4396
+ fun setVisibility(layer: RasterParticleLayer, styleValue: RNMBXStyleValue ) {
4397
+ layer.visibility(Visibility.valueOf(styleValue.getEnumName()));
4398
+ }
4399
+
4400
+ fun setRasterParticleArrayBand(layer: RasterParticleLayer, styleValue: RNMBXStyleValue ) {
4401
+ if (styleValue.isExpression()) {
4402
+ val expression = styleValue.getExpression()
4403
+ if (expression != null) {
4404
+ layer.rasterParticleArrayBand(expression)
4405
+ } else {
4406
+ Logger.e("RNMBXRasterParticle", "Expression for rasterParticleArrayBand is null")
4407
+ }
4408
+ } else {
4409
+ val value = styleValue.getString(VALUE_KEY)
4410
+ if (value != null) {
4411
+ layer.rasterParticleArrayBand(value)
4412
+ } else {
4413
+ Logger.e("RNMBXRasterParticle", "value for rasterParticleArrayBand is null")
4414
+ }
4415
+ }
4416
+ }
4417
+
4418
+ fun setRasterParticleCount(layer: RasterParticleLayer, styleValue: RNMBXStyleValue ) {
4419
+ if (styleValue.isExpression()) {
4420
+ val expression = styleValue.getExpression()
4421
+ if (expression != null) {
4422
+ layer.rasterParticleCount(expression)
4423
+ } else {
4424
+ Logger.e("RNMBXRasterParticle", "Expression for rasterParticleCount is null")
4425
+ }
4426
+ } else {
4427
+ val value = styleValue.getLong(VALUE_KEY)
4428
+ if (value != null) {
4429
+ layer.rasterParticleCount(value)
4430
+ } else {
4431
+ Logger.e("RNMBXRasterParticle", "value for rasterParticleCount is null")
4432
+ }
4433
+ }
4434
+ }
4435
+
4436
+ fun setRasterParticleColor(layer: RasterParticleLayer, styleValue: RNMBXStyleValue ) {
4437
+ if (styleValue.isExpression()) {
4438
+ val expression = styleValue.getExpression()
4439
+ if (expression != null) {
4440
+ layer.rasterParticleColor(expression)
4441
+ } else {
4442
+ Logger.e("RNMBXRasterParticle", "Expression for rasterParticleColor is null")
4443
+ }
4444
+ } else {
4445
+ layer.rasterParticleColor(styleValue.getIntExpression(VALUE_KEY))
4446
+ }
4447
+ }
4448
+
4449
+ fun setRasterParticleMaxSpeed(layer: RasterParticleLayer, styleValue: RNMBXStyleValue ) {
4450
+ if (styleValue.isExpression()) {
4451
+ val expression = styleValue.getExpression()
4452
+ if (expression != null) {
4453
+ layer.rasterParticleMaxSpeed(expression)
4454
+ } else {
4455
+ Logger.e("RNMBXRasterParticle", "Expression for rasterParticleMaxSpeed is null")
4456
+ }
4457
+ } else {
4458
+ val value = styleValue.getDouble(VALUE_KEY)
4459
+ if (value != null) {
4460
+ layer.rasterParticleMaxSpeed(value)
4461
+ } else {
4462
+ Logger.e("RNMBXRasterParticle", "value for rasterParticleMaxSpeed is null")
4463
+ }
4464
+ }
4465
+ }
4466
+
4467
+ fun setRasterParticleSpeedFactor(layer: RasterParticleLayer, styleValue: RNMBXStyleValue ) {
4468
+ if (styleValue.isExpression()) {
4469
+ val expression = styleValue.getExpression()
4470
+ if (expression != null) {
4471
+ layer.rasterParticleSpeedFactor(expression)
4472
+ } else {
4473
+ Logger.e("RNMBXRasterParticle", "Expression for rasterParticleSpeedFactor is null")
4474
+ }
4475
+ } else {
4476
+ val value = styleValue.getDouble(VALUE_KEY)
4477
+ if (value != null) {
4478
+ layer.rasterParticleSpeedFactor(value)
4479
+ } else {
4480
+ Logger.e("RNMBXRasterParticle", "value for rasterParticleSpeedFactor is null")
4481
+ }
4482
+ }
4483
+ }
4484
+
4485
+
4486
+ fun setRasterParticleSpeedFactorTransition(layer: RasterParticleLayer, styleValue: RNMBXStyleValue) {
4487
+ val transition = styleValue.transition
4488
+ if (transition != null) {
4489
+ layer.rasterParticleSpeedFactorTransition(transition);
4490
+ }
4491
+ }
4492
+
4493
+ fun setRasterParticleFadeOpacityFactor(layer: RasterParticleLayer, styleValue: RNMBXStyleValue ) {
4494
+ if (styleValue.isExpression()) {
4495
+ val expression = styleValue.getExpression()
4496
+ if (expression != null) {
4497
+ layer.rasterParticleFadeOpacityFactor(expression)
4498
+ } else {
4499
+ Logger.e("RNMBXRasterParticle", "Expression for rasterParticleFadeOpacityFactor is null")
4500
+ }
4501
+ } else {
4502
+ val value = styleValue.getDouble(VALUE_KEY)
4503
+ if (value != null) {
4504
+ layer.rasterParticleFadeOpacityFactor(value)
4505
+ } else {
4506
+ Logger.e("RNMBXRasterParticle", "value for rasterParticleFadeOpacityFactor is null")
4507
+ }
4508
+ }
4509
+ }
4510
+
4511
+
4512
+ fun setRasterParticleFadeOpacityFactorTransition(layer: RasterParticleLayer, styleValue: RNMBXStyleValue) {
4513
+ val transition = styleValue.transition
4514
+ if (transition != null) {
4515
+ layer.rasterParticleFadeOpacityFactorTransition(transition);
4516
+ }
4517
+ }
4518
+
4519
+ fun setRasterParticleResetRateFactor(layer: RasterParticleLayer, styleValue: RNMBXStyleValue ) {
4520
+ if (styleValue.isExpression()) {
4521
+ val expression = styleValue.getExpression()
4522
+ if (expression != null) {
4523
+ layer.rasterParticleResetRateFactor(expression)
4524
+ } else {
4525
+ Logger.e("RNMBXRasterParticle", "Expression for rasterParticleResetRateFactor is null")
4526
+ }
4527
+ } else {
4528
+ val value = styleValue.getDouble(VALUE_KEY)
4529
+ if (value != null) {
4530
+ layer.rasterParticleResetRateFactor(value)
4531
+ } else {
4532
+ Logger.e("RNMBXRasterParticle", "value for rasterParticleResetRateFactor is null")
4533
+ }
4534
+ }
4535
+ }
4536
+
4357
4537
  fun setVisibility(layer: HillshadeLayer, styleValue: RNMBXStyleValue ) {
4358
4538
  layer.visibility(Visibility.valueOf(styleValue.getEnumName()));
4359
4539
  }
@@ -33,6 +33,10 @@ class RNMBXStyleValue(key: String?, config: ReadableMap) {
33
33
  return mPayload!!.getInt(key!!)
34
34
  }
35
35
 
36
+ fun getLong(key: String?): Long {
37
+ return mPayload!!.getInt(key!!).toLong()
38
+ }
39
+
36
40
  fun getIntExpression(key: String?): Expression {
37
41
  return Expression.literal(mPayload!!.getInt(key!!).toLong())
38
42
  }
@@ -0,0 +1,50 @@
1
+ package com.rnmapbox.rnmbx.events
2
+
3
+ import android.view.View
4
+ import com.facebook.react.bridge.Arguments
5
+ import com.facebook.react.bridge.WritableMap
6
+
7
+ /**
8
+ * Direct event for CameraGestureObserver -> onMapSteady
9
+ * JS registrationName: onMapSteady
10
+ * Native event name (key): topOnMapSteady
11
+ */
12
+ class MapSteadyEvent(
13
+ view: View?,
14
+ private val reason: String,
15
+ private val idleDurationMs: Double?,
16
+ private val lastGestureType: String?
17
+ ) : AbstractEvent(view, "mapSteady") {
18
+ override val key: String
19
+ get() = "topOnMapSteady"
20
+
21
+ override val payload: WritableMap
22
+ get() = Arguments.createMap().apply {
23
+ putString("reason", reason)
24
+ if (idleDurationMs != null) {
25
+ putDouble("idleDurationMs", idleDurationMs)
26
+ } else {
27
+ putNull("idleDurationMs")
28
+ }
29
+ if (lastGestureType != null) {
30
+ putString("lastGestureType", lastGestureType)
31
+ } else {
32
+ putNull("lastGestureType")
33
+ }
34
+ putDouble("timestamp", System.currentTimeMillis().toDouble())
35
+ }
36
+
37
+ override fun canCoalesce(): Boolean {
38
+ // Do not coalesce - each steady/timeout event is significant
39
+ return false
40
+ }
41
+
42
+ companion object {
43
+ fun make(
44
+ view: View,
45
+ reason: String,
46
+ idleDurationMs: Double?,
47
+ lastGestureType: String?
48
+ ): MapSteadyEvent = MapSteadyEvent(view, reason, idleDurationMs, lastGestureType)
49
+ }
50
+ }
@@ -0,0 +1,296 @@
1
+ package com.rnmapbox.rnmbx.events
2
+
3
+ import android.animation.ValueAnimator
4
+ import android.content.Context
5
+ import android.os.Handler
6
+ import android.os.Looper
7
+ import android.util.Log
8
+ import com.mapbox.android.gestures.MoveGestureDetector
9
+ import com.mapbox.android.gestures.RotateGestureDetector
10
+ import com.mapbox.android.gestures.ShoveGestureDetector
11
+ import com.mapbox.android.gestures.StandardScaleGestureDetector
12
+ import com.mapbox.maps.plugin.animation.CameraAnimationsLifecycleListener
13
+ import com.mapbox.maps.plugin.animation.CameraAnimatorType
14
+ import com.mapbox.maps.plugin.gestures.OnMoveListener
15
+ import com.mapbox.maps.plugin.gestures.OnRotateListener
16
+ import com.mapbox.maps.plugin.gestures.OnScaleListener
17
+ import com.mapbox.maps.plugin.gestures.OnShoveListener
18
+ import com.rnmapbox.rnmbx.components.AbstractMapFeature
19
+ import com.rnmapbox.rnmbx.components.RemovalReason
20
+ import com.rnmapbox.rnmbx.components.mapview.RNMBXMapView
21
+
22
+ class RNMBXCameraGestureObserver(
23
+ private val mContext: Context,
24
+ private val mManager: RNMBXCameraGestureObserverManager
25
+ ) : AbstractMapFeature(mContext) {
26
+
27
+ var hasOnMapSteady: Boolean = false
28
+ var quietPeriodMs: Double? = null
29
+ var maxIntervalMs: Double? = null
30
+
31
+ override var requiresStyleLoad: Boolean = false
32
+
33
+ private val handler = Handler(Looper.getMainLooper())
34
+ private var activeAnimations: Int = 0
35
+ private var isGestureActive: Boolean = false
36
+ private var lastGestureType: String? = null
37
+ private var lastTransitionEndedAtMs: Double? = null
38
+ private var quietRunnable: Runnable? = null
39
+ private var timeoutRunnable: Runnable? = null
40
+ private var emittedForCurrentActivity: Boolean = false
41
+
42
+ private val quietMs: Double get() = quietPeriodMs ?: 200.0
43
+ private val maxMs: Double? get() = maxIntervalMs
44
+
45
+ private fun nowMs(): Double = System.currentTimeMillis().toDouble()
46
+ private fun timestamp(): Double = nowMs()
47
+
48
+ private val canEmitSteady: Boolean
49
+ get() = activeAnimations == 0 && !isGestureActive && lastTransitionEndedAtMs != null
50
+
51
+ private fun normalizeGestureType(type: String): String {
52
+ return when (type) {
53
+ "move" -> "pan"
54
+ "scale" -> "pinch"
55
+ "rotate" -> "rotate"
56
+ "shove" -> "pitch"
57
+ else -> type
58
+ }
59
+ }
60
+
61
+ private fun debugLog(message: String) {
62
+ Log.d(
63
+ LOG_TAG,
64
+ "$message; activeAnimations=$activeAnimations isGestureActive=$isGestureActive lastTransitionEnd=${lastTransitionEndedAtMs ?: -1}"
65
+ )
66
+ }
67
+
68
+ private fun scheduleTimer(delay: Double, task: Runnable): Runnable {
69
+ handler.removeCallbacks(task)
70
+ if (delay > 0) {
71
+ handler.postDelayed(task, delay.toLong())
72
+ }
73
+ return task
74
+ }
75
+
76
+ private fun cancelQuietTimer() {
77
+ quietRunnable?.let { handler.removeCallbacks(it) }
78
+ quietRunnable = null
79
+ }
80
+
81
+ private fun cancelTimeoutTimer() {
82
+ timeoutRunnable?.let { handler.removeCallbacks(it) }
83
+ timeoutRunnable = null
84
+ }
85
+
86
+ private fun scheduleQuietCheck() {
87
+ val delay = quietMs
88
+ if (delay <= 0) {
89
+ cancelQuietTimer()
90
+ maybeEmitSteady()
91
+ return
92
+ }
93
+ debugLog("scheduleQuietCheck in ${delay.toInt()}ms")
94
+ val runnable = Runnable {
95
+ debugLog("quiet timer fired")
96
+ maybeEmitSteady()
97
+ }
98
+ quietRunnable = scheduleTimer(delay, runnable)
99
+ }
100
+
101
+ private fun scheduleTimeout() {
102
+ val delay = maxMs ?: return
103
+ val runnable = Runnable {
104
+ emitTimeout()
105
+ }
106
+ timeoutRunnable = scheduleTimer(delay, runnable)
107
+ }
108
+
109
+ private fun markActivity(gestureType: String? = null) {
110
+ if (gestureType != null) lastGestureType = gestureType
111
+ emittedForCurrentActivity = false
112
+ scheduleQuietCheck()
113
+ scheduleTimeout()
114
+ }
115
+
116
+ private fun maybeEmitSteady() {
117
+ if (!canEmitSteady) return
118
+ val lastEnd = lastTransitionEndedAtMs ?: return
119
+ val sinceEnd = nowMs() - lastEnd
120
+ if (sinceEnd < quietMs) return
121
+ emitSteady(sinceEnd)
122
+ }
123
+
124
+ private fun emitSteady(idleDurationMs: Double) {
125
+ if (emittedForCurrentActivity) return
126
+ cancelQuietTimer()
127
+ cancelTimeoutTimer()
128
+ val gesture = lastGestureType
129
+ debugLog("EMIT steady idleDurationMs=$idleDurationMs lastGestureType=$gesture")
130
+ mManager.handleEvent(
131
+ MapSteadyEvent.make(this, "steady", idleDurationMs, gesture)
132
+ )
133
+ lastGestureType = null
134
+ emittedForCurrentActivity = true
135
+ }
136
+
137
+ private fun emitTimeout() {
138
+ cancelQuietTimer()
139
+ debugLog("EMIT timeout lastGestureType=$lastGestureType")
140
+ mManager.handleEvent(
141
+ MapSteadyEvent.make(this, "timeout", null, lastGestureType)
142
+ )
143
+ scheduleTimeout()
144
+ }
145
+
146
+ override fun addToMap(mapView: RNMBXMapView) {
147
+ super.addToMap(mapView)
148
+
149
+ if (!hasOnMapSteady) return
150
+
151
+ mapView.getMapAsync { mapboxMap ->
152
+ // Camera animations lifecycle
153
+ mapboxMap.cameraAnimationsPlugin {
154
+ this.addCameraAnimationsLifecycleListener(object : CameraAnimationsLifecycleListener {
155
+ override fun onAnimatorStarting(
156
+ type: CameraAnimatorType,
157
+ animator: ValueAnimator,
158
+ owner: String?
159
+ ) {
160
+ if (owner != "Maps-Gestures") return
161
+ activeAnimations++
162
+ lastTransitionEndedAtMs = null
163
+ markActivity()
164
+ debugLog("camera animator started")
165
+ }
166
+
167
+ override fun onAnimatorEnding(
168
+ type: CameraAnimatorType,
169
+ animator: ValueAnimator,
170
+ owner: String?
171
+ ) {
172
+ if (owner != "Maps-Gestures") return
173
+ handleAnimatorEnd()
174
+ }
175
+
176
+ override fun onAnimatorCancelling(
177
+ type: CameraAnimatorType,
178
+ animator: ValueAnimator,
179
+ owner: String?
180
+ ) {
181
+ if (owner != "Maps-Gestures") return
182
+ handleAnimatorEnd()
183
+ }
184
+
185
+ override fun onAnimatorInterrupting(
186
+ type: CameraAnimatorType,
187
+ runningAnimator: ValueAnimator,
188
+ runningAnimatorOwner: String?,
189
+ newAnimator: ValueAnimator,
190
+ newAnimatorOwner: String?
191
+ ) {
192
+ // Interruptions are handled by the ending/starting callbacks
193
+ }
194
+ })
195
+ }
196
+
197
+ // Gesture listeners
198
+ mapboxMap.gesturesPlugin {
199
+ this.addOnMoveListener(object : OnMoveListener {
200
+ override fun onMoveBegin(detector: MoveGestureDetector) {
201
+ handleGestureBegin("move")
202
+ }
203
+
204
+ override fun onMove(detector: MoveGestureDetector): Boolean {
205
+ return false
206
+ }
207
+
208
+ override fun onMoveEnd(detector: MoveGestureDetector) {
209
+ handleGestureEnd("move")
210
+ }
211
+ })
212
+
213
+ this.addOnScaleListener(object : OnScaleListener {
214
+ override fun onScaleBegin(detector: StandardScaleGestureDetector) {
215
+ handleGestureBegin("scale")
216
+ }
217
+
218
+ override fun onScale(detector: StandardScaleGestureDetector) {
219
+ }
220
+
221
+ override fun onScaleEnd(detector: StandardScaleGestureDetector) {
222
+ handleGestureEnd("scale")
223
+ }
224
+ })
225
+
226
+ this.addOnRotateListener(object : OnRotateListener {
227
+ override fun onRotateBegin(detector: RotateGestureDetector) {
228
+ handleGestureBegin("rotate")
229
+ }
230
+
231
+ override fun onRotate(detector: RotateGestureDetector) {
232
+ }
233
+
234
+ override fun onRotateEnd(detector: RotateGestureDetector) {
235
+ handleGestureEnd("rotate")
236
+ }
237
+ })
238
+
239
+ this.addOnShoveListener(object : OnShoveListener {
240
+ override fun onShoveBegin(detector: ShoveGestureDetector) {
241
+ handleGestureBegin("shove")
242
+ }
243
+
244
+ override fun onShove(detector: ShoveGestureDetector) {
245
+ }
246
+
247
+ override fun onShoveEnd(detector: ShoveGestureDetector) {
248
+ handleGestureEnd("shove")
249
+ }
250
+ })
251
+ }
252
+
253
+ debugLog("addToMap and subscribed to gestures")
254
+ }
255
+ }
256
+
257
+ override fun removeFromMap(mapView: RNMBXMapView, reason: RemovalReason): Boolean {
258
+ debugLog("removeFromMap and unsubscribed from gestures")
259
+ cancelQuietTimer()
260
+ cancelTimeoutTimer()
261
+ return super.removeFromMap(mapView, reason)
262
+ }
263
+
264
+ private fun handleAnimatorEnd() {
265
+ activeAnimations--
266
+ if (activeAnimations < 0) {
267
+ Log.w(LOG_TAG, "WARNING: activeAnimations went negative, resetting to 0")
268
+ activeAnimations = 0
269
+ }
270
+ lastTransitionEndedAtMs = nowMs()
271
+ scheduleQuietCheck()
272
+ debugLog("camera animator ended")
273
+ }
274
+
275
+ private fun handleGestureBegin(type: String) {
276
+ isGestureActive = true
277
+ lastGestureType = normalizeGestureType(type)
278
+ lastTransitionEndedAtMs = null
279
+ markActivity(lastGestureType)
280
+ debugLog("gesture didBegin type=$lastGestureType")
281
+ }
282
+
283
+ private fun handleGestureEnd(type: String) {
284
+ lastGestureType = normalizeGestureType(type)
285
+ // On Android, gesture end callbacks fire AFTER animations complete
286
+ // So we can mark the gesture as inactive and transition as ended
287
+ isGestureActive = false
288
+ lastTransitionEndedAtMs = nowMs()
289
+ markActivity(lastGestureType)
290
+ debugLog("gesture didEnd type=$lastGestureType -> isGestureActive=$isGestureActive")
291
+ }
292
+
293
+ companion object {
294
+ const val LOG_TAG = "RNMBXCameraGestureObserver"
295
+ }
296
+ }