react-native-google-maps-plus 1.7.0 → 1.8.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 (72) hide show
  1. package/android/build.gradle +1 -1
  2. package/android/gradle.properties +2 -1
  3. package/android/src/main/java/com/rngooglemapsplus/GoogleMapsViewImpl.kt +4 -4
  4. package/android/src/main/java/com/rngooglemapsplus/MapCircleBuilder.kt +2 -3
  5. package/android/src/main/java/com/rngooglemapsplus/MapMarkerBuilder.kt +51 -54
  6. package/android/src/main/java/com/rngooglemapsplus/MapPolygonBuilder.kt +6 -23
  7. package/android/src/main/java/com/rngooglemapsplus/MapPolylineBuilder.kt.kt +12 -39
  8. package/android/src/main/java/com/rngooglemapsplus/RNGoogleMapsPlusView.kt +7 -5
  9. package/android/src/main/java/com/rngooglemapsplus/extensions/CameraPositionExtension.kt +3 -2
  10. package/android/src/main/java/com/rngooglemapsplus/extensions/RNLineCapTypeExtension.kt +14 -0
  11. package/android/src/main/java/com/rngooglemapsplus/extensions/RNLineJoinTypeExtension.kt +12 -0
  12. package/android/src/main/java/com/rngooglemapsplus/extensions/RNMapCircleExtension.kt +7 -1
  13. package/android/src/main/java/com/rngooglemapsplus/extensions/RNMarkerExtension.kt +54 -17
  14. package/android/src/main/java/com/rngooglemapsplus/extensions/RNPolygonExtension.kt +31 -1
  15. package/android/src/main/java/com/rngooglemapsplus/extensions/RNPolylineExtension.kt +6 -1
  16. package/ios/GoogleMapViewImpl.swift +8 -5
  17. package/ios/LocationHandler.swift +3 -1
  18. package/ios/MapCircleBuilder.swift +2 -3
  19. package/ios/MapHelper.swift +3 -5
  20. package/ios/MapMarkerBuilder.swift +108 -105
  21. package/ios/MapPolygonBuilder.swift +6 -41
  22. package/ios/MapPolylineBuilder.swift +2 -10
  23. package/ios/RNGoogleMapsPlusView.swift +31 -25
  24. package/ios/extensions/GMSCameraPosition+Extension.swift +2 -2
  25. package/ios/extensions/RNCircle+Extension.swift +14 -5
  26. package/ios/extensions/RNLatLng+Extension.swift +11 -0
  27. package/ios/extensions/RNLineCapType+Extension.swift +10 -0
  28. package/ios/extensions/RNLineJoinType+Extension.swift +11 -0
  29. package/ios/extensions/RNMarker+Extension.swift +43 -12
  30. package/ios/extensions/RNPolygon+Extension.swift.swift +50 -21
  31. package/ios/extensions/RNPolyline+Extension.swift.swift +15 -26
  32. package/ios/extensions/SVGKImage+Extension.swift +22 -0
  33. package/lib/module/types.js.map +1 -1
  34. package/lib/typescript/src/RNGoogleMapsPlusView.nitro.d.ts +5 -5
  35. package/lib/typescript/src/RNGoogleMapsPlusView.nitro.d.ts.map +1 -1
  36. package/lib/typescript/src/types.d.ts +7 -1
  37. package/lib/typescript/src/types.d.ts.map +1 -1
  38. package/nitrogen/generated/android/RNGoogleMapsPlusOnLoad.cpp +4 -4
  39. package/nitrogen/generated/android/c++/{JFunc_void_RNRegion_RNCamera.hpp → JFunc_void_RNRegion_RNCameraChange.hpp} +21 -22
  40. package/nitrogen/generated/android/c++/JFunc_void_RNRegion_RNCameraChange_bool.hpp +82 -0
  41. package/nitrogen/generated/android/c++/JHybridRNGoogleMapsPlusViewSpec.cpp +42 -38
  42. package/nitrogen/generated/android/c++/JHybridRNGoogleMapsPlusViewSpec.hpp +8 -8
  43. package/nitrogen/generated/android/c++/JRNCameraChange.hpp +70 -0
  44. package/nitrogen/generated/android/c++/JRNInitialProps.hpp +7 -3
  45. package/nitrogen/generated/android/c++/JRNMarker.hpp +1 -5
  46. package/nitrogen/generated/android/kotlin/com/margelo/nitro/rngooglemapsplus/{Func_void_RNRegion_RNCamera.kt → Func_void_RNRegion_RNCameraChange.kt} +9 -9
  47. package/nitrogen/generated/android/kotlin/com/margelo/nitro/rngooglemapsplus/{Func_void_RNRegion_RNCamera_bool.kt → Func_void_RNRegion_RNCameraChange_bool.kt} +9 -9
  48. package/nitrogen/generated/android/kotlin/com/margelo/nitro/rngooglemapsplus/HybridRNGoogleMapsPlusViewSpec.kt +12 -12
  49. package/nitrogen/generated/android/kotlin/com/margelo/nitro/rngooglemapsplus/RNCameraChange.kt +46 -0
  50. package/nitrogen/generated/android/kotlin/com/margelo/nitro/rngooglemapsplus/RNInitialProps.kt +6 -3
  51. package/nitrogen/generated/android/kotlin/com/margelo/nitro/rngooglemapsplus/RNMarker.kt +2 -5
  52. package/nitrogen/generated/ios/RNGoogleMapsPlus-Swift-Cxx-Bridge.cpp +8 -8
  53. package/nitrogen/generated/ios/RNGoogleMapsPlus-Swift-Cxx-Bridge.hpp +39 -36
  54. package/nitrogen/generated/ios/RNGoogleMapsPlus-Swift-Cxx-Umbrella.hpp +3 -0
  55. package/nitrogen/generated/ios/c++/HybridRNGoogleMapsPlusViewSpecSwift.hpp +11 -8
  56. package/nitrogen/generated/ios/swift/{Func_void_RNRegion_RNCamera.swift → Func_void_RNRegion_RNCameraChange.swift} +10 -10
  57. package/nitrogen/generated/ios/swift/{Func_void_RNRegion_RNCamera_bool.swift → Func_void_RNRegion_RNCameraChange_bool.swift} +10 -10
  58. package/nitrogen/generated/ios/swift/HybridRNGoogleMapsPlusViewSpec.swift +4 -4
  59. package/nitrogen/generated/ios/swift/HybridRNGoogleMapsPlusViewSpec_cxx.swift +44 -44
  60. package/nitrogen/generated/ios/swift/RNCameraChange.swift +68 -0
  61. package/nitrogen/generated/ios/swift/RNInitialProps.swift +31 -1
  62. package/nitrogen/generated/ios/swift/RNMarker.swift +1 -31
  63. package/nitrogen/generated/shared/c++/HybridRNGoogleMapsPlusViewSpec.hpp +14 -11
  64. package/nitrogen/generated/shared/c++/RNCameraChange.hpp +88 -0
  65. package/nitrogen/generated/shared/c++/RNInitialProps.hpp +6 -2
  66. package/nitrogen/generated/shared/c++/RNMarker.hpp +1 -5
  67. package/nitrogen/generated/shared/c++/views/HybridRNGoogleMapsPlusViewComponent.cpp +8 -8
  68. package/nitrogen/generated/shared/c++/views/HybridRNGoogleMapsPlusViewComponent.hpp +5 -5
  69. package/package.json +1 -1
  70. package/src/RNGoogleMapsPlusView.nitro.ts +5 -4
  71. package/src/types.ts +8 -1
  72. package/nitrogen/generated/android/c++/JFunc_void_RNRegion_RNCamera_bool.hpp +0 -83
@@ -261,7 +261,7 @@ GMSIndoorDisplayDelegate {
261
261
 
262
262
  var onMapError: ((RNMapErrorCode) -> Void)?
263
263
  var onMapReady: ((Bool) -> Void)?
264
- var onMapLoaded: ((RNRegion, RNCamera) -> Void)?
264
+ var onMapLoaded: ((RNRegion, RNCameraChange) -> Void)?
265
265
  var onLocationUpdate: ((RNLocation) -> Void)?
266
266
  var onLocationError: ((_ error: RNLocationErrorCode) -> Void)?
267
267
  var onMapPress: ((RNLatLng) -> Void)?
@@ -281,9 +281,9 @@ GMSIndoorDisplayDelegate {
281
281
  var onInfoWindowLongPress: ((String) -> Void)?
282
282
  var onMyLocationPress: ((RNLocation) -> Void)?
283
283
  var onMyLocationButtonPress: ((Bool) -> Void)?
284
- var onCameraChangeStart: ((RNRegion, RNCamera, Bool) -> Void)?
285
- var onCameraChange: ((RNRegion, RNCamera, Bool) -> Void)?
286
- var onCameraChangeComplete: ((RNRegion, RNCamera, Bool) -> Void)?
284
+ var onCameraChangeStart: ((RNRegion, RNCameraChange, Bool) -> Void)?
285
+ var onCameraChange: ((RNRegion, RNCameraChange, Bool) -> Void)?
286
+ var onCameraChangeComplete: ((RNRegion, RNCameraChange, Bool) -> Void)?
287
287
 
288
288
  @MainActor
289
289
  func showMarkerInfoWindow(id: String) {
@@ -444,7 +444,10 @@ GMSIndoorDisplayDelegate {
444
444
 
445
445
  @MainActor
446
446
  func removeMarker(id: String) {
447
- markersById.removeValue(forKey: id).map { $0.map = nil }
447
+ markersById.removeValue(forKey: id).map {
448
+ $0.icon = nil
449
+ $0.map = nil
450
+ }
448
451
  }
449
452
 
450
453
  @MainActor
@@ -35,6 +35,8 @@ final class LocationHandler: NSObject, CLLocationManagerDelegate {
35
35
 
36
36
  func showLocationDialog() {
37
37
  onMainAsync { [weak self] in
38
+ guard let self = self else { return }
39
+
38
40
  guard let vc = Self.topMostViewController() else { return }
39
41
  let title =
40
42
  Bundle.main.object(forInfoDictionaryKey: "LocationNotAvailableTitle")
@@ -61,7 +63,7 @@ final class LocationHandler: NSObject, CLLocationManagerDelegate {
61
63
  title: openLocationSettingsButton ?? "Open settings",
62
64
  style: .default
63
65
  ) { _ in
64
- self?.openLocationSettings()
66
+ self.openLocationSettings()
65
67
  }
66
68
  )
67
69
  vc.present(alert, animated: true, completion: nil)
@@ -17,13 +17,12 @@ final class MapCircleBuilder {
17
17
 
18
18
  @MainActor
19
19
  func update(_ prev: RNCircle, _ next: RNCircle, _ c: GMSCircle) {
20
- if prev.center.latitude != next.center.latitude
21
- || prev.center.longitude != next.center.longitude {
20
+ if !prev.centerEquals(next) {
22
21
  c.position = next.center.toCLLocationCoordinate2D()
23
22
  }
24
23
 
25
24
  if prev.radius != next.radius {
26
- c.radius = next.radius ?? 0
25
+ c.radius = next.radius
27
26
  }
28
27
 
29
28
  if prev.fillColor != next.fillColor {
@@ -32,11 +32,9 @@ func onMain(_ block: @escaping @MainActor () -> Void) {
32
32
 
33
33
  @inline(__always)
34
34
  func onMainAsync(
35
- _ block: @MainActor @escaping () async -> Void
35
+ _ block: @escaping @MainActor () async -> Void
36
36
  ) {
37
- if Thread.isMainThread {
38
- Task { @MainActor in await block() }
39
- } else {
40
- Task { @MainActor in await block() }
37
+ Task { @MainActor in
38
+ await block()
41
39
  }
42
40
  }
@@ -15,7 +15,6 @@ final class MapMarkerBuilder {
15
15
  let marker = GMSMarker(
16
16
  position: m.coordinate.toCLLocationCoordinate2D()
17
17
  )
18
- marker.tracksViewChanges = true
19
18
  marker.icon = icon
20
19
  m.title.map { marker.title = $0 }
21
20
  m.snippet.map { marker.snippet = $0 }
@@ -42,107 +41,122 @@ final class MapMarkerBuilder {
42
41
  iconSvg: m.infoWindowIconSvg
43
42
  )
44
43
 
45
- onMainAsync { [weak marker] in
46
- try? await Task.sleep(nanoseconds: 250_000_000)
47
- marker?.tracksViewChanges = false
48
- }
49
-
50
44
  return marker
51
45
  }
52
46
 
53
47
  @MainActor
54
48
  func update(_ prev: RNMarker, _ next: RNMarker, _ m: GMSMarker) {
55
- if prev.coordinate.latitude != next.coordinate.latitude
56
- || prev.coordinate.longitude != next.coordinate.longitude {
57
- m.position = next.coordinate.toCLLocationCoordinate2D()
58
- }
59
-
60
- if prev.title != next.title {
61
- m.title = next.title
62
- }
63
-
64
- if prev.snippet != next.snippet {
65
- m.snippet = next.snippet
66
- }
67
-
68
- if prev.opacity != next.opacity {
69
- let opacity = Float(next.opacity ?? 1)
70
- m.opacity = opacity
71
- m.iconView?.alpha = CGFloat(opacity)
72
- }
73
-
74
- if prev.flat != next.flat {
75
- m.isFlat = next.flat ?? false
76
- }
77
-
78
- if prev.draggable != next.draggable {
79
- m.isDraggable = next.draggable ?? false
80
- }
49
+ withCATransaction(disableActions: true) {
81
50
 
82
- if prev.rotation != next.rotation {
83
- m.rotation = next.rotation ?? 0
84
- }
85
-
86
- if prev.zIndex != next.zIndex {
87
- m.zIndex = Int32(next.zIndex ?? 0)
88
- }
51
+ var tracksViewChanges = false
52
+ var tracksInfoWindowChanges = false
89
53
 
90
- if !prev.markerStyleEquals(next) {
91
- buildIconAsync(next.id, next) { img in
92
- m.tracksViewChanges = true
93
- m.icon = img
54
+ if !prev.coordinateEquals(next) {
55
+ m.position = next.coordinate.toCLLocationCoordinate2D()
56
+ }
94
57
 
95
- if prev.anchor?.x != next.anchor?.x || prev.anchor?.y != next.anchor?.y {
58
+ if !prev.markerStyleEquals(next) {
59
+ self.buildIconAsync(next) { img in
60
+ tracksViewChanges = true
61
+ m.icon = img
62
+
63
+ if !prev.anchorEquals(next) {
64
+ m.groundAnchor = CGPoint(
65
+ x: next.anchor?.x ?? 0.5,
66
+ y: next.anchor?.y ?? 1
67
+ )
68
+ }
69
+
70
+ if !prev.infoWindowAnchorEquals(next) {
71
+ m.infoWindowAnchor = CGPoint(
72
+ x: next.infoWindowAnchor?.x ?? 0.5,
73
+ y: next.infoWindowAnchor?.y ?? 0
74
+ )
75
+ }
76
+ }
77
+ } else {
78
+ if !prev.anchorEquals(next) {
96
79
  m.groundAnchor = CGPoint(
97
80
  x: next.anchor?.x ?? 0.5,
98
81
  y: next.anchor?.y ?? 1
99
82
  )
100
83
  }
101
84
 
102
- if prev.infoWindowAnchor?.x != next.infoWindowAnchor?.x
103
- || prev.infoWindowAnchor?.y != next.infoWindowAnchor?.y {
85
+ if !prev.infoWindowAnchorEquals(next) {
104
86
  m.infoWindowAnchor = CGPoint(
105
87
  x: next.infoWindowAnchor?.x ?? 0.5,
106
88
  y: next.infoWindowAnchor?.y ?? 0
107
89
  )
108
90
  }
91
+ }
109
92
 
110
- onMainAsync { [weak m] in
111
- try? await Task.sleep(nanoseconds: 250_000_000)
112
- m?.tracksViewChanges = false
113
- }
93
+ if prev.title != next.title {
94
+ tracksInfoWindowChanges = true
95
+ m.title = next.title
114
96
  }
115
- } else {
116
- if prev.anchor?.x != next.anchor?.x || prev.anchor?.y != next.anchor?.y {
117
- m.groundAnchor = CGPoint(
118
- x: next.anchor?.x ?? 0.5,
119
- y: next.anchor?.y ?? 1
120
- )
97
+
98
+ if prev.snippet != next.snippet {
99
+ tracksInfoWindowChanges = true
100
+ m.snippet = next.snippet
101
+ }
102
+
103
+ if prev.opacity != next.opacity {
104
+ let opacity = Float(next.opacity ?? 1)
105
+ m.opacity = opacity
106
+ m.iconView?.alpha = CGFloat(opacity)
107
+ }
108
+
109
+ if prev.flat != next.flat {
110
+ m.isFlat = next.flat ?? false
121
111
  }
122
112
 
123
- if prev.infoWindowAnchor?.x != next.infoWindowAnchor?.x
124
- || prev.infoWindowAnchor?.y != next.infoWindowAnchor?.y {
125
- m.infoWindowAnchor = CGPoint(
126
- x: next.infoWindowAnchor?.x ?? 0.5,
127
- y: next.infoWindowAnchor?.y ?? 0
113
+ if prev.draggable != next.draggable {
114
+ m.isDraggable = next.draggable ?? false
115
+ }
116
+
117
+ if prev.rotation != next.rotation {
118
+ m.rotation = next.rotation ?? 0
119
+ }
120
+
121
+ if prev.zIndex != next.zIndex {
122
+ m.zIndex = Int32(next.zIndex ?? 0)
123
+ }
124
+
125
+ if !prev.markerInfoWindowStyleEquals(next) {
126
+ m.tagData = MarkerTag(
127
+ id: next.id,
128
+ iconSvg: next.infoWindowIconSvg
128
129
  )
129
130
  }
130
131
 
131
- m.tagData = MarkerTag(
132
- id: next.id,
133
- iconSvg: next.infoWindowIconSvg
134
- )
132
+ if tracksViewChanges {
133
+ m.tracksViewChanges = tracksViewChanges
134
+ }
135
+ if tracksInfoWindowChanges {
136
+ m.tracksInfoWindowChanges = tracksInfoWindowChanges
137
+ }
138
+
139
+ if tracksViewChanges || tracksInfoWindowChanges {
140
+ onMain { [weak m] in
141
+ guard let m = m else { return }
135
142
 
143
+ if tracksViewChanges {
144
+ m.tracksViewChanges = false
145
+ }
146
+
147
+ if tracksInfoWindowChanges {
148
+ m.tracksInfoWindowChanges = false
149
+ }
150
+ }
151
+ }
136
152
  }
137
153
  }
138
154
 
139
- @MainActor
140
155
  func buildIconAsync(
141
- _ id: String,
142
156
  _ m: RNMarker,
143
157
  onReady: @escaping (UIImage?) -> Void
144
158
  ) {
145
- tasks[id]?.cancel()
159
+ tasks[m.id]?.cancel()
146
160
 
147
161
  if m.iconSvg == nil {
148
162
  onReady(nil)
@@ -155,12 +169,15 @@ final class MapMarkerBuilder {
155
169
  return
156
170
  }
157
171
 
172
+ let scale = UIScreen.main.scale
173
+
158
174
  let task = Task(priority: .userInitiated) { [weak self] in
159
175
  guard let self else { return }
160
- defer { self.tasks.removeValue(forKey: id) }
176
+ defer {
177
+ Task { @MainActor in self.tasks.removeValue(forKey: m.id) }
178
+ }
161
179
 
162
- let scale = UIScreen.main.scale
163
- let img = await self.renderUIImage(m, scale)
180
+ let img = self.renderUIImage(m, scale)
164
181
  guard let img, !Task.isCancelled else { return }
165
182
 
166
183
  self.iconCache.setObject(img, forKey: key)
@@ -171,7 +188,7 @@ final class MapMarkerBuilder {
171
188
  }
172
189
  }
173
190
 
174
- tasks[id] = task
191
+ tasks[m.id] = task
175
192
  }
176
193
 
177
194
  @MainActor
@@ -209,18 +226,11 @@ final class MapMarkerBuilder {
209
226
 
210
227
  svgImg.size = size
211
228
 
212
- guard let base = svgImg.uiImage else {
229
+ guard let finalImage = SVGKExporterUIImage.export(asUIImage: svgImg) else {
230
+ svgImg.clear()
213
231
  return nil
214
232
  }
215
-
216
- let fmt = UIGraphicsImageRendererFormat.default()
217
- fmt.opaque = false
218
- fmt.scale = UIScreen.main.scale
219
- let renderer = UIGraphicsImageRenderer(size: size, format: fmt)
220
-
221
- let finalImage = renderer.image { _ in
222
- base.draw(in: CGRect(origin: .zero, size: size))
223
- }
233
+ svgImg.clear()
224
234
 
225
235
  let imageView = UIImageView(image: finalImage)
226
236
  imageView.frame = CGRect(origin: .zero, size: size)
@@ -230,10 +240,10 @@ final class MapMarkerBuilder {
230
240
  return imageView
231
241
  }
232
242
 
233
- @MainActor
234
- private func renderUIImage(_ m: RNMarker, _ scale: CGFloat) async -> UIImage? {
235
- guard let iconSvg = m.iconSvg,
236
- let data = iconSvg.svgString.data(using: .utf8)
243
+ private func renderUIImage(_ m: RNMarker, _ scale: CGFloat) -> UIImage? {
244
+ guard
245
+ let iconSvg = m.iconSvg,
246
+ let data = iconSvg.svgString.data(using: .utf8)
237
247
  else { return nil }
238
248
 
239
249
  let size = CGSize(
@@ -241,28 +251,21 @@ final class MapMarkerBuilder {
241
251
  height: max(1, CGFloat(iconSvg.height))
242
252
  )
243
253
 
244
- return await Task.detached(priority: .userInitiated) {
245
- autoreleasepool {
246
- guard let svgImg = SVGKImage(data: data) else { return nil }
247
- svgImg.size = size
254
+ return autoreleasepool { () -> UIImage? in
255
+ guard !Task.isCancelled else { return nil }
256
+ guard let svgImg = SVGKImage(data: data) else { return nil }
248
257
 
249
- guard !Task.isCancelled else { return nil }
250
- guard let base = svgImg.uiImage else { return nil }
258
+ svgImg.size = size
251
259
 
252
- if let cg = base.cgImage {
253
- return UIImage(cgImage: cg, scale: scale, orientation: .up)
254
- }
255
- guard !Task.isCancelled else { return nil }
256
- let fmt = UIGraphicsImageRendererFormat.default()
257
- fmt.opaque = false
258
- fmt.scale = scale
259
- guard !Task.isCancelled else { return nil }
260
- let renderer = UIGraphicsImageRenderer(size: size, format: fmt)
261
- return renderer.image { _ in
262
- base.draw(in: CGRect(origin: .zero, size: size))
263
- }
260
+ guard !Task.isCancelled else {
261
+ svgImg.clear()
262
+ return nil
264
263
  }
265
- }.value
264
+
265
+ let uiImage = SVGKExporterUIImage.export(asUIImage: svgImg)
266
+ svgImg.clear()
267
+ return uiImage
268
+ }
266
269
  }
267
270
 
268
271
  }
@@ -3,13 +3,7 @@ import GoogleMaps
3
3
  final class MapPolygonBuilder {
4
4
  @MainActor
5
5
  func build(_ p: RNPolygon) -> GMSPolygon {
6
- let path = GMSMutablePath()
7
- p.coordinates.forEach {
8
- path.add(
9
- $0.toCLLocationCoordinate2D()
10
- )
11
- }
12
-
6
+ let path = p.coordinates.toGMSPath()
13
7
  let pg = GMSPolygon(path: path)
14
8
 
15
9
  p.fillColor.map { pg.fillColor = $0.toUIColor() }
@@ -17,13 +11,7 @@ final class MapPolygonBuilder {
17
11
  p.strokeWidth.map { pg.strokeWidth = CGFloat($0) }
18
12
  p.pressable.map { pg.isTappable = $0 }
19
13
  p.geodesic.map { pg.geodesic = $0 }
20
- p.holes.map {
21
- pg.holes = $0.map { hole in
22
- let path = GMSMutablePath()
23
- hole.coordinates.forEach { path.add($0.toCLLocationCoordinate2D()) }
24
- return path
25
- }
26
- }
14
+ pg.holes = p.holes.toMapPolygonHoles()
27
15
  p.zIndex.map { pg.zIndex = Int32($0) }
28
16
 
29
17
  return pg
@@ -31,35 +19,12 @@ final class MapPolygonBuilder {
31
19
 
32
20
  @MainActor
33
21
  func update(_ prev: RNPolygon, _ next: RNPolygon, _ pg: GMSPolygon) {
34
- let coordsChanged =
35
- prev.coordinates.count != next.coordinates.count
36
- || !zip(prev.coordinates, next.coordinates).allSatisfy {
37
- $0.latitude == $1.latitude && $0.longitude == $1.longitude
38
- }
39
-
40
- if coordsChanged {
41
- let path = GMSMutablePath()
42
- next.coordinates.forEach { path.add($0.toCLLocationCoordinate2D()) }
43
- pg.path = path
22
+ if !prev.coordinatesEquals(next) {
23
+ pg.path = next.coordinates.toGMSPath()
44
24
  }
45
25
 
46
- let prevHoles = prev.holes ?? []
47
- let nextHoles = next.holes ?? []
48
- let holesChanged =
49
- prevHoles.count != nextHoles.count
50
- || !zip(prevHoles, nextHoles).allSatisfy { a, b in
51
- a.coordinates.count == b.coordinates.count
52
- && zip(a.coordinates, b.coordinates).allSatisfy {
53
- $0.latitude == $1.latitude && $0.longitude == $1.longitude
54
- }
55
- }
56
-
57
- if holesChanged {
58
- pg.holes = nextHoles.map { hole in
59
- let path = GMSMutablePath()
60
- hole.coordinates.forEach { path.add($0.toCLLocationCoordinate2D()) }
61
- return path
62
- }
26
+ if !prev.holesEquals(next) {
27
+ pg.holes = next.holes.toMapPolygonHoles()
63
28
  }
64
29
 
65
30
  if prev.fillColor != next.fillColor {
@@ -25,16 +25,8 @@ final class MapPolylineBuilder {
25
25
 
26
26
  @MainActor
27
27
  func update(_ prev: RNPolyline, _ next: RNPolyline, _ pl: GMSPolyline) {
28
- let coordsChanged =
29
- prev.coordinates.count != next.coordinates.count
30
- || !zip(prev.coordinates, next.coordinates).allSatisfy {
31
- $0.latitude == $1.latitude && $0.longitude == $1.longitude
32
- }
33
-
34
- if coordsChanged {
35
- let path = GMSMutablePath()
36
- next.coordinates.forEach { path.add($0.toCLLocationCoordinate2D()) }
37
- pl.path = path
28
+ if !prev.coordinatesEquals(next) {
29
+ pl.path = next.coordinates.toGMSPath()
38
30
  }
39
31
 
40
32
  if prev.width != next.width {
@@ -41,6 +41,9 @@ final class RNGoogleMapsPlusView: HybridRNGoogleMapsPlusViewSpec {
41
41
  initialProps?.camera.map {
42
42
  options.camera = $0.toGMSCameraPosition(current: nil)
43
43
  }
44
+ initialProps?.backgroundColor.map {
45
+ options.backgroundColor = $0.toUIColor()
46
+ }
44
47
  impl.initMapView(googleMapOptions: options)
45
48
  }
46
49
  }
@@ -128,26 +131,26 @@ final class RNGoogleMapsPlusView: HybridRNGoogleMapsPlusViewSpec {
128
131
  )
129
132
 
130
133
  let removed = Set(prevById.keys).subtracting(nextById.keys)
131
- withCATransaction(disableActions: true) {
132
134
 
133
- removed.forEach {
134
- self.impl.removeMarker(id: $0)
135
- self.markerBuilder.cancelIconTask($0)
136
- }
135
+ removed.forEach {
136
+ self.impl.removeMarker(id: $0)
137
+ self.markerBuilder.cancelIconTask($0)
138
+ }
137
139
 
138
- for (id, next) in nextById {
139
- if let prev = prevById[id] {
140
- if !prev.markerEquals(next) {
141
- self.impl.updateMarker(id: id) { m in
142
- self.markerBuilder.update(prev, next, m)
143
- }
144
- }
145
- } else {
146
- self.markerBuilder.buildIconAsync(next.id, next) { icon in
147
- let marker = self.markerBuilder.build(next, icon: icon)
148
- self.impl.addMarker(id: id, marker: marker)
140
+ for (id, next) in nextById {
141
+ if let prev = prevById[id] {
142
+ if !prev.markerEquals(next) {
143
+ self.impl.updateMarker(id: id) { [weak self] m in
144
+ guard let self else { return }
145
+ self.markerBuilder.update(prev, next, m)
149
146
  }
150
147
  }
148
+ } else {
149
+ self.markerBuilder.buildIconAsync(next) { [weak self] icon in
150
+ guard let self else { return }
151
+ let marker = self.markerBuilder.build(next, icon: icon)
152
+ self.impl.addMarker(id: id, marker: marker)
153
+ }
151
154
  }
152
155
  }
153
156
  }
@@ -171,7 +174,8 @@ final class RNGoogleMapsPlusView: HybridRNGoogleMapsPlusViewSpec {
171
174
  for (id, next) in nextById {
172
175
  if let prev = prevById[id] {
173
176
  if !prev.polylineEquals(next) {
174
- impl.updatePolyline(id: id) { pl in
177
+ impl.updatePolyline(id: id) { [weak self] pl in
178
+ guard let self else { return }
175
179
  self.polylineBuilder.update(prev, next, pl)
176
180
  }
177
181
  }
@@ -203,7 +207,8 @@ final class RNGoogleMapsPlusView: HybridRNGoogleMapsPlusViewSpec {
203
207
  for (id, next) in nextById {
204
208
  if let prev = prevById[id] {
205
209
  if !prev.polygonEquals(next) {
206
- impl.updatePolygon(id: id) { pg in
210
+ impl.updatePolygon(id: id) { [weak self] pg in
211
+ guard let self else { return }
207
212
  self.polygonBuilder.update(prev, next, pg)
208
213
  }
209
214
  }
@@ -232,7 +237,8 @@ final class RNGoogleMapsPlusView: HybridRNGoogleMapsPlusViewSpec {
232
237
  for (id, next) in nextById {
233
238
  if let prev = prevById[id] {
234
239
  if !prev.circleEquals(next) {
235
- impl.updateCircle(id: id) { circle in
240
+ impl.updateCircle(id: id) { [weak self] circle in
241
+ guard let self else { return }
236
242
  self.circleBuilder.update(prev, next, circle)
237
243
  }
238
244
  }
@@ -325,7 +331,7 @@ final class RNGoogleMapsPlusView: HybridRNGoogleMapsPlusViewSpec {
325
331
  didSet { impl.onMapReady = onMapReady }
326
332
  }
327
333
  @MainActor
328
- var onMapLoaded: ((RNRegion, RNCamera) -> Void)? {
334
+ var onMapLoaded: ((RNRegion, RNCameraChange) -> Void)? {
329
335
  didSet { impl.onMapLoaded = onMapLoaded }
330
336
  }
331
337
  @MainActor
@@ -405,26 +411,26 @@ final class RNGoogleMapsPlusView: HybridRNGoogleMapsPlusViewSpec {
405
411
  didSet { impl.onMyLocationButtonPress = onMyLocationButtonPress }
406
412
  }
407
413
  @MainActor
408
- var onCameraChangeStart: ((RNRegion, RNCamera, Bool) -> Void)? {
414
+ var onCameraChangeStart: ((RNRegion, RNCameraChange, Bool) -> Void)? {
409
415
  didSet { impl.onCameraChangeStart = onCameraChangeStart }
410
416
  }
411
417
  @MainActor
412
- var onCameraChange: ((RNRegion, RNCamera, Bool) -> Void)? {
418
+ var onCameraChange: ((RNRegion, RNCameraChange, Bool) -> Void)? {
413
419
  didSet { impl.onCameraChange = onCameraChange }
414
420
  }
415
421
  @MainActor
416
- var onCameraChangeComplete: ((RNRegion, RNCamera, Bool) -> Void)? {
422
+ var onCameraChangeComplete: ((RNRegion, RNCameraChange, Bool) -> Void)? {
417
423
  didSet { impl.onCameraChangeComplete = onCameraChangeComplete }
418
424
  }
419
425
 
420
426
  @MainActor
421
427
  func showMarkerInfoWindow(id: String) {
422
- impl.showMarkerInfoWindow(id: id);
428
+ impl.showMarkerInfoWindow(id: id)
423
429
  }
424
430
 
425
431
  @MainActor
426
432
  func hideMarkerInfoWindow(id: String) {
427
- impl.hideMarkerInfoWindow(id: id);
433
+ impl.hideMarkerInfoWindow(id: id)
428
434
  }
429
435
 
430
436
  @MainActor
@@ -1,8 +1,8 @@
1
1
  import GoogleMaps
2
2
 
3
3
  extension GMSCameraPosition {
4
- func toRNCamera() -> RNCamera {
5
- return RNCamera(
4
+ func toRNCamera() -> RNCameraChange {
5
+ return RNCameraChange(
6
6
  center: target.toRNLatLng(),
7
7
  zoom: Double(zoom),
8
8
  bearing: bearing,
@@ -2,10 +2,19 @@ import GoogleMaps
2
2
 
3
3
  extension RNCircle {
4
4
  func circleEquals(_ b: RNCircle) -> Bool {
5
- zIndex == b.zIndex && pressable == b.pressable
6
- && center.latitude == b.center.latitude
7
- && center.longitude == b.center.longitude && radius == b.radius
8
- && strokeWidth == b.strokeWidth && strokeColor == b.strokeColor
9
- && fillColor == b.fillColor
5
+ if zIndex != b.zIndex { return false }
6
+ if pressable != b.pressable { return false }
7
+ if !centerEquals(b) { return false }
8
+ if radius != b.radius { return false }
9
+ if strokeWidth != b.strokeWidth { return false }
10
+ if strokeColor != b.strokeColor { return false }
11
+ if fillColor != b.fillColor { return false }
12
+ return true
13
+ }
14
+
15
+ func centerEquals(_ b: RNCircle) -> Bool {
16
+ if center.latitude != b.center.latitude { return false }
17
+ if center.longitude != b.center.longitude { return false }
18
+ return true
10
19
  }
11
20
  }
@@ -1,7 +1,18 @@
1
1
  import CoreLocation
2
+ import GoogleMaps
2
3
 
3
4
  extension RNLatLng {
4
5
  func toCLLocationCoordinate2D() -> CLLocationCoordinate2D {
5
6
  CLLocationCoordinate2D(latitude: latitude, longitude: longitude)
6
7
  }
7
8
  }
9
+
10
+ extension Array where Element == RNLatLng {
11
+ func toGMSPath() -> GMSPath {
12
+ let path = GMSMutablePath()
13
+ for coord in self {
14
+ path.add(coord.toCLLocationCoordinate2D())
15
+ }
16
+ return path
17
+ }
18
+ }
@@ -0,0 +1,10 @@
1
+ extension RNLineCapType {
2
+ func toCGLineCap() -> CGLineCap {
3
+ switch self {
4
+ case .round: return .round
5
+ case .square: return .square
6
+ default: return .butt
7
+ }
8
+ }
9
+ }
10
+
@@ -0,0 +1,11 @@
1
+ extension RNLineJoinType {
2
+ func toCGLineJoin() -> CGLineJoin {
3
+ switch self {
4
+ case .round: return .round
5
+ case .bevel: return .bevel
6
+ default: return .miter
7
+ }
8
+ }
9
+
10
+ }
11
+