react-native-google-maps-plus 1.3.0 → 1.4.1-dev.1

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 (119) hide show
  1. package/android/build.gradle +1 -1
  2. package/android/src/main/java/com/rngooglemapsplus/GoogleMapsViewImpl.kt +50 -161
  3. package/android/src/main/java/com/rngooglemapsplus/LocationHandler.kt +38 -36
  4. package/android/src/main/java/com/rngooglemapsplus/MapCircleBuilder.kt +33 -9
  5. package/android/src/main/java/com/rngooglemapsplus/MapMarkerBuilder.kt +73 -18
  6. package/android/src/main/java/com/rngooglemapsplus/MapPolygonBuilder.kt +59 -12
  7. package/android/src/main/java/com/rngooglemapsplus/MapPolylineBuilder.kt.kt +47 -12
  8. package/android/src/main/java/com/rngooglemapsplus/RNGoogleMapsPlusView.kt +12 -9
  9. package/android/src/main/java/com/rngooglemapsplus/extensions/CameraPositionExtension.kt +12 -0
  10. package/android/src/main/java/com/rngooglemapsplus/extensions/IntExtension.kt +28 -0
  11. package/android/src/main/java/com/rngooglemapsplus/extensions/LatLngBounds.kt +15 -0
  12. package/android/src/main/java/com/rngooglemapsplus/extensions/LatLngExtension.kt +6 -0
  13. package/android/src/main/java/com/rngooglemapsplus/extensions/LocationExtension.kt +59 -0
  14. package/android/src/main/java/com/rngooglemapsplus/extensions/RNCameraExtension.kt +1 -2
  15. package/android/src/main/java/com/rngooglemapsplus/extensions/RNLatLngExtension.kt +6 -0
  16. package/android/src/main/java/com/rngooglemapsplus/extensions/RNMarkerExtension.kt +8 -0
  17. package/android/src/main/java/com/rngooglemapsplus/extensions/RNPolygonExtension.kt +2 -0
  18. package/android/src/main/java/com/rngooglemapsplus/extensions/RNPolylineExtension.kt +1 -0
  19. package/ios/GoogleMapViewImpl.swift +39 -180
  20. package/ios/LocationHandler.swift +5 -13
  21. package/ios/MapCircleBuilder.swift +30 -18
  22. package/ios/MapHelper.swift +20 -0
  23. package/ios/MapMarkerBuilder.swift +105 -86
  24. package/ios/MapPolygonBuilder.swift +62 -13
  25. package/ios/MapPolylineBuilder.swift +33 -15
  26. package/ios/RNGoogleMapsPlusView.swift +15 -9
  27. package/ios/extensions/CLError+Extension.swift +14 -0
  28. package/ios/extensions/CLLocation+Extension.swift +27 -0
  29. package/ios/extensions/CLLocationCoordinate2D+Extension.swift +7 -0
  30. package/ios/extensions/GMSCameraPosition+Extension.swift +12 -0
  31. package/ios/extensions/GMSCoordinateBounds+Extension.swift +19 -0
  32. package/ios/extensions/RNLatLng+Extension.swift +7 -0
  33. package/ios/extensions/RNMarker+Extension.swift +7 -3
  34. package/ios/extensions/RNPolygon+Extension.swift.swift +16 -1
  35. package/ios/extensions/RNPolyline+Extension.swift.swift +1 -0
  36. package/lib/module/GoogleMapsPlus.js +7 -0
  37. package/lib/module/GoogleMapsPlus.js.map +1 -0
  38. package/lib/module/index.js +3 -5
  39. package/lib/module/index.js.map +1 -1
  40. package/lib/module/types.js.map +1 -1
  41. package/lib/nitrogen/generated/shared/json/RNGoogleMapsPlusViewConfig.json +44 -0
  42. package/lib/typescript/src/GoogleMapsPlus.d.ts +5 -0
  43. package/lib/typescript/src/GoogleMapsPlus.d.ts.map +1 -0
  44. package/lib/typescript/src/index.d.ts +3 -3
  45. package/lib/typescript/src/index.d.ts.map +1 -1
  46. package/lib/typescript/src/types.d.ts +33 -0
  47. package/lib/typescript/src/types.d.ts.map +1 -1
  48. package/nitrogen/generated/android/c++/JFunc_void_RNLocation.hpp +6 -0
  49. package/nitrogen/generated/android/c++/JHybridRNGoogleMapsPlusViewSpec.cpp +12 -0
  50. package/nitrogen/generated/android/c++/JRNLocation.hpp +32 -2
  51. package/nitrogen/generated/android/c++/JRNLocationAndroid.hpp +82 -0
  52. package/nitrogen/generated/android/c++/JRNLocationIOS.hpp +77 -0
  53. package/nitrogen/generated/android/c++/JRNMarker.hpp +8 -0
  54. package/nitrogen/generated/android/c++/JRNPolygon.hpp +29 -2
  55. package/nitrogen/generated/android/c++/JRNPolygonHole.hpp +72 -0
  56. package/nitrogen/generated/android/c++/JRNPolyline.hpp +4 -0
  57. package/nitrogen/generated/android/kotlin/com/margelo/nitro/rngooglemapsplus/RNLocation.kt +19 -1
  58. package/nitrogen/generated/android/kotlin/com/margelo/nitro/rngooglemapsplus/RNLocationAndroid.kt +50 -0
  59. package/nitrogen/generated/android/kotlin/com/margelo/nitro/rngooglemapsplus/RNLocationIOS.kt +47 -0
  60. package/nitrogen/generated/android/kotlin/com/margelo/nitro/rngooglemapsplus/RNMarker.kt +6 -0
  61. package/nitrogen/generated/android/kotlin/com/margelo/nitro/rngooglemapsplus/RNPolygon.kt +7 -1
  62. package/nitrogen/generated/android/kotlin/com/margelo/nitro/rngooglemapsplus/RNPolygonHole.kt +29 -0
  63. package/nitrogen/generated/android/kotlin/com/margelo/nitro/rngooglemapsplus/RNPolyline.kt +3 -0
  64. package/nitrogen/generated/android/kotlin/com/margelo/nitro/rngooglemapsplus/views/HybridRNGoogleMapsPlusViewManager.kt +8 -3
  65. package/nitrogen/generated/ios/RNGoogleMapsPlus-Swift-Cxx-Bridge.cpp +16 -16
  66. package/nitrogen/generated/ios/RNGoogleMapsPlus-Swift-Cxx-Bridge.hpp +87 -20
  67. package/nitrogen/generated/ios/RNGoogleMapsPlus-Swift-Cxx-Umbrella.hpp +9 -0
  68. package/nitrogen/generated/ios/c++/HybridRNGoogleMapsPlusViewSpecSwift.hpp +12 -3
  69. package/nitrogen/generated/ios/c++/views/HybridRNGoogleMapsPlusViewComponent.mm +8 -0
  70. package/nitrogen/generated/ios/swift/HybridRNGoogleMapsPlusViewSpec_cxx.swift +7 -56
  71. package/nitrogen/generated/ios/swift/RNCamera.swift +1 -8
  72. package/nitrogen/generated/ios/swift/RNHeatmap.swift +1 -8
  73. package/nitrogen/generated/ios/swift/RNHeatmapGradient.swift +11 -15
  74. package/nitrogen/generated/ios/swift/RNInitialProps.swift +1 -8
  75. package/nitrogen/generated/ios/swift/RNLocation.swift +92 -2
  76. package/nitrogen/generated/ios/swift/RNLocationAndroid.swift +215 -0
  77. package/nitrogen/generated/ios/swift/RNLocationConfig.swift +2 -16
  78. package/nitrogen/generated/ios/swift/RNLocationIOS.swift +185 -0
  79. package/nitrogen/generated/ios/swift/RNMarker.swift +47 -15
  80. package/nitrogen/generated/ios/swift/RNPolygon.swift +66 -1
  81. package/nitrogen/generated/ios/swift/RNPolygonHole.swift +47 -0
  82. package/nitrogen/generated/ios/swift/RNPolyline.swift +24 -1
  83. package/nitrogen/generated/ios/swift/RNSnapshotOptions.swift +1 -8
  84. package/nitrogen/generated/shared/c++/RNAndroidLocationConfig.hpp +8 -0
  85. package/nitrogen/generated/shared/c++/RNCamera.hpp +8 -0
  86. package/nitrogen/generated/shared/c++/RNCircle.hpp +8 -0
  87. package/nitrogen/generated/shared/c++/RNHeatmap.hpp +8 -0
  88. package/nitrogen/generated/shared/c++/RNHeatmapGradient.hpp +8 -0
  89. package/nitrogen/generated/shared/c++/RNHeatmapPoint.hpp +8 -0
  90. package/nitrogen/generated/shared/c++/RNIOSLocationConfig.hpp +8 -0
  91. package/nitrogen/generated/shared/c++/RNIndoorBuilding.hpp +8 -0
  92. package/nitrogen/generated/shared/c++/RNIndoorLevel.hpp +8 -0
  93. package/nitrogen/generated/shared/c++/RNInitialProps.hpp +8 -0
  94. package/nitrogen/generated/shared/c++/RNKMLayer.hpp +8 -0
  95. package/nitrogen/generated/shared/c++/RNLatLng.hpp +8 -0
  96. package/nitrogen/generated/shared/c++/RNLatLngBounds.hpp +8 -0
  97. package/nitrogen/generated/shared/c++/RNLocation.hpp +41 -2
  98. package/nitrogen/generated/shared/c++/RNLocationAndroid.hpp +104 -0
  99. package/nitrogen/generated/shared/c++/RNLocationConfig.hpp +8 -0
  100. package/nitrogen/generated/shared/c++/RNLocationIOS.hpp +99 -0
  101. package/nitrogen/generated/shared/c++/RNLocationPermissionResult.hpp +8 -0
  102. package/nitrogen/generated/shared/c++/RNMapPadding.hpp +8 -0
  103. package/nitrogen/generated/shared/c++/RNMapUiSettings.hpp +8 -0
  104. package/nitrogen/generated/shared/c++/RNMapZoomConfig.hpp +8 -0
  105. package/nitrogen/generated/shared/c++/RNMarker.hpp +17 -1
  106. package/nitrogen/generated/shared/c++/RNMarkerSvg.hpp +8 -0
  107. package/nitrogen/generated/shared/c++/RNPolygon.hpp +21 -2
  108. package/nitrogen/generated/shared/c++/RNPolygonHole.hpp +77 -0
  109. package/nitrogen/generated/shared/c++/RNPolyline.hpp +13 -1
  110. package/nitrogen/generated/shared/c++/RNPosition.hpp +8 -0
  111. package/nitrogen/generated/shared/c++/RNRegion.hpp +8 -0
  112. package/nitrogen/generated/shared/c++/RNSize.hpp +8 -0
  113. package/nitrogen/generated/shared/c++/RNSnapshotOptions.hpp +8 -0
  114. package/package.json +9 -16
  115. package/src/GoogleMapsPlus.tsx +20 -0
  116. package/src/index.tsx +6 -14
  117. package/src/types.ts +36 -0
  118. package/lib/module/package.json +0 -1
  119. package/lib/typescript/package.json +0 -1
@@ -28,7 +28,7 @@ apply from: "./fix-prefab.gradle"
28
28
  if (rootProject.name != "rngooglemapsplus.example") {
29
29
  apply plugin: "com.facebook.react"
30
30
  } else {
31
- println("\u001B[33m⚠️ Skipping React Native Gradle plugin in library (example build detected)\u001B[0m")
31
+ println("\u001B[33mSkipping React Native Gradle plugin in library (example build detected)\u001B[0m")
32
32
  }
33
33
 
34
34
  def getExtOrIntegerDefault(name) {
@@ -2,7 +2,6 @@ package com.rngooglemapsplus
2
2
 
3
3
  import android.annotation.SuppressLint
4
4
  import android.graphics.Bitmap
5
- import android.location.Location
6
5
  import android.util.Base64
7
6
  import android.util.Size
8
7
  import android.widget.FrameLayout
@@ -11,7 +10,6 @@ import com.facebook.react.bridge.LifecycleEventListener
11
10
  import com.facebook.react.bridge.UiThreadUtil
12
11
  import com.facebook.react.uimanager.PixelUtil.dpToPx
13
12
  import com.facebook.react.uimanager.ThemedReactContext
14
- import com.google.android.gms.common.ConnectionResult
15
13
  import com.google.android.gms.maps.CameraUpdateFactory
16
14
  import com.google.android.gms.maps.GoogleMap
17
15
  import com.google.android.gms.maps.GoogleMapOptions
@@ -35,9 +33,15 @@ import com.google.android.gms.maps.model.TileOverlayOptions
35
33
  import com.google.maps.android.data.kml.KmlLayer
36
34
  import com.margelo.nitro.core.Promise
37
35
  import com.rngooglemapsplus.extensions.toGooglePriority
36
+ import com.rngooglemapsplus.extensions.toLatLng
38
37
  import com.rngooglemapsplus.extensions.toLocationErrorCode
39
38
  import com.rngooglemapsplus.extensions.toRNIndoorBuilding
40
39
  import com.rngooglemapsplus.extensions.toRNIndoorLevel
40
+ import com.rngooglemapsplus.extensions.toRNMapErrorCodeOrNull
41
+ import com.rngooglemapsplus.extensions.toRnCamera
42
+ import com.rngooglemapsplus.extensions.toRnLatLng
43
+ import com.rngooglemapsplus.extensions.toRnLocation
44
+ import com.rngooglemapsplus.extensions.toRnRegion
41
45
  import java.io.ByteArrayInputStream
42
46
  import java.io.ByteArrayOutputStream
43
47
  import java.io.File
@@ -63,6 +67,7 @@ class GoogleMapsViewImpl(
63
67
  LifecycleEventListener {
64
68
  private var initialized = false
65
69
  private var mapReady = false
70
+ private var destroyed = false
66
71
  private var googleMap: GoogleMap? = null
67
72
  private var mapView: MapView? = null
68
73
 
@@ -81,58 +86,32 @@ class GoogleMapsViewImpl(
81
86
  private val kmlLayersById = mutableMapOf<String, KmlLayer>()
82
87
 
83
88
  private var cameraMoveReason = -1
84
- private var lastSubmittedLocation: Location? = null
85
89
  private var lastSubmittedCameraPosition: CameraPosition? = null
86
90
 
87
91
  init {
88
92
  reactContext.addLifecycleEventListener(this)
89
93
  }
90
94
 
91
- fun initMapView(
92
- mapId: String?,
93
- liteMode: Boolean?,
94
- cameraPosition: CameraPosition?,
95
- ) {
95
+ fun initMapView(googleMapsOptions: GoogleMapOptions) {
96
96
  if (initialized) return
97
97
  initialized = true
98
98
  val result = playServiceHandler.playServicesAvailability()
99
+ val errorCode = result.toRNMapErrorCodeOrNull()
99
100
 
100
- when (result) {
101
- ConnectionResult.SERVICE_MISSING -> {
102
- onMapError?.invoke(RNMapErrorCode.PLAY_SERVICES_MISSING)
103
- return
104
- }
101
+ if (errorCode != null) {
102
+ onMapError?.invoke(errorCode)
105
103
 
106
- ConnectionResult.SERVICE_INVALID -> {
107
- onMapError?.invoke(RNMapErrorCode.PLAY_SERVICES_INVALID)
104
+ if (errorCode == RNMapErrorCode.PLAY_SERVICES_MISSING ||
105
+ errorCode == RNMapErrorCode.PLAY_SERVICES_INVALID
106
+ ) {
108
107
  return
109
108
  }
110
-
111
- ConnectionResult.SERVICE_VERSION_UPDATE_REQUIRED ->
112
- onMapError?.invoke(RNMapErrorCode.PLAY_SERVICES_OUTDATED)
113
-
114
- ConnectionResult.SERVICE_UPDATING ->
115
- onMapError?.invoke(RNMapErrorCode.PLAY_SERVICE_UPDATING)
116
-
117
- ConnectionResult.SERVICE_DISABLED ->
118
- onMapError?.invoke(RNMapErrorCode.PLAY_SERVICES_DISABLED)
119
-
120
- ConnectionResult.SUCCESS -> {}
121
-
122
- else ->
123
- onMapError?.invoke(RNMapErrorCode.UNKNOWN)
124
109
  }
125
110
 
126
111
  mapView =
127
112
  MapView(
128
113
  reactContext,
129
- GoogleMapOptions().apply {
130
- mapId?.let { mapId(it) }
131
- liteMode?.let { liteMode(it) }
132
- cameraPosition?.let {
133
- camera(it)
134
- }
135
- },
114
+ googleMapsOptions,
136
115
  )
137
116
 
138
117
  super.addView(mapView)
@@ -151,8 +130,8 @@ class GoogleMapsViewImpl(
151
130
  googleMap?.setOnMapClickListener(this@GoogleMapsViewImpl)
152
131
  googleMap?.setOnMarkerDragListener(this@GoogleMapsViewImpl)
153
132
  }
133
+ applyProps()
154
134
  initLocationCallbacks()
155
- applyPending()
156
135
  mapReady = true
157
136
  onMapReady?.invoke(true)
158
137
  }
@@ -168,21 +147,9 @@ class GoogleMapsViewImpl(
168
147
  }
169
148
  val isGesture = GoogleMap.OnCameraMoveStartedListener.REASON_GESTURE == reason
170
149
 
171
- val latDelta = bounds.northeast.latitude - bounds.southwest.latitude
172
- val lngDelta = bounds.northeast.longitude - bounds.southwest.longitude
173
-
174
150
  onCameraChangeStart?.invoke(
175
- RNRegion(
176
- center = RNLatLng(bounds.center.latitude, bounds.center.longitude),
177
- latitudeDelta = latDelta,
178
- longitudeDelta = lngDelta,
179
- ),
180
- RNCamera(
181
- center = RNLatLng(cameraPosition.target.latitude, cameraPosition.target.longitude),
182
- zoom = cameraPosition.zoom.toDouble(),
183
- bearing = cameraPosition.bearing.toDouble(),
184
- tilt = cameraPosition.tilt.toDouble(),
185
- ),
151
+ bounds.toRnRegion(),
152
+ cameraPosition.toRnCamera(),
186
153
  isGesture,
187
154
  )
188
155
  }
@@ -200,21 +167,9 @@ class GoogleMapsViewImpl(
200
167
 
201
168
  val isGesture = GoogleMap.OnCameraMoveStartedListener.REASON_GESTURE == cameraMoveReason
202
169
 
203
- val latDelta = bounds.northeast.latitude - bounds.southwest.latitude
204
- val lngDelta = bounds.northeast.longitude - bounds.southwest.longitude
205
-
206
- onCameraChange?.invoke(
207
- RNRegion(
208
- center = RNLatLng(bounds.center.latitude, bounds.center.longitude),
209
- latitudeDelta = latDelta,
210
- longitudeDelta = lngDelta,
211
- ),
212
- RNCamera(
213
- center = RNLatLng(cameraPosition.target.latitude, cameraPosition.target.longitude),
214
- zoom = cameraPosition.zoom.toDouble(),
215
- bearing = cameraPosition.bearing.toDouble(),
216
- tilt = cameraPosition.tilt.toDouble(),
217
- ),
170
+ onCameraChangeStart?.invoke(
171
+ bounds.toRnRegion(),
172
+ cameraPosition.toRnCamera(),
218
173
  isGesture,
219
174
  )
220
175
  }
@@ -228,39 +183,16 @@ class GoogleMapsViewImpl(
228
183
  }
229
184
  val isGesture = GoogleMap.OnCameraMoveStartedListener.REASON_GESTURE == cameraMoveReason
230
185
 
231
- val latDelta = bounds.northeast.latitude - bounds.southwest.latitude
232
- val lngDelta = bounds.northeast.longitude - bounds.southwest.longitude
233
-
234
- onCameraChangeComplete?.invoke(
235
- RNRegion(
236
- center = RNLatLng(bounds.center.latitude, bounds.center.longitude),
237
- latitudeDelta = latDelta,
238
- longitudeDelta = lngDelta,
239
- ),
240
- RNCamera(
241
- center = RNLatLng(cameraPosition.target.latitude, cameraPosition.target.longitude),
242
- zoom = cameraPosition.zoom.toDouble(),
243
- bearing = cameraPosition.bearing.toDouble(),
244
- tilt = cameraPosition.tilt.toDouble(),
245
- ),
186
+ onCameraChangeStart?.invoke(
187
+ bounds.toRnRegion(),
188
+ cameraPosition.toRnCamera(),
246
189
  isGesture,
247
190
  )
248
191
  }
249
192
 
250
193
  fun initLocationCallbacks() {
251
194
  locationHandler.onUpdate = { location ->
252
- // / only the coordinated are relevant right now
253
- if (lastSubmittedLocation?.latitude != location.latitude || lastSubmittedLocation?.longitude != location.longitude ||
254
- lastSubmittedLocation?.bearing != location.bearing
255
- ) {
256
- onLocationUpdate?.invoke(
257
- RNLocation(
258
- RNLatLng(location.latitude, location.longitude),
259
- location.bearing.toDouble(),
260
- ),
261
- )
262
- }
263
- lastSubmittedLocation = location
195
+ onLocationUpdate?.invoke(location.toRnLocation())
264
196
  }
265
197
 
266
198
  locationHandler.onError = { error ->
@@ -269,65 +201,18 @@ class GoogleMapsViewImpl(
269
201
  locationHandler.start()
270
202
  }
271
203
 
272
- fun applyPending() {
273
- onUi {
274
- mapPadding?.let {
275
- googleMap?.setPadding(
276
- it.left.dpToPx().toInt(),
277
- it.top.dpToPx().toInt(),
278
- it.right.dpToPx().toInt(),
279
- it.bottom.dpToPx().toInt(),
280
- )
281
- }
282
-
283
- uiSettings?.let { v ->
284
- googleMap?.uiSettings?.apply {
285
- v.allGesturesEnabled?.let { setAllGesturesEnabled(it) }
286
- v.compassEnabled?.let { isCompassEnabled = it }
287
- v.indoorLevelPickerEnabled?.let { isIndoorLevelPickerEnabled = it }
288
- v.mapToolbarEnabled?.let { isMapToolbarEnabled = it }
289
- v.myLocationButtonEnabled?.let {
290
- googleMap?.setLocationSource(locationHandler)
291
- isMyLocationButtonEnabled = it
292
- }
293
- v.rotateEnabled?.let { isRotateGesturesEnabled = it }
294
- v.scrollEnabled?.let { isScrollGesturesEnabled = it }
295
- v.scrollDuringRotateOrZoomEnabled?.let {
296
- isScrollGesturesEnabledDuringRotateOrZoom = it
297
- }
298
- v.tiltEnabled?.let { isTiltGesturesEnabled = it }
299
- v.zoomControlsEnabled?.let { isZoomControlsEnabled = it }
300
- v.zoomGesturesEnabled?.let { isZoomGesturesEnabled = it }
301
- }
302
- }
303
-
304
- buildingEnabled?.let {
305
- googleMap?.isBuildingsEnabled = it
306
- }
307
- trafficEnabled?.let {
308
- googleMap?.isTrafficEnabled = it
309
- }
310
- indoorEnabled?.let {
311
- googleMap?.isIndoorEnabled = it
312
- }
313
- googleMap?.setMapStyle(customMapStyle)
314
- mapType?.let {
315
- googleMap?.mapType = it
316
- }
317
- userInterfaceStyle?.let {
318
- googleMap?.mapColorScheme = it
319
- }
320
- mapZoomConfig?.let {
321
- googleMap?.setMinZoomPreference(it.min?.toFloat() ?: 2.0f)
322
- googleMap?.setMaxZoomPreference(it.max?.toFloat() ?: 21.0f)
323
- }
324
- }
325
-
326
- locationConfig?.let {
327
- locationHandler.priority = it.android?.priority?.toGooglePriority()
328
- locationHandler.interval = it.android?.interval?.toLong()
329
- locationHandler.minUpdateInterval = it.android?.minUpdateInterval?.toLong()
330
- }
204
+ fun applyProps() {
205
+ mapPadding = mapPadding
206
+ uiSettings = uiSettings
207
+ myLocationEnabled = myLocationEnabled
208
+ buildingEnabled = buildingEnabled
209
+ trafficEnabled = trafficEnabled
210
+ indoorEnabled = indoorEnabled
211
+ customMapStyle = customMapStyle
212
+ mapType = mapType
213
+ userInterfaceStyle = userInterfaceStyle
214
+ mapZoomConfig = mapZoomConfig
215
+ locationConfig = locationConfig
331
216
 
332
217
  if (pendingMarkers.isNotEmpty()) {
333
218
  pendingMarkers.forEach { (id, opts) ->
@@ -488,9 +373,11 @@ class GoogleMapsViewImpl(
488
373
  var locationConfig: RNLocationConfig? = null
489
374
  set(value) {
490
375
  field = value
491
- locationHandler.priority = value?.android?.priority?.toGooglePriority()
492
- locationHandler.interval = value?.android?.interval?.toLong()
493
- locationHandler.minUpdateInterval = value?.android?.minUpdateInterval?.toLong()
376
+ locationHandler.updateConfig(
377
+ value?.android?.priority?.toGooglePriority(),
378
+ value?.android?.interval?.toLong(),
379
+ value?.android?.minUpdateInterval?.toLong(),
380
+ )
494
381
  }
495
382
 
496
383
  var onMapError: ((RNMapErrorCode) -> Unit)? = null
@@ -544,7 +431,7 @@ class GoogleMapsViewImpl(
544
431
  onUi {
545
432
  val builder = LatLngBounds.Builder()
546
433
  coordinates.forEach { coord ->
547
- builder.include(LatLng(coord.latitude, coord.longitude))
434
+ builder.include(coord.toLatLng())
548
435
  }
549
436
  val bounds = builder.build()
550
437
 
@@ -927,7 +814,7 @@ class GoogleMapsViewImpl(
927
814
  onUi {
928
815
  heatmapsById.values.forEach { it.remove() }
929
816
  }
930
- circlesById.clear()
817
+ heatmapsById.clear()
931
818
  pendingHeatmaps.clear()
932
819
  }
933
820
 
@@ -976,6 +863,8 @@ class GoogleMapsViewImpl(
976
863
  }
977
864
 
978
865
  fun destroyInternal() {
866
+ if (destroyed) return
867
+ destroyed = true
979
868
  onUi {
980
869
  locationHandler.stop()
981
870
  markerBuilder.cancelAllJobs()
@@ -1069,28 +958,28 @@ class GoogleMapsViewImpl(
1069
958
 
1070
959
  override fun onMapClick(coordinates: LatLng) {
1071
960
  onMapPress?.invoke(
1072
- RNLatLng(coordinates.latitude, coordinates.longitude),
961
+ coordinates.toRnLatLng(),
1073
962
  )
1074
963
  }
1075
964
 
1076
965
  override fun onMarkerDragStart(marker: Marker) {
1077
966
  onMarkerDragStart?.invoke(
1078
967
  marker.tag?.toString(),
1079
- RNLatLng(marker.position.latitude, marker.position.longitude),
968
+ marker.position.toRnLatLng(),
1080
969
  )
1081
970
  }
1082
971
 
1083
972
  override fun onMarkerDrag(marker: Marker) {
1084
973
  onMarkerDrag?.invoke(
1085
974
  marker.tag?.toString(),
1086
- RNLatLng(marker.position.latitude, marker.position.longitude),
975
+ marker.position.toRnLatLng(),
1087
976
  )
1088
977
  }
1089
978
 
1090
979
  override fun onMarkerDragEnd(marker: Marker) {
1091
980
  onMarkerDragEnd?.invoke(
1092
981
  marker.tag?.toString(),
1093
- RNLatLng(marker.position.latitude, marker.position.longitude),
982
+ marker.position.toRnLatLng(),
1094
983
  )
1095
984
  }
1096
985
 
@@ -35,30 +35,28 @@ class LocationHandler(
35
35
  private var listener: LocationSource.OnLocationChangedListener? = null
36
36
  private var locationRequest: LocationRequest? = null
37
37
  private var locationCallback: LocationCallback? = null
38
-
39
- var priority: Int? = PRIORITY_DEFAULT
40
- set(value) {
41
- field = value ?: PRIORITY_DEFAULT
42
- start()
43
- }
44
-
45
- var interval: Long? = INTERVAL_DEFAULT
46
- set(value) {
47
- field = value ?: INTERVAL_DEFAULT
48
- buildLocationRequest()
49
- }
50
-
51
- var minUpdateInterval: Long? = MIN_UPDATE_INTERVAL
52
- set(value) {
53
- field = value ?: MIN_UPDATE_INTERVAL
54
- buildLocationRequest()
55
- }
38
+ private var priority: Int = PRIORITY_DEFAULT
39
+ private var interval: Long = INTERVAL_DEFAULT
40
+ private var minUpdateInterval: Long = MIN_UPDATE_INTERVAL
41
+ private var lastSubmittedLocation: Location? = null
42
+ private var isActive = false
56
43
 
57
44
  var onUpdate: ((Location) -> Unit)? = null
58
45
  var onError: ((RNLocationErrorCode) -> Unit)? = null
59
46
 
60
47
  init {
61
- buildLocationRequest()
48
+ buildLocationRequest(priority, interval, minUpdateInterval)
49
+ }
50
+
51
+ fun updateConfig(
52
+ priority: Int? = null,
53
+ interval: Long? = null,
54
+ minUpdateInterval: Long? = null,
55
+ ) {
56
+ this.priority = priority ?: PRIORITY_DEFAULT
57
+ this.interval = interval ?: INTERVAL_DEFAULT
58
+ this.minUpdateInterval = minUpdateInterval ?: MIN_UPDATE_INTERVAL
59
+ buildLocationRequest(this.priority, this.interval, this.minUpdateInterval)
62
60
  }
63
61
 
64
62
  fun showLocationDialog() {
@@ -108,11 +106,11 @@ class LocationHandler(
108
106
  }
109
107
 
110
108
  @Suppress("deprecation")
111
- private fun buildLocationRequest() {
112
- val priority = priority ?: Priority.PRIORITY_BALANCED_POWER_ACCURACY
113
- val interval = interval ?: INTERVAL_DEFAULT
114
- val minUpdateInterval = minUpdateInterval ?: MIN_UPDATE_INTERVAL
115
-
109
+ private fun buildLocationRequest(
110
+ priority: Int,
111
+ interval: Long,
112
+ minUpdateInterval: Long,
113
+ ) {
116
114
  locationRequest =
117
115
  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
118
116
  LocationRequest
@@ -126,11 +124,13 @@ class LocationHandler(
126
124
  .setInterval(interval)
127
125
  .setFastestInterval(minUpdateInterval)
128
126
  }
129
- restartLocationUpdates()
130
127
  }
131
128
 
132
- private fun restartLocationUpdates() {
133
- stop()
129
+ @SuppressLint("MissingPermission")
130
+ fun start() {
131
+ if (isActive) return
132
+ isActive = true
133
+
134
134
  val playServicesStatus =
135
135
  GoogleApiAvailability
136
136
  .getInstance()
@@ -139,17 +139,13 @@ class LocationHandler(
139
139
  onError?.invoke(RNLocationErrorCode.PLAY_SERVICE_NOT_AVAILABLE)
140
140
  return
141
141
  }
142
- start()
143
- }
144
-
145
- @SuppressLint("MissingPermission")
146
- fun start() {
147
142
  try {
148
143
  fusedLocationClientProviderClient.lastLocation
149
144
  .addOnSuccessListener(
150
145
  OnSuccessListener { location ->
151
- if (location != null) {
146
+ if (location != null && location != lastSubmittedLocation) {
152
147
  onUpdate?.invoke(location)
148
+ lastSubmittedLocation = location
153
149
  }
154
150
  },
155
151
  ).addOnFailureListener { e ->
@@ -161,8 +157,11 @@ class LocationHandler(
161
157
  override fun onLocationResult(locationResult: LocationResult) {
162
158
  val location = locationResult.lastLocation
163
159
  if (location != null) {
164
- listener?.onLocationChanged(location)
165
- onUpdate?.invoke(location)
160
+ if (location != lastSubmittedLocation) {
161
+ lastSubmittedLocation = location
162
+ listener?.onLocationChanged(location)
163
+ onUpdate?.invoke(location)
164
+ }
166
165
  } else {
167
166
  onError?.invoke(RNLocationErrorCode.POSITION_UNAVAILABLE)
168
167
  }
@@ -186,9 +185,11 @@ class LocationHandler(
186
185
  }
187
186
 
188
187
  fun stop() {
189
- listener = null
188
+ if (!isActive) return
189
+ isActive = false
190
190
  if (locationCallback != null) {
191
191
  fusedLocationClientProviderClient.removeLocationUpdates(locationCallback!!)
192
+ fusedLocationClientProviderClient.flushLocations()
192
193
  locationCallback = null
193
194
  }
194
195
  }
@@ -199,6 +200,7 @@ class LocationHandler(
199
200
  }
200
201
 
201
202
  override fun deactivate() {
203
+ listener = null
202
204
  stop()
203
205
  }
204
206
  }
@@ -4,13 +4,13 @@ import android.graphics.Color
4
4
  import com.facebook.react.uimanager.PixelUtil.dpToPx
5
5
  import com.google.android.gms.maps.model.Circle
6
6
  import com.google.android.gms.maps.model.CircleOptions
7
- import com.google.android.gms.maps.model.LatLng
8
7
  import com.rngooglemapsplus.extensions.toColor
8
+ import com.rngooglemapsplus.extensions.toLatLng
9
9
 
10
10
  class MapCircleBuilder {
11
11
  fun build(circle: RNCircle): CircleOptions =
12
12
  CircleOptions().apply {
13
- center(LatLng(circle.center.latitude, circle.center.longitude))
13
+ center(circle.center.toLatLng())
14
14
  radius(circle.radius)
15
15
  circle.strokeWidth?.let { strokeWidth(it.dpToPx()) }
16
16
  circle.strokeColor?.let { strokeColor(it.toColor()) }
@@ -20,14 +20,38 @@ class MapCircleBuilder {
20
20
  }
21
21
 
22
22
  fun update(
23
- circle: Circle,
23
+ prev: RNCircle,
24
24
  next: RNCircle,
25
+ circle: Circle,
25
26
  ) {
26
- circle.center = LatLng(next.center.latitude, next.center.longitude)
27
- circle.radius = next.radius
28
- circle.strokeWidth = next.strokeWidth?.dpToPx() ?: 1f
29
- circle.strokeColor = next.strokeColor?.toColor() ?: Color.BLACK
30
- circle.fillColor = next.fillColor?.toColor() ?: Color.TRANSPARENT
31
- circle.zIndex = next.zIndex?.toFloat() ?: 0f
27
+ if (prev.center.latitude != next.center.latitude ||
28
+ prev.center.longitude != next.center.longitude
29
+ ) {
30
+ circle.center = next.center.toLatLng()
31
+ }
32
+
33
+ if (prev.radius != next.radius) {
34
+ circle.radius = next.radius
35
+ }
36
+
37
+ if (prev.strokeWidth != next.strokeWidth) {
38
+ circle.strokeWidth = next.strokeWidth?.dpToPx() ?: 1f
39
+ }
40
+
41
+ if (prev.strokeColor != next.strokeColor) {
42
+ circle.strokeColor = next.strokeColor?.toColor() ?: Color.BLACK
43
+ }
44
+
45
+ if (prev.fillColor != next.fillColor) {
46
+ circle.fillColor = next.fillColor?.toColor() ?: Color.TRANSPARENT
47
+ }
48
+
49
+ if (prev.pressable != next.pressable) {
50
+ circle.isClickable = next.pressable ?: false
51
+ }
52
+
53
+ if (prev.zIndex != next.zIndex) {
54
+ circle.zIndex = next.zIndex?.toFloat() ?: 0f
55
+ }
32
56
  }
33
57
  }
@@ -8,11 +8,11 @@ import com.caverock.androidsvg.SVG
8
8
  import com.facebook.react.uimanager.PixelUtil.dpToPx
9
9
  import com.google.android.gms.maps.model.BitmapDescriptor
10
10
  import com.google.android.gms.maps.model.BitmapDescriptorFactory
11
- import com.google.android.gms.maps.model.LatLng
12
11
  import com.google.android.gms.maps.model.Marker
13
12
  import com.google.android.gms.maps.model.MarkerOptions
14
13
  import com.rngooglemapsplus.extensions.markerStyleEquals
15
14
  import com.rngooglemapsplus.extensions.styleHash
15
+ import com.rngooglemapsplus.extensions.toLatLng
16
16
  import kotlinx.coroutines.CoroutineScope
17
17
  import kotlinx.coroutines.Dispatchers
18
18
  import kotlinx.coroutines.Job
@@ -40,43 +40,98 @@ class MapMarkerBuilder(
40
40
  icon: BitmapDescriptor?,
41
41
  ): MarkerOptions =
42
42
  MarkerOptions().apply {
43
- position(LatLng(m.coordinate.latitude, m.coordinate.longitude))
43
+ position(m.coordinate.toLatLng())
44
44
  icon(icon)
45
45
  m.title?.let { title(it) }
46
46
  m.snippet?.let { snippet(it) }
47
47
  m.opacity?.let { alpha(it.toFloat()) }
48
48
  m.flat?.let { flat(it) }
49
49
  m.draggable?.let { draggable(it) }
50
+ m.rotation?.let { rotation(it.toFloat()) }
51
+ m.infoWindowAnchor?.let { infoWindowAnchor(it.x.toFloat(), it.y.toFloat()) }
50
52
  m.anchor?.let { anchor((m.anchor.x).toFloat(), (m.anchor.y).toFloat()) }
51
53
  m.zIndex?.let { zIndex(it.toFloat()) }
52
54
  }
53
55
 
54
56
  fun update(
55
- marker: Marker,
56
57
  prev: RNMarker,
57
58
  next: RNMarker,
59
+ marker: Marker,
58
60
  ) {
59
- marker.position =
60
- LatLng(
61
- next.coordinate.latitude,
62
- next.coordinate.longitude,
63
- )
61
+ if (prev.coordinate.latitude != next.coordinate.latitude ||
62
+ prev.coordinate.longitude != next.coordinate.longitude
63
+ ) {
64
+ marker.position = next.coordinate.toLatLng()
65
+ }
64
66
 
65
67
  if (!prev.markerStyleEquals(next)) {
66
68
  buildIconAsync(marker.id, next) { icon ->
67
69
  marker.setIcon(icon)
70
+ if (prev.infoWindowAnchor?.x != next.infoWindowAnchor?.x ||
71
+ prev.infoWindowAnchor?.y != next.infoWindowAnchor?.y
72
+ ) {
73
+ marker.setInfoWindowAnchor(
74
+ (next.infoWindowAnchor?.x ?: 0.5f).toFloat(),
75
+ (next.infoWindowAnchor?.y ?: 0f).toFloat(),
76
+ )
77
+ }
78
+
79
+ if (prev.anchor?.x != next.anchor?.x ||
80
+ prev.anchor?.y != next.anchor?.y
81
+ ) {
82
+ marker.setAnchor(
83
+ (next.anchor?.x ?: 0.5f).toFloat(),
84
+ (next.anchor?.y ?: 1.0f).toFloat(),
85
+ )
86
+ }
68
87
  }
88
+ } else {
89
+ if (prev.infoWindowAnchor?.x != next.infoWindowAnchor?.x ||
90
+ prev.infoWindowAnchor?.y != next.infoWindowAnchor?.y
91
+ ) {
92
+ marker.setInfoWindowAnchor(
93
+ (next.infoWindowAnchor?.x ?: 0.5f).toFloat(),
94
+ (next.infoWindowAnchor?.y ?: 0f).toFloat(),
95
+ )
96
+ }
97
+
98
+ if (prev.anchor?.x != next.anchor?.x ||
99
+ prev.anchor?.y != next.anchor?.y
100
+ ) {
101
+ marker.setAnchor(
102
+ (next.anchor?.x ?: 0.5f).toFloat(),
103
+ (next.anchor?.y ?: 1.0f).toFloat(),
104
+ )
105
+ }
106
+ }
107
+
108
+ if (prev.title != next.title) {
109
+ marker.title = next.title
110
+ }
111
+
112
+ if (prev.snippet != next.snippet) {
113
+ marker.snippet = next.snippet
114
+ }
115
+
116
+ if (prev.opacity != next.opacity) {
117
+ marker.alpha = next.opacity?.toFloat() ?: 1f
118
+ }
119
+
120
+ if (prev.flat != next.flat) {
121
+ marker.isFlat = next.flat ?: false
122
+ }
123
+
124
+ if (prev.draggable != next.draggable) {
125
+ marker.isDraggable = next.draggable ?: false
126
+ }
127
+
128
+ if (prev.rotation != next.rotation) {
129
+ marker.rotation = next.rotation?.toFloat() ?: 0f
130
+ }
131
+
132
+ if (prev.zIndex != next.zIndex) {
133
+ marker.zIndex = next.zIndex?.toFloat() ?: 0f
69
134
  }
70
- marker.title = next.title
71
- marker.snippet = next.snippet
72
- marker.alpha = next.opacity?.toFloat() ?: 0f
73
- marker.isFlat = next.flat ?: false
74
- marker.isDraggable = next.draggable ?: false
75
- marker.setAnchor(
76
- (next.anchor?.x ?: 0.5).toFloat(),
77
- (next.anchor?.y ?: 1.0).toFloat(),
78
- )
79
- marker.zIndex = next.zIndex?.toFloat() ?: 0f
80
135
  }
81
136
 
82
137
  fun buildIconAsync(