react-native-google-maps-plus 1.3.0-dev.7 → 1.3.0-dev.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 (52) hide show
  1. package/android/src/main/java/com/rngooglemapsplus/GoogleMapsViewImpl.kt +24 -78
  2. package/android/src/main/java/com/rngooglemapsplus/LocationHandler.kt +38 -36
  3. package/android/src/main/java/com/rngooglemapsplus/MapCircleBuilder.kt +31 -8
  4. package/android/src/main/java/com/rngooglemapsplus/MapMarkerBuilder.kt +69 -18
  5. package/android/src/main/java/com/rngooglemapsplus/MapPolygonBuilder.kt +53 -14
  6. package/android/src/main/java/com/rngooglemapsplus/MapPolylineBuilder.kt.kt +44 -11
  7. package/android/src/main/java/com/rngooglemapsplus/RNGoogleMapsPlusView.kt +4 -4
  8. package/android/src/main/java/com/rngooglemapsplus/extensions/LocationExtension.kt +59 -0
  9. package/ios/GoogleMapViewImpl.swift +17 -63
  10. package/ios/MapCircleBuilder.swift +29 -9
  11. package/ios/MapMarkerBuilder.swift +59 -18
  12. package/ios/MapPolygonBuilder.swift +50 -16
  13. package/ios/MapPolylineBuilder.swift +31 -15
  14. package/ios/RNGoogleMapsPlusView.swift +9 -3
  15. package/ios/extensions/CLLocation+Extension.swift +27 -0
  16. package/lib/module/GoogleMapsPlus.js +7 -0
  17. package/lib/module/GoogleMapsPlus.js.map +1 -0
  18. package/lib/module/index.js +3 -5
  19. package/lib/module/index.js.map +1 -1
  20. package/lib/module/types.js.map +1 -1
  21. package/lib/nitrogen/generated/shared/json/RNGoogleMapsPlusViewConfig.json +44 -0
  22. package/lib/typescript/src/GoogleMapsPlus.d.ts +5 -0
  23. package/lib/typescript/src/GoogleMapsPlus.d.ts.map +1 -0
  24. package/lib/typescript/src/index.d.ts +3 -3
  25. package/lib/typescript/src/index.d.ts.map +1 -1
  26. package/lib/typescript/src/types.d.ts +25 -0
  27. package/lib/typescript/src/types.d.ts.map +1 -1
  28. package/nitrogen/generated/android/c++/JFunc_void_RNLocation.hpp +6 -0
  29. package/nitrogen/generated/android/c++/JHybridRNGoogleMapsPlusViewSpec.cpp +8 -0
  30. package/nitrogen/generated/android/c++/JRNLocation.hpp +32 -2
  31. package/nitrogen/generated/android/c++/JRNLocationAndroid.hpp +82 -0
  32. package/nitrogen/generated/android/c++/JRNLocationIOS.hpp +77 -0
  33. package/nitrogen/generated/android/kotlin/com/margelo/nitro/rngooglemapsplus/RNLocation.kt +19 -1
  34. package/nitrogen/generated/android/kotlin/com/margelo/nitro/rngooglemapsplus/RNLocationAndroid.kt +50 -0
  35. package/nitrogen/generated/android/kotlin/com/margelo/nitro/rngooglemapsplus/RNLocationIOS.kt +47 -0
  36. package/nitrogen/generated/android/kotlin/com/margelo/nitro/rngooglemapsplus/views/HybridRNGoogleMapsPlusViewManager.kt +7 -2
  37. package/nitrogen/generated/ios/RNGoogleMapsPlus-Swift-Cxx-Bridge.hpp +36 -0
  38. package/nitrogen/generated/ios/RNGoogleMapsPlus-Swift-Cxx-Umbrella.hpp +6 -0
  39. package/nitrogen/generated/ios/c++/HybridRNGoogleMapsPlusViewSpecSwift.hpp +6 -0
  40. package/nitrogen/generated/ios/c++/views/HybridRNGoogleMapsPlusViewComponent.mm +8 -0
  41. package/nitrogen/generated/ios/swift/RNLocation.swift +92 -2
  42. package/nitrogen/generated/ios/swift/RNLocationAndroid.swift +215 -0
  43. package/nitrogen/generated/ios/swift/RNLocationIOS.swift +185 -0
  44. package/nitrogen/generated/shared/c++/RNLocation.hpp +33 -2
  45. package/nitrogen/generated/shared/c++/RNLocationAndroid.hpp +104 -0
  46. package/nitrogen/generated/shared/c++/RNLocationIOS.hpp +99 -0
  47. package/package.json +6 -13
  48. package/src/GoogleMapsPlus.tsx +20 -0
  49. package/src/index.tsx +6 -14
  50. package/src/types.ts +27 -0
  51. package/lib/module/package.json +0 -1
  52. package/lib/typescript/package.json +0 -1
@@ -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
@@ -40,6 +39,7 @@ import com.rngooglemapsplus.extensions.toLocationErrorCode
40
39
  import com.rngooglemapsplus.extensions.toRNIndoorBuilding
41
40
  import com.rngooglemapsplus.extensions.toRNIndoorLevel
42
41
  import com.rngooglemapsplus.extensions.toRnLatLng
42
+ import com.rngooglemapsplus.extensions.toRnLocation
43
43
  import java.io.ByteArrayInputStream
44
44
  import java.io.ByteArrayOutputStream
45
45
  import java.io.File
@@ -65,6 +65,7 @@ class GoogleMapsViewImpl(
65
65
  LifecycleEventListener {
66
66
  private var initialized = false
67
67
  private var mapReady = false
68
+ private var destroyed = false
68
69
  private var googleMap: GoogleMap? = null
69
70
  private var mapView: MapView? = null
70
71
 
@@ -83,7 +84,6 @@ class GoogleMapsViewImpl(
83
84
  private val kmlLayersById = mutableMapOf<String, KmlLayer>()
84
85
 
85
86
  private var cameraMoveReason = -1
86
- private var lastSubmittedLocation: Location? = null
87
87
  private var lastSubmittedCameraPosition: CameraPosition? = null
88
88
 
89
89
  init {
@@ -143,8 +143,8 @@ class GoogleMapsViewImpl(
143
143
  googleMap?.setOnMapClickListener(this@GoogleMapsViewImpl)
144
144
  googleMap?.setOnMarkerDragListener(this@GoogleMapsViewImpl)
145
145
  }
146
+ applyProps()
146
147
  initLocationCallbacks()
147
- applyPending()
148
148
  mapReady = true
149
149
  onMapReady?.invoke(true)
150
150
  }
@@ -241,18 +241,7 @@ class GoogleMapsViewImpl(
241
241
 
242
242
  fun initLocationCallbacks() {
243
243
  locationHandler.onUpdate = { location ->
244
- // / only the coordinated are relevant right now
245
- if (lastSubmittedLocation?.latitude != location.latitude || lastSubmittedLocation?.longitude != location.longitude ||
246
- lastSubmittedLocation?.bearing != location.bearing
247
- ) {
248
- onLocationUpdate?.invoke(
249
- RNLocation(
250
- RNLatLng(location.latitude, location.longitude),
251
- location.bearing.toDouble(),
252
- ),
253
- )
254
- }
255
- lastSubmittedLocation = location
244
+ onLocationUpdate?.invoke(location.toRnLocation())
256
245
  }
257
246
 
258
247
  locationHandler.onError = { error ->
@@ -261,65 +250,18 @@ class GoogleMapsViewImpl(
261
250
  locationHandler.start()
262
251
  }
263
252
 
264
- fun applyPending() {
265
- onUi {
266
- mapPadding?.let {
267
- googleMap?.setPadding(
268
- it.left.dpToPx().toInt(),
269
- it.top.dpToPx().toInt(),
270
- it.right.dpToPx().toInt(),
271
- it.bottom.dpToPx().toInt(),
272
- )
273
- }
274
-
275
- uiSettings?.let { v ->
276
- googleMap?.uiSettings?.apply {
277
- v.allGesturesEnabled?.let { setAllGesturesEnabled(it) }
278
- v.compassEnabled?.let { isCompassEnabled = it }
279
- v.indoorLevelPickerEnabled?.let { isIndoorLevelPickerEnabled = it }
280
- v.mapToolbarEnabled?.let { isMapToolbarEnabled = it }
281
- v.myLocationButtonEnabled?.let {
282
- googleMap?.setLocationSource(locationHandler)
283
- isMyLocationButtonEnabled = it
284
- }
285
- v.rotateEnabled?.let { isRotateGesturesEnabled = it }
286
- v.scrollEnabled?.let { isScrollGesturesEnabled = it }
287
- v.scrollDuringRotateOrZoomEnabled?.let {
288
- isScrollGesturesEnabledDuringRotateOrZoom = it
289
- }
290
- v.tiltEnabled?.let { isTiltGesturesEnabled = it }
291
- v.zoomControlsEnabled?.let { isZoomControlsEnabled = it }
292
- v.zoomGesturesEnabled?.let { isZoomGesturesEnabled = it }
293
- }
294
- }
295
-
296
- buildingEnabled?.let {
297
- googleMap?.isBuildingsEnabled = it
298
- }
299
- trafficEnabled?.let {
300
- googleMap?.isTrafficEnabled = it
301
- }
302
- indoorEnabled?.let {
303
- googleMap?.isIndoorEnabled = it
304
- }
305
- googleMap?.setMapStyle(customMapStyle)
306
- mapType?.let {
307
- googleMap?.mapType = it
308
- }
309
- userInterfaceStyle?.let {
310
- googleMap?.mapColorScheme = it
311
- }
312
- mapZoomConfig?.let {
313
- googleMap?.setMinZoomPreference(it.min?.toFloat() ?: 2.0f)
314
- googleMap?.setMaxZoomPreference(it.max?.toFloat() ?: 21.0f)
315
- }
316
- }
317
-
318
- locationConfig?.let {
319
- locationHandler.priority = it.android?.priority?.toGooglePriority()
320
- locationHandler.interval = it.android?.interval?.toLong()
321
- locationHandler.minUpdateInterval = it.android?.minUpdateInterval?.toLong()
322
- }
253
+ fun applyProps() {
254
+ mapPadding = mapPadding
255
+ uiSettings = uiSettings
256
+ myLocationEnabled = myLocationEnabled
257
+ buildingEnabled = buildingEnabled
258
+ trafficEnabled = trafficEnabled
259
+ indoorEnabled = indoorEnabled
260
+ customMapStyle = customMapStyle
261
+ mapType = mapType
262
+ userInterfaceStyle = userInterfaceStyle
263
+ mapZoomConfig = mapZoomConfig
264
+ locationConfig = locationConfig
323
265
 
324
266
  if (pendingMarkers.isNotEmpty()) {
325
267
  pendingMarkers.forEach { (id, opts) ->
@@ -480,9 +422,11 @@ class GoogleMapsViewImpl(
480
422
  var locationConfig: RNLocationConfig? = null
481
423
  set(value) {
482
424
  field = value
483
- locationHandler.priority = value?.android?.priority?.toGooglePriority()
484
- locationHandler.interval = value?.android?.interval?.toLong()
485
- locationHandler.minUpdateInterval = value?.android?.minUpdateInterval?.toLong()
425
+ locationHandler.updateConfig(
426
+ value?.android?.priority?.toGooglePriority(),
427
+ value?.android?.interval?.toLong(),
428
+ value?.android?.minUpdateInterval?.toLong(),
429
+ )
486
430
  }
487
431
 
488
432
  var onMapError: ((RNMapErrorCode) -> Unit)? = null
@@ -919,7 +863,7 @@ class GoogleMapsViewImpl(
919
863
  onUi {
920
864
  heatmapsById.values.forEach { it.remove() }
921
865
  }
922
- circlesById.clear()
866
+ heatmapsById.clear()
923
867
  pendingHeatmaps.clear()
924
868
  }
925
869
 
@@ -968,6 +912,8 @@ class GoogleMapsViewImpl(
968
912
  }
969
913
 
970
914
  fun destroyInternal() {
915
+ if (destroyed) return
916
+ destroyed = true
971
917
  onUi {
972
918
  locationHandler.stop()
973
919
  markerBuilder.cancelAllJobs()
@@ -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
  }
@@ -20,15 +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 = next.center.toLatLng()
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.isClickable = next.pressable ?: false
32
- 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
+ }
33
56
  }
34
57
  }
@@ -54,33 +54,84 @@ class MapMarkerBuilder(
54
54
  }
55
55
 
56
56
  fun update(
57
- marker: Marker,
58
57
  prev: RNMarker,
59
58
  next: RNMarker,
59
+ marker: Marker,
60
60
  ) {
61
- marker.position =
62
- next.coordinate.toLatLng()
61
+ if (prev.coordinate.latitude != next.coordinate.latitude ||
62
+ prev.coordinate.longitude != next.coordinate.longitude
63
+ ) {
64
+ marker.position = next.coordinate.toLatLng()
65
+ }
63
66
 
64
67
  if (!prev.markerStyleEquals(next)) {
65
68
  buildIconAsync(marker.id, next) { icon ->
66
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
+ }
67
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
68
134
  }
69
- marker.title = next.title
70
- marker.snippet = next.snippet
71
- marker.alpha = next.opacity?.toFloat() ?: 1f
72
- marker.isFlat = next.flat ?: false
73
- marker.isDraggable = next.draggable ?: false
74
- marker.rotation = next.rotation?.toFloat() ?: 0f
75
- marker.setInfoWindowAnchor(
76
- (next.infoWindowAnchor?.x ?: 0.5).toFloat(),
77
- (next.infoWindowAnchor?.y ?: 0).toFloat(),
78
- )
79
- marker.setAnchor(
80
- (next.anchor?.x ?: 0.5).toFloat(),
81
- (next.anchor?.y ?: 1.0).toFloat(),
82
- )
83
- marker.zIndex = next.zIndex?.toFloat() ?: 0f
84
135
  }
85
136
 
86
137
  fun buildIconAsync(
@@ -27,21 +27,60 @@ class MapPolygonBuilder {
27
27
  }
28
28
 
29
29
  fun update(
30
- poly: Polygon,
30
+ prev: RNPolygon,
31
31
  next: RNPolygon,
32
+ poly: Polygon,
32
33
  ) {
33
- poly.points =
34
- next.coordinates.map {
35
- it.toLatLng()
36
- }
37
- poly.fillColor = next.fillColor?.toColor() ?: Color.TRANSPARENT
38
- poly.strokeColor = next.strokeColor?.toColor() ?: Color.BLACK
39
- poly.strokeWidth = next.strokeWidth?.dpToPx() ?: 1f
40
- poly.isClickable = next.pressable ?: false
41
- poly.isGeodesic = next.geodesic ?: false
42
- poly.holes = next.holes?.map { hole ->
43
- hole.coordinates.map { it.toLatLng() }
44
- } ?: emptyList()
45
- poly.zIndex = next.zIndex?.toFloat() ?: 0f
34
+ val coordsChanged =
35
+ prev.coordinates.size != next.coordinates.size ||
36
+ !prev.coordinates.zip(next.coordinates).all { (a, b) ->
37
+ a.latitude == b.latitude && a.longitude == b.longitude
38
+ }
39
+
40
+ if (coordsChanged) {
41
+ poly.points = next.coordinates.map { it.toLatLng() }
42
+ }
43
+
44
+ val prevHoles = prev.holes?.toList() ?: emptyList()
45
+ val nextHoles = next.holes?.toList() ?: emptyList()
46
+ val holesChanged =
47
+ prevHoles.size != nextHoles.size ||
48
+ !prevHoles.zip(nextHoles).all { (ha, hb) ->
49
+ ha.coordinates.size == hb.coordinates.size &&
50
+ ha.coordinates.zip(hb.coordinates).all { (a, b) ->
51
+ a.latitude == b.latitude && a.longitude == b.longitude
52
+ }
53
+ }
54
+
55
+ if (holesChanged) {
56
+ poly.holes =
57
+ nextHoles.map { hole ->
58
+ hole.coordinates.map { it.toLatLng() }
59
+ }
60
+ }
61
+
62
+ if (prev.fillColor != next.fillColor) {
63
+ poly.fillColor = next.fillColor?.toColor() ?: Color.TRANSPARENT
64
+ }
65
+
66
+ if (prev.strokeColor != next.strokeColor) {
67
+ poly.strokeColor = next.strokeColor?.toColor() ?: Color.BLACK
68
+ }
69
+
70
+ if (prev.strokeWidth != next.strokeWidth) {
71
+ poly.strokeWidth = next.strokeWidth?.dpToPx() ?: 1f
72
+ }
73
+
74
+ if (prev.pressable != next.pressable) {
75
+ poly.isClickable = next.pressable ?: false
76
+ }
77
+
78
+ if (prev.geodesic != next.geodesic) {
79
+ poly.isGeodesic = next.geodesic ?: false
80
+ }
81
+
82
+ if (prev.zIndex != next.zIndex) {
83
+ poly.zIndex = next.zIndex?.toFloat() ?: 0f
84
+ }
46
85
  }
47
86
  }
@@ -31,19 +31,52 @@ class MapPolylineBuilder {
31
31
  }
32
32
 
33
33
  fun update(
34
- polyline: Polyline,
34
+ prev: RNPolyline,
35
35
  next: RNPolyline,
36
+ polyline: Polyline,
36
37
  ) {
37
- polyline.points = next.coordinates.map { it.toLatLng() }
38
- polyline.width = next.width?.dpToPx() ?: 1f
39
- val cap = mapLineCap(next.lineCap ?: RNLineCapType.BUTT)
40
- polyline.startCap = cap
41
- polyline.endCap = cap
42
- polyline.jointType = mapLineJoin(next.lineJoin ?: RNLineJoinType.MITER)
43
- polyline.color = next.color?.toColor() ?: Color.BLACK
44
- polyline.isClickable = next.pressable ?: false
45
- polyline.isGeodesic = next.geodesic ?: false
46
- polyline.zIndex = next.zIndex?.toFloat() ?: 0f
38
+ val coordsChanged =
39
+ prev.coordinates.size != next.coordinates.size ||
40
+ !prev.coordinates.zip(next.coordinates).all { (a, b) ->
41
+ a.latitude == b.latitude && a.longitude == b.longitude
42
+ }
43
+
44
+ if (coordsChanged) {
45
+ polyline.points = next.coordinates.map { it.toLatLng() }
46
+ }
47
+
48
+ if (prev.width != next.width) {
49
+ polyline.width = next.width?.dpToPx() ?: 1f
50
+ }
51
+
52
+ val newCap = mapLineCap(next.lineCap ?: RNLineCapType.BUTT)
53
+ val prevCap = mapLineCap(prev.lineCap ?: RNLineCapType.BUTT)
54
+ if (newCap != prevCap) {
55
+ polyline.startCap = newCap
56
+ polyline.endCap = newCap
57
+ }
58
+
59
+ val newJoin = mapLineJoin(next.lineJoin ?: RNLineJoinType.MITER)
60
+ val prevJoin = mapLineJoin(prev.lineJoin ?: RNLineJoinType.MITER)
61
+ if (newJoin != prevJoin) {
62
+ polyline.jointType = newJoin
63
+ }
64
+
65
+ if (prev.color != next.color) {
66
+ polyline.color = next.color?.toColor() ?: Color.BLACK
67
+ }
68
+
69
+ if (prev.pressable != next.pressable) {
70
+ polyline.isClickable = next.pressable ?: false
71
+ }
72
+
73
+ if (prev.geodesic != next.geodesic) {
74
+ polyline.isGeodesic = next.geodesic ?: false
75
+ }
76
+
77
+ if (prev.zIndex != next.zIndex) {
78
+ polyline.zIndex = next.zIndex?.toFloat() ?: 0f
79
+ }
47
80
  }
48
81
 
49
82
  private fun mapLineCap(type: RNLineCapType?): Cap =
@@ -157,7 +157,7 @@ class RNGoogleMapsPlusView(
157
157
  } else if (!prev.markerEquals(next)) {
158
158
  view.updateMarker(id) { marker ->
159
159
  onUi {
160
- markerBuilder.update(marker, next, prev)
160
+ markerBuilder.update(prev, next, marker)
161
161
  }
162
162
  }
163
163
  }
@@ -181,7 +181,7 @@ class RNGoogleMapsPlusView(
181
181
  } else if (!prev.polylineEquals(next)) {
182
182
  view.updatePolyline(id) { polyline ->
183
183
  onUi {
184
- polylineBuilder.update(polyline, next)
184
+ polylineBuilder.update(prev, next, polyline)
185
185
  }
186
186
  }
187
187
  }
@@ -205,7 +205,7 @@ class RNGoogleMapsPlusView(
205
205
  view.addPolygon(id, polygonBuilder.build(next))
206
206
  } else if (!prev.polygonEquals(next)) {
207
207
  view.updatePolygon(id) { polygon ->
208
- onUi { polygonBuilder.update(polygon, next) }
208
+ onUi { polygonBuilder.update(prev, next, polygon) }
209
209
  }
210
210
  }
211
211
  }
@@ -229,7 +229,7 @@ class RNGoogleMapsPlusView(
229
229
  } else if (!prev.circleEquals(next)) {
230
230
  view.updateCircle(id) { circle ->
231
231
  onUi {
232
- circleBuilder.update(circle, next)
232
+ circleBuilder.update(prev, next, circle)
233
233
  }
234
234
  }
235
235
  }
@@ -0,0 +1,59 @@
1
+ package com.rngooglemapsplus.extensions
2
+
3
+ import android.location.Location
4
+ import android.os.Build
5
+ import com.rngooglemapsplus.RNLatLng
6
+ import com.rngooglemapsplus.RNLocation
7
+ import com.rngooglemapsplus.RNLocationAndroid
8
+
9
+ fun Location.toRnLocation(): RNLocation =
10
+ RNLocation(
11
+ center = RNLatLng(latitude, longitude),
12
+ altitude = altitude,
13
+ accuracy = accuracy.toDouble(),
14
+ bearing = bearing.toDouble(),
15
+ speed = speed.toDouble(),
16
+ time = time.toDouble(),
17
+ android =
18
+ RNLocationAndroid(
19
+ provider = provider,
20
+ elapsedRealtimeNanos = elapsedRealtimeNanos.toDouble(),
21
+ bearingAccuracyDegrees =
22
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
23
+ bearingAccuracyDegrees.toDouble()
24
+ } else {
25
+ null
26
+ },
27
+ speedAccuracyMetersPerSecond =
28
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
29
+ speedAccuracyMetersPerSecond.toDouble()
30
+ } else {
31
+ null
32
+ },
33
+ verticalAccuracyMeters =
34
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
35
+ verticalAccuracyMeters.toDouble()
36
+ } else {
37
+ null
38
+ },
39
+ mslAltitudeMeters =
40
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
41
+ mslAltitudeMeters
42
+ } else {
43
+ null
44
+ },
45
+ mslAltitudeAccuracyMeters =
46
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
47
+ mslAltitudeAccuracyMeters.toDouble()
48
+ } else {
49
+ null
50
+ },
51
+ isMock =
52
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
53
+ isMock
54
+ } else {
55
+ isFromMockProvider
56
+ },
57
+ ),
58
+ ios = null,
59
+ )