react-native-google-maps-plus 1.0.2 → 1.1.0-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 (107) hide show
  1. package/README.md +127 -11
  2. package/android/src/main/java/com/rngooglemapsplus/GoogleMapsViewImpl.kt +359 -139
  3. package/android/src/main/java/com/rngooglemapsplus/LocationHandler.kt +44 -44
  4. package/android/src/main/java/com/rngooglemapsplus/MapCircleBuilder.kt +19 -0
  5. package/android/src/main/java/com/rngooglemapsplus/{MapMarker.kt → MapMarkerBuilder.kt} +7 -6
  6. package/android/src/main/java/com/rngooglemapsplus/{MapPolygon.kt → MapPolygonBuilder.kt} +4 -18
  7. package/android/src/main/java/com/rngooglemapsplus/{MapPolyline.kt → MapPolylineBuilder.kt.kt} +4 -19
  8. package/android/src/main/java/com/rngooglemapsplus/RNGoogleMapsPlusView.kt +145 -129
  9. package/android/src/main/java/com/rngooglemapsplus/extensions/RNCameraExtension.kt +19 -0
  10. package/android/src/main/java/com/rngooglemapsplus/extensions/RNLocationPriorityExtension.kt +12 -0
  11. package/android/src/main/java/com/rngooglemapsplus/extensions/RNMapCircleExtension.kt +14 -0
  12. package/android/src/main/java/com/rngooglemapsplus/extensions/RNPolygonExtension.kt +20 -0
  13. package/android/src/main/java/com/rngooglemapsplus/extensions/RNPolylineExtension.kt +21 -0
  14. package/android/src/main/java/com/rngooglemapsplus/extensions/RNUserInterfaceExtension.kt +12 -0
  15. package/android/src/main/java/com/rngooglemapsplus/{Color.kt → extensions/StringExtension.kt} +1 -1
  16. package/android/src/main/java/com/rngooglemapsplus/extensions/ThrowableExtension.kt +38 -0
  17. package/ios/GoogleMapViewImpl.swift +348 -150
  18. package/ios/LocationHandler.swift +29 -69
  19. package/ios/MapCircleBuilder.swift +20 -0
  20. package/ios/{MapMarker.swift → MapMarkerBuilder.swift} +11 -42
  21. package/ios/MapPolygonBuilder.swift +20 -0
  22. package/ios/MapPolylineBuilder.swift +24 -0
  23. package/ios/PermissionHandler.swift +1 -1
  24. package/ios/RNGoogleMapsPlusModule.swift +1 -1
  25. package/ios/RNGoogleMapsPlusView.swift +159 -168
  26. package/ios/extensions/RNCamera+Extension.swift +22 -0
  27. package/ios/extensions/RNCircle+Extension.swift +24 -0
  28. package/ios/extensions/RNIOSLocationAccuracy+Extensions.swift +19 -0
  29. package/ios/extensions/RNMarker+Extension.swift +24 -0
  30. package/ios/{MapPolygon.swift → extensions/RNPolygon+Extension.swift.swift} +7 -23
  31. package/ios/extensions/RNPolyline+Extension.swift.swift +62 -0
  32. package/ios/extensions/RNUserInterface+Extension.swift +16 -0
  33. package/ios/{Color.swift → extensions/String+Extensions.swift} +20 -20
  34. package/lib/module/types.js +14 -0
  35. package/lib/module/types.js.map +1 -1
  36. package/lib/typescript/src/RNGoogleMapsPlusView.nitro.d.ts +21 -12
  37. package/lib/typescript/src/RNGoogleMapsPlusView.nitro.d.ts.map +1 -1
  38. package/lib/typescript/src/types.d.ts +59 -3
  39. package/lib/typescript/src/types.d.ts.map +1 -1
  40. package/nitrogen/generated/android/c++/JHybridRNGoogleMapsPlusViewSpec.cpp +233 -69
  41. package/nitrogen/generated/android/c++/JHybridRNGoogleMapsPlusViewSpec.hpp +40 -22
  42. package/nitrogen/generated/android/c++/JRNAndroidLocationConfig.hpp +63 -0
  43. package/nitrogen/generated/android/c++/JRNAndroidLocationPriority.hpp +65 -0
  44. package/nitrogen/generated/android/c++/JRNCircle.hpp +84 -0
  45. package/nitrogen/generated/android/c++/JRNIOSLocationAccuracy.hpp +65 -0
  46. package/nitrogen/generated/android/c++/JRNIOSLocationConfig.hpp +59 -0
  47. package/nitrogen/generated/android/c++/JRNInitialProps.hpp +66 -0
  48. package/nitrogen/generated/android/c++/JRNLocationConfig.hpp +65 -0
  49. package/nitrogen/generated/android/c++/JRNMapType.hpp +68 -0
  50. package/nitrogen/generated/android/c++/JRNMapUiSettings.hpp +93 -0
  51. package/nitrogen/generated/android/c++/JRNMarker.hpp +4 -4
  52. package/nitrogen/generated/android/c++/JRNPolygon.hpp +8 -4
  53. package/nitrogen/generated/android/c++/JRNPolyline.hpp +8 -4
  54. package/nitrogen/generated/android/c++/views/JHybridRNGoogleMapsPlusViewStateUpdater.cpp +40 -4
  55. package/nitrogen/generated/android/kotlin/com/margelo/nitro/rngooglemapsplus/HybridRNGoogleMapsPlusViewSpec.kt +89 -11
  56. package/nitrogen/generated/android/kotlin/com/margelo/nitro/rngooglemapsplus/RNAndroidLocationConfig.kt +35 -0
  57. package/nitrogen/generated/android/kotlin/com/margelo/nitro/rngooglemapsplus/RNAndroidLocationPriority.kt +23 -0
  58. package/nitrogen/generated/android/kotlin/com/margelo/nitro/rngooglemapsplus/RNCircle.kt +50 -0
  59. package/nitrogen/generated/android/kotlin/com/margelo/nitro/rngooglemapsplus/RNIOSLocationAccuracy.kt +23 -0
  60. package/nitrogen/generated/android/kotlin/com/margelo/nitro/rngooglemapsplus/RNIOSLocationConfig.kt +32 -0
  61. package/nitrogen/generated/android/kotlin/com/margelo/nitro/rngooglemapsplus/RNInitialProps.kt +35 -0
  62. package/nitrogen/generated/android/kotlin/com/margelo/nitro/rngooglemapsplus/RNLocationConfig.kt +32 -0
  63. package/nitrogen/generated/android/kotlin/com/margelo/nitro/rngooglemapsplus/RNMapType.kt +24 -0
  64. package/nitrogen/generated/android/kotlin/com/margelo/nitro/rngooglemapsplus/RNMapUiSettings.kt +59 -0
  65. package/nitrogen/generated/android/kotlin/com/margelo/nitro/rngooglemapsplus/RNMarker.kt +1 -1
  66. package/nitrogen/generated/android/kotlin/com/margelo/nitro/rngooglemapsplus/RNPolygon.kt +4 -1
  67. package/nitrogen/generated/android/kotlin/com/margelo/nitro/rngooglemapsplus/RNPolyline.kt +4 -1
  68. package/nitrogen/generated/android/kotlin/com/margelo/nitro/rngooglemapsplus/views/HybridRNGoogleMapsPlusViewManager.kt +7 -1
  69. package/nitrogen/generated/ios/RNGoogleMapsPlus-Swift-Cxx-Bridge.hpp +296 -45
  70. package/nitrogen/generated/ios/RNGoogleMapsPlus-Swift-Cxx-Umbrella.hpp +27 -0
  71. package/nitrogen/generated/ios/c++/HybridRNGoogleMapsPlusViewSpecSwift.hpp +131 -37
  72. package/nitrogen/generated/ios/c++/views/HybridRNGoogleMapsPlusViewComponent.mm +61 -16
  73. package/nitrogen/generated/ios/swift/HybridRNGoogleMapsPlusViewSpec.swift +20 -11
  74. package/nitrogen/generated/ios/swift/HybridRNGoogleMapsPlusViewSpec_cxx.swift +378 -45
  75. package/nitrogen/generated/ios/swift/RNAndroidLocationConfig.swift +93 -0
  76. package/nitrogen/generated/ios/swift/RNAndroidLocationPriority.swift +48 -0
  77. package/nitrogen/generated/ios/swift/RNCircle.swift +198 -0
  78. package/nitrogen/generated/ios/swift/RNIOSLocationAccuracy.swift +48 -0
  79. package/nitrogen/generated/ios/swift/RNIOSLocationConfig.swift +70 -0
  80. package/nitrogen/generated/ios/swift/RNInitialProps.swift +107 -0
  81. package/nitrogen/generated/ios/swift/RNLocationConfig.swift +84 -0
  82. package/nitrogen/generated/ios/swift/RNMapType.swift +52 -0
  83. package/nitrogen/generated/ios/swift/RNMapUiSettings.swift +277 -0
  84. package/nitrogen/generated/ios/swift/RNMarker.swift +17 -5
  85. package/nitrogen/generated/ios/swift/RNPolygon.swift +40 -5
  86. package/nitrogen/generated/ios/swift/RNPolyline.swift +40 -5
  87. package/nitrogen/generated/shared/c++/HybridRNGoogleMapsPlusViewSpec.cpp +20 -2
  88. package/nitrogen/generated/shared/c++/HybridRNGoogleMapsPlusViewSpec.hpp +59 -26
  89. package/nitrogen/generated/shared/c++/RNAndroidLocationConfig.hpp +77 -0
  90. package/nitrogen/generated/shared/c++/RNAndroidLocationPriority.hpp +64 -0
  91. package/nitrogen/generated/shared/c++/RNCircle.hpp +98 -0
  92. package/nitrogen/generated/shared/c++/RNIOSLocationAccuracy.hpp +64 -0
  93. package/nitrogen/generated/shared/c++/RNIOSLocationConfig.hpp +73 -0
  94. package/nitrogen/generated/shared/c++/RNInitialProps.hpp +78 -0
  95. package/nitrogen/generated/shared/c++/RNLocationConfig.hpp +76 -0
  96. package/nitrogen/generated/shared/c++/RNMapType.hpp +88 -0
  97. package/nitrogen/generated/shared/c++/RNMapUiSettings.hpp +107 -0
  98. package/nitrogen/generated/shared/c++/RNMarker.hpp +6 -6
  99. package/nitrogen/generated/shared/c++/RNPolygon.hpp +10 -6
  100. package/nitrogen/generated/shared/c++/RNPolyline.hpp +10 -6
  101. package/nitrogen/generated/shared/c++/views/HybridRNGoogleMapsPlusViewComponent.cpp +138 -30
  102. package/nitrogen/generated/shared/c++/views/HybridRNGoogleMapsPlusViewComponent.hpp +27 -13
  103. package/nitrogen/generated/shared/json/RNGoogleMapsPlusViewConfig.json +10 -1
  104. package/package.json +5 -5
  105. package/src/RNGoogleMapsPlusView.nitro.ts +25 -11
  106. package/src/types.ts +67 -3
  107. package/ios/MapPolyline.swift +0 -83
@@ -2,6 +2,7 @@ package com.rngooglemapsplus
2
2
 
3
3
  import android.annotation.SuppressLint
4
4
  import android.location.Location
5
+ import android.widget.FrameLayout
5
6
  import com.facebook.react.bridge.LifecycleEventListener
6
7
  import com.facebook.react.bridge.UiThreadUtil
7
8
  import com.facebook.react.uimanager.PixelUtil.dpToPx
@@ -9,9 +10,11 @@ import com.facebook.react.uimanager.ThemedReactContext
9
10
  import com.google.android.gms.common.ConnectionResult
10
11
  import com.google.android.gms.maps.CameraUpdateFactory
11
12
  import com.google.android.gms.maps.GoogleMap
13
+ import com.google.android.gms.maps.GoogleMapOptions
12
14
  import com.google.android.gms.maps.MapView
13
- import com.google.android.gms.maps.OnMapReadyCallback
14
15
  import com.google.android.gms.maps.model.CameraPosition
16
+ import com.google.android.gms.maps.model.Circle
17
+ import com.google.android.gms.maps.model.CircleOptions
15
18
  import com.google.android.gms.maps.model.LatLng
16
19
  import com.google.android.gms.maps.model.LatLngBounds
17
20
  import com.google.android.gms.maps.model.MapColorScheme
@@ -22,59 +25,54 @@ import com.google.android.gms.maps.model.Polygon
22
25
  import com.google.android.gms.maps.model.PolygonOptions
23
26
  import com.google.android.gms.maps.model.Polyline
24
27
  import com.google.android.gms.maps.model.PolylineOptions
28
+ import com.rngooglemapsplus.extensions.toGooglePriority
29
+ import com.rngooglemapsplus.extensions.toLocationErrorCode
25
30
 
26
31
  class GoogleMapsViewImpl(
27
32
  val reactContext: ThemedReactContext,
28
33
  val locationHandler: LocationHandler,
29
34
  val playServiceHandler: PlayServicesHandler,
30
- val markerOptions: com.rngooglemapsplus.MarkerOptions,
31
- ) : MapView(reactContext),
35
+ val markerBuilder: MarkerBuilder,
36
+ ) : FrameLayout(reactContext),
32
37
  GoogleMap.OnCameraMoveStartedListener,
33
38
  GoogleMap.OnCameraMoveListener,
34
39
  GoogleMap.OnCameraIdleListener,
35
40
  GoogleMap.OnMapClickListener,
36
- OnMapReadyCallback,
37
41
  GoogleMap.OnMarkerClickListener,
42
+ GoogleMap.OnPolylineClickListener,
43
+ GoogleMap.OnPolygonClickListener,
44
+ GoogleMap.OnCircleClickListener,
38
45
  LifecycleEventListener {
46
+ private var initialized = false
47
+ private var mapReady = false
39
48
  private var googleMap: GoogleMap? = null
49
+ private var mapView: MapView? = null
40
50
 
41
- private var pendingBuildingEnabled: Boolean = false
42
- private var pendingTrafficEnabled: Boolean = false
43
- private var pendingCustomMapStyle: MapStyleOptions? = null
44
- private var pendingInitialCamera: CameraPosition =
45
- CameraPosition
46
- .builder()
47
- .target(
48
- LatLng(
49
- 0.0,
50
- 0.0,
51
- ),
52
- ).zoom(0f)
53
- .bearing(0f)
54
- .tilt(0f)
55
- .build()
56
- private var pendingUserInterfaceStyle: Int = MapColorScheme.FOLLOW_SYSTEM
57
- private var pendingMinZoomLevel: Double = 0.0
58
- private var pendingMaxZoomLevel: Double = 21.0
59
- private var pendingMapPadding: RNMapPadding = RNMapPadding(0.0, 0.0, 0.0, 0.0)
60
- private val pendingPolygons = mutableListOf<Pair<String, PolygonOptions>>()
61
- private val pendingPolylines = mutableListOf<Pair<String, PolylineOptions>>()
62
51
  private val pendingMarkers = mutableListOf<Pair<String, MarkerOptions>>()
63
- private var cameraMoveReason = -1
52
+ private val pendingPolylines = mutableListOf<Pair<String, PolylineOptions>>()
53
+ private val pendingPolygons = mutableListOf<Pair<String, PolygonOptions>>()
54
+ private val pendingCircles = mutableListOf<Pair<String, CircleOptions>>()
64
55
 
65
- private val polygonsById = mutableMapOf<String, Polygon>()
66
- private val polylinesById = mutableMapOf<String, Polyline>()
67
56
  private val markersById = mutableMapOf<String, Marker>()
57
+ private val polylinesById = mutableMapOf<String, Polyline>()
58
+ private val polygonsById = mutableMapOf<String, Polygon>()
59
+ private val circlesById = mutableMapOf<String, Circle>()
68
60
 
61
+ private var cameraMoveReason = -1
69
62
  private var lastSubmittedLocation: Location? = null
70
63
  private var lastSubmittedCameraPosition: CameraPosition? = null
71
64
 
72
65
  init {
73
66
  reactContext.addLifecycleEventListener(this)
74
- getMap()
75
67
  }
76
68
 
77
- private fun getMap() {
69
+ fun initMapView(
70
+ mapId: String?,
71
+ liteMode: Boolean?,
72
+ cameraPosition: CameraPosition?,
73
+ ) {
74
+ if (initialized) return
75
+ initialized = true
78
76
  val result = playServiceHandler.playServicesAvailability()
79
77
 
80
78
  when (result) {
@@ -103,8 +101,38 @@ class GoogleMapsViewImpl(
103
101
  onMapError?.invoke(RNMapErrorCode.UNKNOWN)
104
102
  }
105
103
 
106
- onCreate(null)
107
- getMapAsync(this@GoogleMapsViewImpl)
104
+ mapView =
105
+ MapView(
106
+ reactContext,
107
+ GoogleMapOptions().apply {
108
+ mapId?.let { mapId(it) }
109
+ liteMode?.let { liteMode(it) }
110
+ cameraPosition?.let {
111
+ camera(it)
112
+ }
113
+ },
114
+ )
115
+
116
+ super.addView(mapView)
117
+
118
+ mapView?.onCreate(null)
119
+ mapView?.getMapAsync { map ->
120
+ googleMap = map
121
+ googleMap?.setOnMapLoadedCallback {
122
+ googleMap?.setOnCameraMoveStartedListener(this@GoogleMapsViewImpl)
123
+ googleMap?.setOnCameraMoveListener(this@GoogleMapsViewImpl)
124
+ googleMap?.setOnCameraIdleListener(this@GoogleMapsViewImpl)
125
+ googleMap?.setOnMarkerClickListener(this@GoogleMapsViewImpl)
126
+ googleMap?.setOnPolylineClickListener(this@GoogleMapsViewImpl)
127
+ googleMap?.setOnPolygonClickListener(this@GoogleMapsViewImpl)
128
+ googleMap?.setOnCircleClickListener(this@GoogleMapsViewImpl)
129
+ googleMap?.setOnMapClickListener(this@GoogleMapsViewImpl)
130
+ }
131
+ initLocationCallbacks()
132
+ applyPending()
133
+ }
134
+ mapReady = true
135
+ onMapReady?.invoke(true)
108
136
  }
109
137
 
110
138
  override fun onCameraMoveStarted(reason: Int) {
@@ -195,22 +223,6 @@ class GoogleMapsViewImpl(
195
223
  )
196
224
  }
197
225
 
198
- @SuppressLint("PotentialBehaviorOverride")
199
- override fun onMapReady(map: GoogleMap) {
200
- googleMap = map
201
- googleMap?.setOnMapLoadedCallback {
202
- googleMap?.setOnCameraMoveStartedListener(this)
203
- googleMap?.setOnCameraMoveListener(this)
204
- googleMap?.setOnCameraIdleListener(this)
205
- googleMap?.setOnMarkerClickListener(this)
206
- googleMap?.setOnMapClickListener(this)
207
- }
208
- initLocationCallbacks()
209
- applyPending()
210
-
211
- onMapReady?.invoke(true)
212
- }
213
-
214
226
  fun initLocationCallbacks() {
215
227
  locationHandler.onUpdate = { location ->
216
228
  // / only the coordinated are relevant right now
@@ -235,27 +247,64 @@ class GoogleMapsViewImpl(
235
247
 
236
248
  fun applyPending() {
237
249
  onUi {
238
- googleMap?.setPadding(
239
- pendingMapPadding.left.dpToPx().toInt(),
240
- pendingMapPadding.top.dpToPx().toInt(),
241
- pendingMapPadding.right.dpToPx().toInt(),
242
- pendingMapPadding.bottom.dpToPx().toInt(),
243
- )
244
-
245
- pendingInitialCamera.let {
246
- googleMap?.moveCamera(
247
- CameraUpdateFactory.newCameraPosition(
248
- it,
249
- ),
250
+ mapPadding?.let {
251
+ googleMap?.setPadding(
252
+ it.left.dpToPx().toInt(),
253
+ it.top.dpToPx().toInt(),
254
+ it.right.dpToPx().toInt(),
255
+ it.bottom.dpToPx().toInt(),
250
256
  )
251
257
  }
252
258
 
253
- googleMap?.isBuildingsEnabled = pendingBuildingEnabled
254
- googleMap?.isTrafficEnabled = pendingTrafficEnabled
255
- googleMap?.setMapStyle(pendingCustomMapStyle)
256
- googleMap?.mapColorScheme = pendingUserInterfaceStyle
257
- googleMap?.setMinZoomPreference(pendingMinZoomLevel.toFloat())
258
- googleMap?.setMaxZoomPreference(pendingMaxZoomLevel.toFloat())
259
+ uiSettings?.let { v ->
260
+ googleMap?.uiSettings?.apply {
261
+ v.allGesturesEnabled?.let { setAllGesturesEnabled(it) }
262
+ v.compassEnabled?.let { isCompassEnabled = it }
263
+ v.indoorLevelPickerEnabled?.let { isIndoorLevelPickerEnabled = it }
264
+ v.mapToolbarEnabled?.let { isMapToolbarEnabled = it }
265
+ v.myLocationButtonEnabled?.let {
266
+ googleMap?.setLocationSource(locationHandler)
267
+ isMyLocationButtonEnabled = it
268
+ }
269
+ v.rotateEnabled?.let { isRotateGesturesEnabled = it }
270
+ v.scrollEnabled?.let { isScrollGesturesEnabled = it }
271
+ v.scrollDuringRotateOrZoomEnabled?.let {
272
+ isScrollGesturesEnabledDuringRotateOrZoom = it
273
+ }
274
+ v.tiltEnabled?.let { isTiltGesturesEnabled = it }
275
+ v.zoomControlsEnabled?.let { isZoomControlsEnabled = it }
276
+ v.zoomGesturesEnabled?.let { isZoomGesturesEnabled = it }
277
+ }
278
+ }
279
+
280
+ buildingEnabled?.let {
281
+ googleMap?.isBuildingsEnabled = it
282
+ }
283
+ trafficEnabled?.let {
284
+ googleMap?.isTrafficEnabled = it
285
+ }
286
+ indoorEnabled?.let {
287
+ googleMap?.isIndoorEnabled = it
288
+ }
289
+ googleMap?.setMapStyle(customMapStyle)
290
+ mapType?.let {
291
+ googleMap?.mapType = it
292
+ }
293
+ userInterfaceStyle?.let {
294
+ googleMap?.mapColorScheme = it
295
+ }
296
+ minZoomLevel?.let {
297
+ googleMap?.setMinZoomPreference(it.toFloat())
298
+ }
299
+ maxZoomLevel?.let {
300
+ googleMap?.setMaxZoomPreference(it.toFloat())
301
+ }
302
+ }
303
+
304
+ locationConfig?.let {
305
+ locationHandler.priority = it.android?.priority?.toGooglePriority()
306
+ locationHandler.interval = it.android?.interval?.toLong()
307
+ locationHandler.minUpdateInterval = it.android?.minUpdateInterval?.toLong()
259
308
  }
260
309
 
261
310
  if (pendingMarkers.isNotEmpty()) {
@@ -278,94 +327,212 @@ class GoogleMapsViewImpl(
278
327
  }
279
328
  pendingPolygons.clear()
280
329
  }
330
+
331
+ if (pendingCircles.isNotEmpty()) {
332
+ pendingCircles.forEach { (id, opts) ->
333
+ internalAddCircle(id, opts)
334
+ }
335
+ pendingCircles.clear()
336
+ }
281
337
  }
282
338
 
283
- var buildingEnabled: Boolean
284
- get() = googleMap?.isBuildingsEnabled ?: pendingBuildingEnabled
339
+ var uiSettings: RNMapUiSettings? = null
285
340
  set(value) {
286
- pendingBuildingEnabled = value
341
+ field = value
287
342
  onUi {
288
- googleMap?.isBuildingsEnabled = value
343
+ value?.let { v ->
344
+ googleMap?.uiSettings?.apply {
345
+ v.allGesturesEnabled?.let { setAllGesturesEnabled(it) }
346
+ v.compassEnabled?.let { isCompassEnabled = it }
347
+ v.indoorLevelPickerEnabled?.let { isIndoorLevelPickerEnabled = it }
348
+ v.mapToolbarEnabled?.let { isMapToolbarEnabled = it }
349
+ v.myLocationButtonEnabled?.let {
350
+ googleMap?.setLocationSource(locationHandler)
351
+ isMyLocationButtonEnabled = it
352
+ }
353
+ v.rotateEnabled?.let { isRotateGesturesEnabled = it }
354
+ v.scrollEnabled?.let { isScrollGesturesEnabled = it }
355
+ v.scrollDuringRotateOrZoomEnabled?.let {
356
+ isScrollGesturesEnabledDuringRotateOrZoom = it
357
+ }
358
+ v.tiltEnabled?.let { isTiltGesturesEnabled = it }
359
+ v.zoomControlsEnabled?.let { isZoomControlsEnabled = it }
360
+ v.zoomGesturesEnabled?.let { isZoomGesturesEnabled = it }
361
+ }
362
+ }
363
+ ?: run {
364
+ googleMap?.uiSettings?.apply {
365
+ setAllGesturesEnabled(true)
366
+ isCompassEnabled = false
367
+ isIndoorLevelPickerEnabled = false
368
+ isMapToolbarEnabled = false
369
+ isMyLocationButtonEnabled = false
370
+ googleMap?.setLocationSource(null)
371
+ isRotateGesturesEnabled = true
372
+ isScrollGesturesEnabled = true
373
+ isScrollGesturesEnabledDuringRotateOrZoom = true
374
+ isTiltGesturesEnabled = true
375
+ isZoomControlsEnabled = false
376
+ isZoomGesturesEnabled = false
377
+ }
378
+ }
289
379
  }
290
380
  }
291
381
 
292
- var trafficEnabled: Boolean
293
- get() = googleMap?.isTrafficEnabled ?: pendingTrafficEnabled
382
+ @SuppressLint("MissingPermission")
383
+ var myLocationEnabled: Boolean? = null
294
384
  set(value) {
295
- pendingTrafficEnabled = value
296
385
  onUi {
297
- googleMap?.isTrafficEnabled = value
386
+ try {
387
+ value?.let {
388
+ googleMap?.isMyLocationEnabled = it
389
+ }
390
+ ?: run {
391
+ googleMap?.isMyLocationEnabled = false
392
+ }
393
+ } catch (se: SecurityException) {
394
+ onLocationError?.invoke(RNLocationErrorCode.PERMISSION_DENIED)
395
+ } catch (ex: Exception) {
396
+ val error = ex.toLocationErrorCode(context)
397
+ onLocationError?.invoke(error)
398
+ }
298
399
  }
299
400
  }
300
401
 
301
- var customMapStyle: MapStyleOptions?
302
- get() = pendingCustomMapStyle
402
+ var buildingEnabled: Boolean? = null
303
403
  set(value) {
304
- pendingCustomMapStyle = value
404
+ field = value
305
405
  onUi {
306
- googleMap?.setMapStyle(value)
406
+ value?.let {
407
+ googleMap?.isBuildingsEnabled = it
408
+ }
409
+ ?: run {
410
+ googleMap?.isBuildingsEnabled = false
411
+ }
307
412
  }
308
413
  }
309
414
 
310
- var initialCamera: CameraPosition
311
- get() = pendingInitialCamera
415
+ var trafficEnabled: Boolean? = null
312
416
  set(value) {
313
- pendingInitialCamera = value
417
+ field = value
418
+ onUi {
419
+ value?.let {
420
+ googleMap?.isTrafficEnabled = it
421
+ } ?: run {
422
+ googleMap?.isTrafficEnabled = false
423
+ }
424
+ }
314
425
  }
315
426
 
316
- var userInterfaceStyle: Int
317
- get() = pendingUserInterfaceStyle
427
+ var indoorEnabled: Boolean? = null
318
428
  set(value) {
319
- pendingUserInterfaceStyle = value
429
+ field = value
320
430
  onUi {
321
- googleMap?.mapColorScheme = value
431
+ value?.let {
432
+ googleMap?.isIndoorEnabled = it
433
+ }
434
+ ?: run {
435
+ googleMap?.isIndoorEnabled = false
436
+ }
322
437
  }
323
438
  }
324
439
 
325
- var minZoomLevel: Double
326
- get() = pendingMinZoomLevel
440
+ var customMapStyle: MapStyleOptions? = null
327
441
  set(value) {
328
- pendingMinZoomLevel = value
442
+ field = value
329
443
  onUi {
330
- googleMap?.setMinZoomPreference(value.toFloat())
444
+ googleMap?.setMapStyle(value)
331
445
  }
332
446
  }
333
447
 
334
- var maxZoomLevel: Double
335
- get() = pendingMaxZoomLevel
448
+ var userInterfaceStyle: Int? = null
336
449
  set(value) {
337
- pendingMaxZoomLevel = value
450
+ field = value
338
451
  onUi {
339
- googleMap?.setMaxZoomPreference(value.toFloat())
452
+ value?.let {
453
+ googleMap?.mapColorScheme = it
454
+ } ?: run {
455
+ googleMap?.mapColorScheme = MapColorScheme.FOLLOW_SYSTEM
456
+ }
340
457
  }
341
458
  }
342
459
 
343
- var mapPadding: RNMapPadding
344
- get() = pendingMapPadding
460
+ var minZoomLevel: Double? = null
345
461
  set(value) {
346
- pendingMapPadding = value
462
+ field = value
347
463
  onUi {
348
- googleMap?.setPadding(
349
- value.left.dpToPx().toInt(),
350
- value.top.dpToPx().toInt(),
351
- value.right.dpToPx().toInt(),
352
- value.bottom.dpToPx().toInt(),
353
- )
464
+ value?.let {
465
+ googleMap?.setMinZoomPreference(it.toFloat())
466
+ } ?: run {
467
+ googleMap?.setMinZoomPreference(2.0f)
468
+ }
354
469
  }
355
470
  }
356
471
 
472
+ var maxZoomLevel: Double? = null
473
+ set(value) {
474
+ field = value
475
+ onUi {
476
+ value?.let {
477
+ googleMap?.setMaxZoomPreference(it.toFloat())
478
+ } ?: run {
479
+ googleMap?.setMaxZoomPreference(21.0f)
480
+ }
481
+ }
482
+ }
483
+
484
+ var mapPadding: RNMapPadding? = null
485
+ set(value) {
486
+ field = value
487
+ value?.let {
488
+ onUi {
489
+ googleMap?.setPadding(
490
+ it.left.dpToPx().toInt(),
491
+ it.top.dpToPx().toInt(),
492
+ it.right.dpToPx().toInt(),
493
+ it.bottom.dpToPx().toInt(),
494
+ )
495
+ }
496
+ } ?: run {
497
+ googleMap?.setPadding(0, 0, 0, 0)
498
+ }
499
+ }
500
+
501
+ var mapType: Int? = null
502
+ set(value) {
503
+ field = value
504
+ onUi {
505
+ value?.let {
506
+ googleMap?.mapType = it
507
+ } ?: run {
508
+ googleMap?.mapType = 1
509
+ }
510
+ }
511
+ }
512
+
513
+ var locationConfig: RNLocationConfig? = null
514
+ set(value) {
515
+ field = value
516
+ locationHandler.priority = value?.android?.priority?.toGooglePriority()
517
+ locationHandler.interval = value?.android?.interval?.toLong()
518
+ locationHandler.minUpdateInterval = value?.android?.minUpdateInterval?.toLong()
519
+ }
520
+
357
521
  var onMapError: ((RNMapErrorCode) -> Unit)? = null
358
522
  var onMapReady: ((Boolean) -> Unit)? = null
359
523
  var onLocationUpdate: ((RNLocation) -> Unit)? = null
360
524
  var onLocationError: ((RNLocationErrorCode) -> Unit)? = null
361
525
  var onMapPress: ((RNLatLng) -> Unit)? = null
362
526
  var onMarkerPress: ((String) -> Unit)? = null
527
+ var onPolylinePress: ((String) -> Unit)? = null
528
+ var onPolygonPress: ((String) -> Unit)? = null
529
+ var onCirclePress: ((String) -> Unit)? = null
363
530
  var onCameraChangeStart: ((RNRegion, RNCamera, Boolean) -> Unit)? = null
364
531
  var onCameraChange: ((RNRegion, RNCamera, Boolean) -> Unit)? = null
365
532
  var onCameraChangeComplete: ((RNRegion, RNCamera, Boolean) -> Unit)? = null
366
533
 
367
534
  fun setCamera(
368
- camera: RNCamera,
535
+ cameraPosition: CameraPosition,
369
536
  animated: Boolean,
370
537
  durationMS: Int,
371
538
  ) {
@@ -374,33 +541,8 @@ class GoogleMapsViewImpl(
374
541
  if (current == null) {
375
542
  return@onUi
376
543
  }
377
- val camPosBuilder =
378
- CameraPosition.Builder(
379
- current,
380
- )
381
544
 
382
- camera.center?.let {
383
- camPosBuilder.target(
384
- LatLng(
385
- it.latitude,
386
- it.longitude,
387
- ),
388
- )
389
- }
390
-
391
- camera.zoom?.let {
392
- camPosBuilder.zoom(it.toFloat())
393
- }
394
- camera.bearing?.let {
395
- camPosBuilder.bearing(it.toFloat())
396
- }
397
- camera.tilt?.let {
398
- camPosBuilder.tilt(it.toFloat())
399
- }
400
-
401
- val camPos = camPosBuilder.build()
402
-
403
- val update = CameraUpdateFactory.newCameraPosition(camPos)
545
+ val update = CameraUpdateFactory.newCameraPosition(cameraPosition)
404
546
 
405
547
  if (animated) {
406
548
  googleMap?.animateCamera(update, durationMS, null)
@@ -429,8 +571,8 @@ class GoogleMapsViewImpl(
429
571
  val latSpan = bounds.northeast.latitude - bounds.southwest.latitude
430
572
  val lngSpan = bounds.northeast.longitude - bounds.southwest.longitude
431
573
 
432
- val latPerPixel = latSpan / height
433
- val lngPerPixel = lngSpan / width
574
+ val latPerPixel = latSpan / (mapView?.height ?: 0)
575
+ val lngPerPixel = lngSpan / (mapView?.width ?: 0)
434
576
 
435
577
  builder.include(
436
578
  LatLng(
@@ -459,8 +601,10 @@ class GoogleMapsViewImpl(
459
601
 
460
602
  val paddedBounds = builder.build()
461
603
 
462
- val adjustedWidth = (width - padding.left.dpToPx() - padding.right.dpToPx()).toInt()
463
- val adjustedHeight = (height - padding.top.dpToPx() - padding.bottom.dpToPx()).toInt()
604
+ val adjustedWidth =
605
+ ((mapView?.width ?: 0) - padding.left.dpToPx() - padding.right.dpToPx()).toInt()
606
+ val adjustedHeight =
607
+ ((mapView?.height ?: 0) - padding.top.dpToPx() - padding.bottom.dpToPx()).toInt()
464
608
 
465
609
  val update =
466
610
  CameraUpdateFactory.newLatLngBounds(
@@ -639,22 +783,86 @@ class GoogleMapsViewImpl(
639
783
  pendingPolygons.clear()
640
784
  }
641
785
 
642
- fun clearAll() {
786
+ fun addCircle(
787
+ id: String,
788
+ opts: CircleOptions,
789
+ ) {
790
+ if (googleMap == null) {
791
+ pendingCircles.add(id to opts)
792
+ return
793
+ }
794
+
795
+ onUi {
796
+ circlesById.remove(id)?.remove()
797
+ }
798
+ internalAddCircle(id, opts)
799
+ }
800
+
801
+ private fun internalAddCircle(
802
+ id: String,
803
+ opts: CircleOptions,
804
+ ) {
805
+ onUi {
806
+ val circle =
807
+ googleMap?.addCircle(opts).also {
808
+ it?.tag = id
809
+ }
810
+ if (circle != null) {
811
+ circlesById[id] = circle
812
+ }
813
+ }
814
+ }
815
+
816
+ fun updateCircle(
817
+ id: String,
818
+ block: (Circle) -> Unit,
819
+ ) {
820
+ val circle = circlesById[id] ?: return
821
+ onUi {
822
+ block(circle)
823
+ }
824
+ }
825
+
826
+ fun removeCircle(id: String) {
643
827
  onUi {
644
- markerOptions.cancelAllJobs()
828
+ circlesById.remove(id)?.remove()
829
+ }
830
+ }
831
+
832
+ fun clearCircles() {
833
+ onUi {
834
+ circlesById.values.forEach { it.remove() }
835
+ }
836
+ circlesById.clear()
837
+ pendingCircles.clear()
838
+ }
839
+
840
+ fun destroyInternal() {
841
+ onUi {
842
+ markerBuilder.cancelAllJobs()
645
843
  clearMarkers()
646
844
  clearPolylines()
647
845
  clearPolygons()
846
+ clearCircles()
648
847
  locationHandler.stop()
649
848
  googleMap?.apply {
650
849
  setOnCameraMoveStartedListener(null)
651
850
  setOnCameraMoveListener(null)
652
851
  setOnCameraIdleListener(null)
653
852
  setOnMarkerClickListener(null)
853
+ setOnPolylineClickListener(null)
854
+ setOnPolygonClickListener(null)
855
+ setOnCircleClickListener(null)
654
856
  setOnMapClickListener(null)
655
857
  }
656
- this@GoogleMapsViewImpl.onDestroy()
657
858
  googleMap = null
859
+ mapView?.apply {
860
+ onPause()
861
+ onStop()
862
+ onDestroy()
863
+ removeAllViews()
864
+ }
865
+ super.removeAllViews()
658
866
  reactContext.removeLifecycleEventListener(this)
659
867
  }
660
868
  }
@@ -684,19 +892,19 @@ class GoogleMapsViewImpl(
684
892
  override fun onHostResume() {
685
893
  onUi {
686
894
  locationHandler.start()
687
- this@GoogleMapsViewImpl.onResume()
895
+ mapView?.onResume()
688
896
  }
689
897
  }
690
898
 
691
899
  override fun onHostPause() {
692
900
  onUi {
693
901
  locationHandler.stop()
694
- this@GoogleMapsViewImpl.onPause()
902
+ mapView?.onPause()
695
903
  }
696
904
  }
697
905
 
698
906
  override fun onHostDestroy() {
699
- clearAll()
907
+ destroyInternal()
700
908
  }
701
909
 
702
910
  override fun onMarkerClick(marker: Marker): Boolean {
@@ -704,6 +912,18 @@ class GoogleMapsViewImpl(
704
912
  return true
705
913
  }
706
914
 
915
+ override fun onPolylineClick(polyline: Polyline) {
916
+ onPolylinePress?.invoke(polyline.tag?.toString() ?: "unknown")
917
+ }
918
+
919
+ override fun onPolygonClick(polygon: Polygon) {
920
+ onPolygonPress?.invoke(polygon.tag?.toString() ?: "unknown")
921
+ }
922
+
923
+ override fun onCircleClick(circle: Circle) {
924
+ onCirclePress?.invoke(circle.tag?.toString() ?: "unknown")
925
+ }
926
+
707
927
  override fun onMapClick(coordinates: LatLng) {
708
928
  onMapPress?.invoke(
709
929
  RNLatLng(coordinates.latitude, coordinates.longitude),