react-native-google-maps-plus 1.4.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 (61) hide show
  1. package/android/src/main/java/com/rngooglemapsplus/GoogleMapsViewImpl.kt +41 -144
  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/CameraPositionExtension.kt +12 -0
  9. package/android/src/main/java/com/rngooglemapsplus/extensions/IntExtension.kt +28 -0
  10. package/android/src/main/java/com/rngooglemapsplus/extensions/LatLngBounds.kt +15 -0
  11. package/android/src/main/java/com/rngooglemapsplus/extensions/LocationExtension.kt +59 -0
  12. package/ios/GoogleMapViewImpl.swift +28 -138
  13. package/ios/LocationHandler.swift +5 -13
  14. package/ios/MapCircleBuilder.swift +29 -9
  15. package/ios/MapHelper.swift +20 -0
  16. package/ios/MapMarkerBuilder.swift +101 -84
  17. package/ios/MapPolygonBuilder.swift +50 -16
  18. package/ios/MapPolylineBuilder.swift +31 -15
  19. package/ios/RNGoogleMapsPlusView.swift +15 -11
  20. package/ios/extensions/CLError+Extension.swift +14 -0
  21. package/ios/extensions/CLLocation+Extension.swift +27 -0
  22. package/ios/extensions/GMSCameraPosition+Extension.swift +12 -0
  23. package/ios/extensions/GMSCoordinateBounds+Extension.swift +19 -0
  24. package/ios/extensions/RNMarker+Extension.swift +2 -3
  25. package/lib/module/GoogleMapsPlus.js +7 -0
  26. package/lib/module/GoogleMapsPlus.js.map +1 -0
  27. package/lib/module/index.js +3 -5
  28. package/lib/module/index.js.map +1 -1
  29. package/lib/module/types.js.map +1 -1
  30. package/lib/nitrogen/generated/shared/json/RNGoogleMapsPlusViewConfig.json +44 -0
  31. package/lib/typescript/src/GoogleMapsPlus.d.ts +5 -0
  32. package/lib/typescript/src/GoogleMapsPlus.d.ts.map +1 -0
  33. package/lib/typescript/src/index.d.ts +3 -3
  34. package/lib/typescript/src/index.d.ts.map +1 -1
  35. package/lib/typescript/src/types.d.ts +25 -0
  36. package/lib/typescript/src/types.d.ts.map +1 -1
  37. package/nitrogen/generated/android/c++/JFunc_void_RNLocation.hpp +6 -0
  38. package/nitrogen/generated/android/c++/JHybridRNGoogleMapsPlusViewSpec.cpp +8 -0
  39. package/nitrogen/generated/android/c++/JRNLocation.hpp +32 -2
  40. package/nitrogen/generated/android/c++/JRNLocationAndroid.hpp +82 -0
  41. package/nitrogen/generated/android/c++/JRNLocationIOS.hpp +77 -0
  42. package/nitrogen/generated/android/kotlin/com/margelo/nitro/rngooglemapsplus/RNLocation.kt +19 -1
  43. package/nitrogen/generated/android/kotlin/com/margelo/nitro/rngooglemapsplus/RNLocationAndroid.kt +50 -0
  44. package/nitrogen/generated/android/kotlin/com/margelo/nitro/rngooglemapsplus/RNLocationIOS.kt +47 -0
  45. package/nitrogen/generated/android/kotlin/com/margelo/nitro/rngooglemapsplus/views/HybridRNGoogleMapsPlusViewManager.kt +7 -2
  46. package/nitrogen/generated/ios/RNGoogleMapsPlus-Swift-Cxx-Bridge.hpp +36 -0
  47. package/nitrogen/generated/ios/RNGoogleMapsPlus-Swift-Cxx-Umbrella.hpp +6 -0
  48. package/nitrogen/generated/ios/c++/HybridRNGoogleMapsPlusViewSpecSwift.hpp +6 -0
  49. package/nitrogen/generated/ios/c++/views/HybridRNGoogleMapsPlusViewComponent.mm +8 -0
  50. package/nitrogen/generated/ios/swift/RNLocation.swift +92 -2
  51. package/nitrogen/generated/ios/swift/RNLocationAndroid.swift +215 -0
  52. package/nitrogen/generated/ios/swift/RNLocationIOS.swift +185 -0
  53. package/nitrogen/generated/shared/c++/RNLocation.hpp +33 -2
  54. package/nitrogen/generated/shared/c++/RNLocationAndroid.hpp +104 -0
  55. package/nitrogen/generated/shared/c++/RNLocationIOS.hpp +99 -0
  56. package/package.json +6 -13
  57. package/src/GoogleMapsPlus.tsx +20 -0
  58. package/src/index.tsx +6 -14
  59. package/src/types.ts +27 -0
  60. package/lib/module/package.json +0 -1
  61. package/lib/typescript/package.json +0 -1
@@ -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,12 @@
1
+ package com.rngooglemapsplus.extensions
2
+
3
+ import com.google.android.gms.maps.model.CameraPosition
4
+ import com.rngooglemapsplus.RNCamera
5
+
6
+ fun CameraPosition.toRnCamera(): RNCamera =
7
+ RNCamera(
8
+ center = target.toRnLatLng(),
9
+ zoom = zoom.toDouble(),
10
+ bearing = bearing.toDouble(),
11
+ tilt = tilt.toDouble(),
12
+ )
@@ -0,0 +1,28 @@
1
+ package com.rngooglemapsplus.extensions
2
+
3
+ import com.google.android.gms.common.ConnectionResult
4
+ import com.rngooglemapsplus.RNMapErrorCode
5
+
6
+ fun Int.toRNMapErrorCodeOrNull(): RNMapErrorCode? =
7
+ when (this) {
8
+ ConnectionResult.SERVICE_MISSING ->
9
+ RNMapErrorCode.PLAY_SERVICES_MISSING
10
+
11
+ ConnectionResult.SERVICE_INVALID ->
12
+ RNMapErrorCode.PLAY_SERVICES_INVALID
13
+
14
+ ConnectionResult.SERVICE_VERSION_UPDATE_REQUIRED ->
15
+ RNMapErrorCode.PLAY_SERVICES_OUTDATED
16
+
17
+ ConnectionResult.SERVICE_UPDATING ->
18
+ RNMapErrorCode.PLAY_SERVICE_UPDATING
19
+
20
+ ConnectionResult.SERVICE_DISABLED ->
21
+ RNMapErrorCode.PLAY_SERVICES_DISABLED
22
+
23
+ ConnectionResult.SUCCESS ->
24
+ null
25
+
26
+ else ->
27
+ RNMapErrorCode.UNKNOWN
28
+ }
@@ -0,0 +1,15 @@
1
+ package com.rngooglemapsplus.extensions
2
+
3
+ import com.google.android.gms.maps.model.LatLngBounds
4
+ import com.rngooglemapsplus.RNRegion
5
+
6
+ fun LatLngBounds.toRnRegion(): RNRegion {
7
+ val latDelta = northeast.latitude - southwest.latitude
8
+ val lngDelta = northeast.longitude - southwest.longitude
9
+
10
+ return RNRegion(
11
+ center = center.toRnLatLng(),
12
+ latitudeDelta = latDelta,
13
+ longitudeDelta = lngDelta,
14
+ )
15
+ }
@@ -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
+ )
@@ -11,6 +11,7 @@ GMSIndoorDisplayDelegate {
11
11
  private var mapView: GMSMapView?
12
12
  private var initialized = false
13
13
  private var mapReady = false
14
+ private var deInitialized = false
14
15
 
15
16
  private var pendingMarkers: [(id: String, marker: GMSMarker)] = []
16
17
  private var pendingPolylines: [(id: String, polyline: GMSPolyline)] = []
@@ -28,7 +29,6 @@ GMSIndoorDisplayDelegate {
28
29
 
29
30
  private var cameraMoveReasonIsGesture: Bool = false
30
31
  private var lastSubmittedCameraPosition: GMSCameraPosition?
31
- private var lastSubmittedLocation: CLLocation?
32
32
 
33
33
  init(
34
34
  frame: CGRect = .zero,
@@ -72,8 +72,8 @@ GMSIndoorDisplayDelegate {
72
72
  mapView?.autoresizingMask = [.flexibleWidth, .flexibleHeight]
73
73
  mapView?.paddingAdjustmentBehavior = .never
74
74
  mapView.map { addSubview($0) }
75
+ applyProps()
75
76
  initLocationCallbacks()
76
- applyPending()
77
77
  onMapReady?(true)
78
78
  mapReady = true
79
79
  }
@@ -82,18 +82,7 @@ GMSIndoorDisplayDelegate {
82
82
  private func initLocationCallbacks() {
83
83
  locationHandler.onUpdate = { [weak self] loc in
84
84
  guard let self = self else { return }
85
- if self.lastSubmittedLocation?.coordinate.latitude
86
- != loc.coordinate.latitude
87
- || self.lastSubmittedLocation?.coordinate.longitude
88
- != loc.coordinate.longitude {
89
- self.onLocationUpdate?(
90
- RNLocation(
91
- loc.coordinate.toRNLatLng(),
92
- loc.course
93
- )
94
- )
95
- }
96
- self.lastSubmittedLocation = loc
85
+ self.onLocationUpdate?(loc.toRnLocation())
97
86
  }
98
87
  locationHandler.onError = { [weak self] error in
99
88
  self?.onLocationError?(error)
@@ -102,55 +91,19 @@ GMSIndoorDisplayDelegate {
102
91
  }
103
92
 
104
93
  @MainActor
105
- private func applyPending() {
106
- mapPadding.map {
107
- mapView?.padding = UIEdgeInsets(
108
- top: $0.top,
109
- left: $0.left,
110
- bottom: $0.bottom,
111
- right: $0.right
112
- )
113
- }
114
-
115
- if let v = uiSettings {
116
- v.allGesturesEnabled.map { mapView?.settings.setAllGesturesEnabled($0) }
117
- v.compassEnabled.map { mapView?.settings.compassButton = $0 }
118
- v.indoorLevelPickerEnabled.map { mapView?.settings.indoorPicker = $0 }
119
- v.mapToolbarEnabled.map { _ in /* not supported */ }
120
- v.myLocationButtonEnabled.map { mapView?.settings.myLocationButton = $0 }
121
- v.rotateEnabled.map { mapView?.settings.rotateGestures = $0 }
122
- v.scrollEnabled.map { mapView?.settings.scrollGestures = $0 }
123
- v.scrollDuringRotateOrZoomEnabled.map {
124
- mapView?.settings.allowScrollGesturesDuringRotateOrZoom = $0
125
- }
126
- v.tiltEnabled.map { mapView?.settings.tiltGestures = $0 }
127
- v.zoomControlsEnabled.map { _ in /* not supported */ }
128
- v.zoomGesturesEnabled.map { mapView?.settings.zoomGestures = $0 }
129
- }
130
-
131
- myLocationEnabled.map { mapView?.isMyLocationEnabled = $0 }
132
- buildingEnabled.map { mapView?.isBuildingsEnabled = $0 }
133
- trafficEnabled.map { mapView?.isTrafficEnabled = $0 }
134
- indoorEnabled.map {
135
- mapView?.isIndoorEnabled = $0
136
- mapView?.indoorDisplay.delegate = $0 == true ? self : nil
137
- }
138
- customMapStyle.map { mapView?.mapStyle = $0 }
139
- mapType.map { mapView?.mapType = $0 }
140
- userInterfaceStyle.map { mapView?.overrideUserInterfaceStyle = $0 }
94
+ private func applyProps() {
95
+ ({ self.uiSettings = self.uiSettings })()
96
+ ({ self.mapPadding = self.mapPadding })()
97
+ ({ self.myLocationEnabled = self.myLocationEnabled })()
98
+ ({ self.buildingEnabled = self.buildingEnabled })()
99
+ ({ self.trafficEnabled = self.trafficEnabled })()
100
+ ({ self.indoorEnabled = self.indoorEnabled })()
101
+ ({ self.customMapStyle = self.customMapStyle })()
102
+ ({ self.mapType = self.mapType })()
103
+ ({ self.userInterfaceStyle = self.userInterfaceStyle })()
104
+ ({ self.mapZoomConfig = self.mapZoomConfig })()
105
+ ({ self.locationConfig = self.locationConfig })()
141
106
 
142
- mapZoomConfig.map {
143
- mapView?.setMinZoom(
144
- Float($0.min ?? 2),
145
- maxZoom: Float($0.max ?? 21)
146
- )
147
- }
148
-
149
- locationConfig.map {
150
- locationHandler.desiredAccuracy =
151
- $0.ios?.desiredAccuracy?.toCLLocationAccuracy
152
- locationHandler.distanceFilterMeters = $0.ios?.distanceFilterMeters
153
- }
154
107
  if !pendingMarkers.isEmpty {
155
108
  pendingMarkers.forEach { addMarkerInternal(id: $0.id, marker: $0.marker) }
156
109
  pendingMarkers.removeAll()
@@ -402,7 +355,7 @@ GMSIndoorDisplayDelegate {
402
355
  ) -> NitroModules.Promise<String?> {
403
356
  let promise = Promise<String?>()
404
357
 
405
- DispatchQueue.main.async {
358
+ onMainAsync {
406
359
  guard let mapView = self.mapView else {
407
360
  promise.resolve(withResult: nil)
408
361
  return
@@ -435,7 +388,6 @@ GMSIndoorDisplayDelegate {
435
388
  return
436
389
  }
437
390
 
438
- // Rückgabe
439
391
  if resultIsFile {
440
392
  let filename =
441
393
  "map_snapshot_\(Int(Date().timeIntervalSince1970)).\(format)"
@@ -660,6 +612,8 @@ GMSIndoorDisplayDelegate {
660
612
  }
661
613
 
662
614
  func deinitInternal() {
615
+ guard !deInitialized else { return }
616
+ deInitialized = true
663
617
  onMain {
664
618
  self.locationHandler.stop()
665
619
  self.markerBuilder.cancelAllIconTasks()
@@ -703,33 +657,14 @@ GMSIndoorDisplayDelegate {
703
657
 
704
658
  func mapView(_ mapView: GMSMapView, willMove gesture: Bool) {
705
659
  onMain {
660
+ self.cameraMoveReasonIsGesture = gesture
706
661
  let visibleRegion = mapView.projection.visibleRegion()
707
662
  let bounds = GMSCoordinateBounds(region: visibleRegion)
708
663
 
709
- let center = CLLocationCoordinate2D(
710
- latitude: (bounds.northEast.latitude + bounds.southWest.latitude) / 2.0,
711
- longitude: (bounds.northEast.longitude + bounds.southWest.longitude)
712
- / 2.0
713
- )
664
+ let region = bounds.toRNRegion()
665
+ let camera = mapView.camera.toRNCamera()
714
666
 
715
- let latDelta = bounds.northEast.latitude - bounds.southWest.latitude
716
- let lngDelta = bounds.northEast.longitude - bounds.southWest.longitude
717
-
718
- let cp = mapView.camera
719
- let region = RNRegion(
720
- center: center.toRNLatLng(),
721
- latitudeDelta: latDelta,
722
- longitudeDelta: lngDelta
723
- )
724
- let cam = RNCamera(
725
- center: cp.target.toRNLatLng(),
726
- zoom: Double(cp.zoom),
727
- bearing: cp.bearing,
728
- tilt: cp.viewingAngle
729
- )
730
- self.cameraMoveReasonIsGesture = gesture
731
-
732
- self.onCameraChangeStart?(region, cam, gesture)
667
+ self.onCameraChange?(region, camera, gesture)
733
668
  }
734
669
  }
735
670
 
@@ -748,28 +683,10 @@ GMSIndoorDisplayDelegate {
748
683
  let visibleRegion = mapView.projection.visibleRegion()
749
684
  let bounds = GMSCoordinateBounds(region: visibleRegion)
750
685
 
751
- let center = CLLocationCoordinate2D(
752
- latitude: (bounds.northEast.latitude + bounds.southWest.latitude) / 2.0,
753
- longitude: (bounds.northEast.longitude + bounds.southWest.longitude)
754
- / 2.0
755
- )
756
-
757
- let latDelta = bounds.northEast.latitude - bounds.southWest.latitude
758
- let lngDelta = bounds.northEast.longitude - bounds.southWest.longitude
686
+ let region = bounds.toRNRegion()
687
+ let camera = mapView.camera.toRNCamera()
759
688
 
760
- let cp = mapView.camera
761
- let region = RNRegion(
762
- center: center.toRNLatLng(),
763
- latitudeDelta: latDelta,
764
- longitudeDelta: lngDelta
765
- )
766
- let cam = RNCamera(
767
- center: cp.target.toRNLatLng(),
768
- zoom: Double(cp.zoom),
769
- bearing: cp.bearing,
770
- tilt: cp.viewingAngle
771
- )
772
- self.onCameraChange?(region, cam, self.cameraMoveReasonIsGesture)
689
+ self.onCameraChange?(region, camera, self.cameraMoveReasonIsGesture)
773
690
  }
774
691
  }
775
692
 
@@ -778,28 +695,10 @@ GMSIndoorDisplayDelegate {
778
695
  let visibleRegion = mapView.projection.visibleRegion()
779
696
  let bounds = GMSCoordinateBounds(region: visibleRegion)
780
697
 
781
- let center = CLLocationCoordinate2D(
782
- latitude: (bounds.northEast.latitude + bounds.southWest.latitude) / 2.0,
783
- longitude: (bounds.northEast.longitude + bounds.southWest.longitude)
784
- / 2.0
785
- )
786
-
787
- let latDelta = bounds.northEast.latitude - bounds.southWest.latitude
788
- let lngDelta = bounds.northEast.longitude - bounds.southWest.longitude
698
+ let region = bounds.toRNRegion()
699
+ let camera = mapView.camera.toRNCamera()
789
700
 
790
- let cp = mapView.camera
791
- let region = RNRegion(
792
- center: center.toRNLatLng(),
793
- latitudeDelta: latDelta,
794
- longitudeDelta: lngDelta
795
- )
796
- let cam = RNCamera(
797
- center: cp.target.toRNLatLng(),
798
- zoom: Double(cp.zoom),
799
- bearing: cp.bearing,
800
- tilt: cp.viewingAngle
801
- )
802
- self.onCameraChangeComplete?(region, cam, self.cameraMoveReasonIsGesture)
701
+ self.onCameraChange?(region, camera, self.cameraMoveReasonIsGesture)
803
702
  }
804
703
  }
805
704
 
@@ -893,12 +792,3 @@ GMSIndoorDisplayDelegate {
893
792
  }
894
793
  }
895
794
  }
896
-
897
- @inline(__always)
898
- func onMain(_ block: @escaping () -> Void) {
899
- if Thread.isMainThread {
900
- block()
901
- } else {
902
- DispatchQueue.main.async { block() }
903
- }
904
- }
@@ -34,7 +34,7 @@ final class LocationHandler: NSObject, CLLocationManagerDelegate {
34
34
  }
35
35
 
36
36
  func showLocationDialog() {
37
- DispatchQueue.main.async {
37
+ onMainAsync { [weak self] in
38
38
  guard let vc = Self.topMostViewController() else { return }
39
39
  let title =
40
40
  Bundle.main.object(forInfoDictionaryKey: "LocationNotAvailableTitle")
@@ -61,7 +61,7 @@ final class LocationHandler: NSObject, CLLocationManagerDelegate {
61
61
  title: openLocationSettingsButton ?? "Open settings",
62
62
  style: .default
63
63
  ) { _ in
64
- self.openLocationSettings()
64
+ self?.openLocationSettings()
65
65
  }
66
66
  )
67
67
  vc.present(alert, animated: true, completion: nil)
@@ -78,7 +78,7 @@ final class LocationHandler: NSObject, CLLocationManagerDelegate {
78
78
  }
79
79
 
80
80
  func openLocationSettings() {
81
- DispatchQueue.main.async {
81
+ onMainAsync {
82
82
  let openSettings = {
83
83
  if #available(iOS 18.3, *) {
84
84
  guard
@@ -114,18 +114,10 @@ final class LocationHandler: NSObject, CLLocationManagerDelegate {
114
114
  didFailWithError error: Error
115
115
  ) {
116
116
  let code: RNLocationErrorCode
117
-
118
117
  if let clError = error as? CLError {
119
- switch clError.code {
120
- case .denied:
121
- code = RNLocationErrorCode.permissionDenied
122
- case .locationUnknown, .network:
123
- code = RNLocationErrorCode.positionUnavailable
124
- default:
125
- code = RNLocationErrorCode.internalError
126
- }
118
+ code = clError.code.toRNLocationErrorCode
127
119
  } else {
128
- code = RNLocationErrorCode.internalError
120
+ code = .internalError
129
121
  }
130
122
  onError?(code)
131
123
  }
@@ -14,14 +14,34 @@ final class MapCircleBuilder {
14
14
  return circle
15
15
  }
16
16
 
17
- func update(_ next: RNCircle, _ c: GMSCircle) {
18
- c.position = next.center.toCLLocationCoordinate2D()
19
- c.radius = next.radius
20
- c.fillColor = next.fillColor?.toUIColor() ?? nil
21
- c.strokeColor = next.strokeColor?.toUIColor() ?? .black
22
- c.strokeWidth = CGFloat(next.strokeWidth ?? 1.0)
23
- c.isTappable = next.pressable ?? false
24
- c.zIndex = Int32(next.zIndex ?? 0)
25
- }
17
+ func update(_ prev: RNCircle, _ next: RNCircle, _ c: GMSCircle) {
18
+ if prev.center.latitude != next.center.latitude
19
+ || prev.center.longitude != next.center.longitude {
20
+ c.position = next.center.toCLLocationCoordinate2D()
21
+ }
22
+
23
+ if prev.radius != next.radius {
24
+ c.radius = next.radius ?? 0
25
+ }
26
+
27
+ if prev.fillColor != next.fillColor {
28
+ c.fillColor = next.fillColor?.toUIColor() ?? .clear
29
+ }
30
+
31
+ if prev.strokeColor != next.strokeColor {
32
+ c.strokeColor = next.strokeColor?.toUIColor() ?? .black
33
+ }
26
34
 
35
+ if prev.strokeWidth != next.strokeWidth {
36
+ c.strokeWidth = CGFloat(next.strokeWidth ?? 1.0)
37
+ }
38
+
39
+ if prev.pressable != next.pressable {
40
+ c.isTappable = next.pressable ?? false
41
+ }
42
+
43
+ if prev.zIndex != next.zIndex {
44
+ c.zIndex = Int32(next.zIndex ?? 0)
45
+ }
46
+ }
27
47
  }
@@ -18,3 +18,23 @@ func withCATransaction(
18
18
  body()
19
19
  CATransaction.commit()
20
20
  }
21
+
22
+ @MainActor @inline(__always)
23
+ func onMain(_ block: @escaping @MainActor () -> Void) {
24
+ if Thread.isMainThread {
25
+ block()
26
+ } else {
27
+ Task { @MainActor in block() }
28
+ }
29
+ }
30
+
31
+ @inline(__always)
32
+ func onMainAsync(
33
+ _ block: @MainActor @escaping () async -> Void
34
+ ) {
35
+ if Thread.isMainThread {
36
+ Task { @MainActor in await block() }
37
+ } else {
38
+ Task { @MainActor in await block() }
39
+ }
40
+ }