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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (119) hide show
  1. package/android/build.gradle +1 -1
  2. package/android/src/main/java/com/rngooglemapsplus/GoogleMapsViewImpl.kt +50 -161
  3. package/android/src/main/java/com/rngooglemapsplus/LocationHandler.kt +38 -36
  4. package/android/src/main/java/com/rngooglemapsplus/MapCircleBuilder.kt +33 -9
  5. package/android/src/main/java/com/rngooglemapsplus/MapMarkerBuilder.kt +73 -18
  6. package/android/src/main/java/com/rngooglemapsplus/MapPolygonBuilder.kt +59 -12
  7. package/android/src/main/java/com/rngooglemapsplus/MapPolylineBuilder.kt.kt +47 -12
  8. package/android/src/main/java/com/rngooglemapsplus/RNGoogleMapsPlusView.kt +12 -9
  9. package/android/src/main/java/com/rngooglemapsplus/extensions/CameraPositionExtension.kt +12 -0
  10. package/android/src/main/java/com/rngooglemapsplus/extensions/IntExtension.kt +28 -0
  11. package/android/src/main/java/com/rngooglemapsplus/extensions/LatLngBounds.kt +15 -0
  12. package/android/src/main/java/com/rngooglemapsplus/extensions/LatLngExtension.kt +6 -0
  13. package/android/src/main/java/com/rngooglemapsplus/extensions/LocationExtension.kt +59 -0
  14. package/android/src/main/java/com/rngooglemapsplus/extensions/RNCameraExtension.kt +1 -2
  15. package/android/src/main/java/com/rngooglemapsplus/extensions/RNLatLngExtension.kt +6 -0
  16. package/android/src/main/java/com/rngooglemapsplus/extensions/RNMarkerExtension.kt +8 -0
  17. package/android/src/main/java/com/rngooglemapsplus/extensions/RNPolygonExtension.kt +2 -0
  18. package/android/src/main/java/com/rngooglemapsplus/extensions/RNPolylineExtension.kt +1 -0
  19. package/ios/GoogleMapViewImpl.swift +39 -180
  20. package/ios/LocationHandler.swift +5 -13
  21. package/ios/MapCircleBuilder.swift +30 -18
  22. package/ios/MapHelper.swift +20 -0
  23. package/ios/MapMarkerBuilder.swift +105 -86
  24. package/ios/MapPolygonBuilder.swift +62 -13
  25. package/ios/MapPolylineBuilder.swift +33 -15
  26. package/ios/RNGoogleMapsPlusView.swift +15 -9
  27. package/ios/extensions/CLError+Extension.swift +14 -0
  28. package/ios/extensions/CLLocation+Extension.swift +27 -0
  29. package/ios/extensions/CLLocationCoordinate2D+Extension.swift +7 -0
  30. package/ios/extensions/GMSCameraPosition+Extension.swift +12 -0
  31. package/ios/extensions/GMSCoordinateBounds+Extension.swift +19 -0
  32. package/ios/extensions/RNLatLng+Extension.swift +7 -0
  33. package/ios/extensions/RNMarker+Extension.swift +7 -3
  34. package/ios/extensions/RNPolygon+Extension.swift.swift +16 -1
  35. package/ios/extensions/RNPolyline+Extension.swift.swift +1 -0
  36. package/lib/module/GoogleMapsPlus.js +7 -0
  37. package/lib/module/GoogleMapsPlus.js.map +1 -0
  38. package/lib/module/index.js +3 -5
  39. package/lib/module/index.js.map +1 -1
  40. package/lib/module/types.js.map +1 -1
  41. package/lib/nitrogen/generated/shared/json/RNGoogleMapsPlusViewConfig.json +44 -0
  42. package/lib/typescript/src/GoogleMapsPlus.d.ts +5 -0
  43. package/lib/typescript/src/GoogleMapsPlus.d.ts.map +1 -0
  44. package/lib/typescript/src/index.d.ts +3 -3
  45. package/lib/typescript/src/index.d.ts.map +1 -1
  46. package/lib/typescript/src/types.d.ts +33 -0
  47. package/lib/typescript/src/types.d.ts.map +1 -1
  48. package/nitrogen/generated/android/c++/JFunc_void_RNLocation.hpp +6 -0
  49. package/nitrogen/generated/android/c++/JHybridRNGoogleMapsPlusViewSpec.cpp +12 -0
  50. package/nitrogen/generated/android/c++/JRNLocation.hpp +32 -2
  51. package/nitrogen/generated/android/c++/JRNLocationAndroid.hpp +82 -0
  52. package/nitrogen/generated/android/c++/JRNLocationIOS.hpp +77 -0
  53. package/nitrogen/generated/android/c++/JRNMarker.hpp +8 -0
  54. package/nitrogen/generated/android/c++/JRNPolygon.hpp +29 -2
  55. package/nitrogen/generated/android/c++/JRNPolygonHole.hpp +72 -0
  56. package/nitrogen/generated/android/c++/JRNPolyline.hpp +4 -0
  57. package/nitrogen/generated/android/kotlin/com/margelo/nitro/rngooglemapsplus/RNLocation.kt +19 -1
  58. package/nitrogen/generated/android/kotlin/com/margelo/nitro/rngooglemapsplus/RNLocationAndroid.kt +50 -0
  59. package/nitrogen/generated/android/kotlin/com/margelo/nitro/rngooglemapsplus/RNLocationIOS.kt +47 -0
  60. package/nitrogen/generated/android/kotlin/com/margelo/nitro/rngooglemapsplus/RNMarker.kt +6 -0
  61. package/nitrogen/generated/android/kotlin/com/margelo/nitro/rngooglemapsplus/RNPolygon.kt +7 -1
  62. package/nitrogen/generated/android/kotlin/com/margelo/nitro/rngooglemapsplus/RNPolygonHole.kt +29 -0
  63. package/nitrogen/generated/android/kotlin/com/margelo/nitro/rngooglemapsplus/RNPolyline.kt +3 -0
  64. package/nitrogen/generated/android/kotlin/com/margelo/nitro/rngooglemapsplus/views/HybridRNGoogleMapsPlusViewManager.kt +8 -3
  65. package/nitrogen/generated/ios/RNGoogleMapsPlus-Swift-Cxx-Bridge.cpp +16 -16
  66. package/nitrogen/generated/ios/RNGoogleMapsPlus-Swift-Cxx-Bridge.hpp +87 -20
  67. package/nitrogen/generated/ios/RNGoogleMapsPlus-Swift-Cxx-Umbrella.hpp +9 -0
  68. package/nitrogen/generated/ios/c++/HybridRNGoogleMapsPlusViewSpecSwift.hpp +12 -3
  69. package/nitrogen/generated/ios/c++/views/HybridRNGoogleMapsPlusViewComponent.mm +8 -0
  70. package/nitrogen/generated/ios/swift/HybridRNGoogleMapsPlusViewSpec_cxx.swift +7 -56
  71. package/nitrogen/generated/ios/swift/RNCamera.swift +1 -8
  72. package/nitrogen/generated/ios/swift/RNHeatmap.swift +1 -8
  73. package/nitrogen/generated/ios/swift/RNHeatmapGradient.swift +11 -15
  74. package/nitrogen/generated/ios/swift/RNInitialProps.swift +1 -8
  75. package/nitrogen/generated/ios/swift/RNLocation.swift +92 -2
  76. package/nitrogen/generated/ios/swift/RNLocationAndroid.swift +215 -0
  77. package/nitrogen/generated/ios/swift/RNLocationConfig.swift +2 -16
  78. package/nitrogen/generated/ios/swift/RNLocationIOS.swift +185 -0
  79. package/nitrogen/generated/ios/swift/RNMarker.swift +47 -15
  80. package/nitrogen/generated/ios/swift/RNPolygon.swift +66 -1
  81. package/nitrogen/generated/ios/swift/RNPolygonHole.swift +47 -0
  82. package/nitrogen/generated/ios/swift/RNPolyline.swift +24 -1
  83. package/nitrogen/generated/ios/swift/RNSnapshotOptions.swift +1 -8
  84. package/nitrogen/generated/shared/c++/RNAndroidLocationConfig.hpp +8 -0
  85. package/nitrogen/generated/shared/c++/RNCamera.hpp +8 -0
  86. package/nitrogen/generated/shared/c++/RNCircle.hpp +8 -0
  87. package/nitrogen/generated/shared/c++/RNHeatmap.hpp +8 -0
  88. package/nitrogen/generated/shared/c++/RNHeatmapGradient.hpp +8 -0
  89. package/nitrogen/generated/shared/c++/RNHeatmapPoint.hpp +8 -0
  90. package/nitrogen/generated/shared/c++/RNIOSLocationConfig.hpp +8 -0
  91. package/nitrogen/generated/shared/c++/RNIndoorBuilding.hpp +8 -0
  92. package/nitrogen/generated/shared/c++/RNIndoorLevel.hpp +8 -0
  93. package/nitrogen/generated/shared/c++/RNInitialProps.hpp +8 -0
  94. package/nitrogen/generated/shared/c++/RNKMLayer.hpp +8 -0
  95. package/nitrogen/generated/shared/c++/RNLatLng.hpp +8 -0
  96. package/nitrogen/generated/shared/c++/RNLatLngBounds.hpp +8 -0
  97. package/nitrogen/generated/shared/c++/RNLocation.hpp +41 -2
  98. package/nitrogen/generated/shared/c++/RNLocationAndroid.hpp +104 -0
  99. package/nitrogen/generated/shared/c++/RNLocationConfig.hpp +8 -0
  100. package/nitrogen/generated/shared/c++/RNLocationIOS.hpp +99 -0
  101. package/nitrogen/generated/shared/c++/RNLocationPermissionResult.hpp +8 -0
  102. package/nitrogen/generated/shared/c++/RNMapPadding.hpp +8 -0
  103. package/nitrogen/generated/shared/c++/RNMapUiSettings.hpp +8 -0
  104. package/nitrogen/generated/shared/c++/RNMapZoomConfig.hpp +8 -0
  105. package/nitrogen/generated/shared/c++/RNMarker.hpp +17 -1
  106. package/nitrogen/generated/shared/c++/RNMarkerSvg.hpp +8 -0
  107. package/nitrogen/generated/shared/c++/RNPolygon.hpp +21 -2
  108. package/nitrogen/generated/shared/c++/RNPolygonHole.hpp +77 -0
  109. package/nitrogen/generated/shared/c++/RNPolyline.hpp +13 -1
  110. package/nitrogen/generated/shared/c++/RNPosition.hpp +8 -0
  111. package/nitrogen/generated/shared/c++/RNRegion.hpp +8 -0
  112. package/nitrogen/generated/shared/c++/RNSize.hpp +8 -0
  113. package/nitrogen/generated/shared/c++/RNSnapshotOptions.hpp +8 -0
  114. package/package.json +9 -16
  115. package/src/GoogleMapsPlus.tsx +20 -0
  116. package/src/index.tsx +6 -14
  117. package/src/types.ts +36 -0
  118. package/lib/module/package.json +0 -1
  119. package/lib/typescript/package.json +0 -1
@@ -3,20 +3,16 @@ import SVGKit
3
3
  import UIKit
4
4
 
5
5
  final class MapMarkerBuilder {
6
- private let iconCache = NSCache<NSString, UIImage>()
6
+ private let iconCache: NSCache<NSNumber, UIImage> = {
7
+ let c = NSCache<NSNumber, UIImage>()
8
+ c.countLimit = 512
9
+ return c
10
+ }()
7
11
  private var tasks: [String: Task<Void, Never>] = [:]
8
- private let queue = DispatchQueue(
9
- label: "map.marker.render",
10
- qos: .userInitiated,
11
- attributes: .concurrent
12
- )
13
12
 
14
13
  func build(_ m: RNMarker, icon: UIImage?) -> GMSMarker {
15
14
  let marker = GMSMarker(
16
- position: CLLocationCoordinate2D(
17
- latitude: m.coordinate.latitude,
18
- longitude: m.coordinate.longitude
19
- )
15
+ position: m.coordinate.toCLLocationCoordinate2D()
20
16
  )
21
17
  marker.userData = m.id
22
18
  marker.tracksViewChanges = true
@@ -26,6 +22,10 @@ final class MapMarkerBuilder {
26
22
  m.opacity.map { marker.iconView?.alpha = CGFloat($0) }
27
23
  m.flat.map { marker.isFlat = $0 }
28
24
  m.draggable.map { marker.isDraggable = $0 }
25
+ m.rotation.map { marker.rotation = $0 }
26
+ m.infoWindowAnchor.map {
27
+ marker.infoWindowAnchor = CGPoint(x: $0.x, y: $0.y)
28
+ }
29
29
  m.anchor.map {
30
30
  marker.groundAnchor = CGPoint(
31
31
  x: $0.x,
@@ -34,7 +34,8 @@ final class MapMarkerBuilder {
34
34
  }
35
35
  m.zIndex.map { marker.zIndex = Int32($0) }
36
36
 
37
- DispatchQueue.main.asyncAfter(deadline: .now() + 0.25) { [weak marker] in
37
+ onMainAsync { [weak marker] in
38
+ try? await Task.sleep(nanoseconds: 250_000_000)
38
39
  marker?.tracksViewChanges = false
39
40
  }
40
41
 
@@ -43,21 +44,41 @@ final class MapMarkerBuilder {
43
44
 
44
45
  @MainActor
45
46
  func update(_ prev: RNMarker, _ next: RNMarker, _ m: GMSMarker) {
46
- m.position = CLLocationCoordinate2D(
47
- latitude: next.coordinate.latitude,
48
- longitude: next.coordinate.longitude
49
- )
47
+ if prev.coordinate.latitude != next.coordinate.latitude
48
+ || prev.coordinate.longitude != next.coordinate.longitude {
49
+ m.position = next.coordinate.toCLLocationCoordinate2D()
50
+ }
51
+
52
+ if prev.title != next.title {
53
+ m.title = next.title
54
+ }
55
+
56
+ if prev.snippet != next.snippet {
57
+ m.snippet = next.snippet
58
+ }
59
+
60
+ if prev.opacity != next.opacity {
61
+ let opacity = Float(next.opacity ?? 1)
62
+ m.opacity = opacity
63
+ m.iconView?.alpha = CGFloat(opacity)
64
+ }
65
+
66
+ if prev.flat != next.flat {
67
+ m.isFlat = next.flat ?? false
68
+ }
69
+
70
+ if prev.draggable != next.draggable {
71
+ m.isDraggable = next.draggable ?? false
72
+ }
73
+
74
+ if prev.rotation != next.rotation {
75
+ m.rotation = next.rotation ?? 0
76
+ }
77
+
78
+ if prev.zIndex != next.zIndex {
79
+ m.zIndex = Int32(next.zIndex ?? 0)
80
+ }
50
81
 
51
- m.title = next.title
52
- m.snippet = next.snippet
53
- m.iconView?.alpha = CGFloat(next.opacity ?? 0)
54
- m.isFlat = next.flat ?? false
55
- m.isDraggable = next.draggable ?? false
56
- m.zIndex = Int32(next.zIndex ?? 0)
57
- m.groundAnchor = CGPoint(
58
- x: next.anchor?.x ?? 0.5,
59
- y: next.anchor?.y ?? 1
60
- )
61
82
  if !prev.markerStyleEquals(next) {
62
83
  buildIconAsync(next.id, next) { img in
63
84
  m.tracksViewChanges = true
@@ -66,14 +87,38 @@ final class MapMarkerBuilder {
66
87
  if prev.anchor?.x != next.anchor?.x || prev.anchor?.y != next.anchor?.y {
67
88
  m.groundAnchor = CGPoint(
68
89
  x: next.anchor?.x ?? 0.5,
69
- y: next.anchor?.y ?? 0.5
90
+ y: next.anchor?.y ?? 1
91
+ )
92
+ }
93
+
94
+ if prev.infoWindowAnchor?.x != next.infoWindowAnchor?.x
95
+ || prev.infoWindowAnchor?.y != next.infoWindowAnchor?.y {
96
+ m.infoWindowAnchor = CGPoint(
97
+ x: next.infoWindowAnchor?.x ?? 0.5,
98
+ y: next.infoWindowAnchor?.y ?? 0
70
99
  )
71
100
  }
72
101
 
73
- DispatchQueue.main.asyncAfter(deadline: .now() + 0.25) { [weak m] in
102
+ onMainAsync { [weak m] in
103
+ try? await Task.sleep(nanoseconds: 250_000_000)
74
104
  m?.tracksViewChanges = false
75
105
  }
76
106
  }
107
+ } else {
108
+ if prev.anchor?.x != next.anchor?.x || prev.anchor?.y != next.anchor?.y {
109
+ m.groundAnchor = CGPoint(
110
+ x: next.anchor?.x ?? 0.5,
111
+ y: next.anchor?.y ?? 1
112
+ )
113
+ }
114
+
115
+ if prev.infoWindowAnchor?.x != next.infoWindowAnchor?.x
116
+ || prev.infoWindowAnchor?.y != next.infoWindowAnchor?.y {
117
+ m.infoWindowAnchor = CGPoint(
118
+ x: next.infoWindowAnchor?.x ?? 0.5,
119
+ y: next.infoWindowAnchor?.y ?? 0
120
+ )
121
+ }
77
122
  }
78
123
  }
79
124
 
@@ -100,7 +145,8 @@ final class MapMarkerBuilder {
100
145
  guard let self else { return }
101
146
  defer { self.tasks.removeValue(forKey: id) }
102
147
 
103
- let img = await self.renderUIImage(m)
148
+ let scale = UIScreen.main.scale
149
+ let img = await self.renderUIImage(m, scale)
104
150
  guard let img, !Task.isCancelled else { return }
105
151
 
106
152
  self.iconCache.setObject(img, forKey: key)
@@ -128,65 +174,38 @@ final class MapMarkerBuilder {
128
174
  iconCache.removeAllObjects()
129
175
  }
130
176
 
131
- private func renderUIImage(_ m: RNMarker) async -> UIImage? {
132
- guard let iconSvg = m.iconSvg else {
133
- return nil
134
- }
135
-
136
- return await withTaskCancellationHandler(
137
- operation: {
138
- await withCheckedContinuation {
139
- (cont: CheckedContinuation<UIImage?, Never>) in
140
- queue.async {
141
- if Task.isCancelled {
142
- cont.resume(returning: nil)
143
- return
144
- }
145
-
146
- let targetW = max(1, Int(CGFloat(iconSvg.width)))
147
- let targetH = max(1, Int(CGFloat(iconSvg.height)))
148
- let size = CGSize(width: targetW, height: targetH)
149
-
150
- guard
151
- let data = iconSvg.svgString.data(using: .utf8),
152
- let svgImg = SVGKImage(data: data)
153
- else {
154
- cont.resume(returning: nil)
155
- return
156
- }
157
-
158
- svgImg.size = size
159
-
160
- if Task.isCancelled {
161
- cont.resume(returning: nil)
162
- return
163
- }
164
-
165
- guard let base = svgImg.uiImage else {
166
- cont.resume(returning: nil)
167
- return
168
- }
169
-
170
- let scale = UIScreen.main.scale
171
- let img: UIImage
172
- if let cg = base.cgImage {
173
- img = UIImage(cgImage: cg, scale: scale, orientation: .up)
174
- } else {
175
- let fmt = UIGraphicsImageRendererFormat.default()
176
- fmt.opaque = false
177
- fmt.scale = scale
178
- let renderer = UIGraphicsImageRenderer(size: size, format: fmt)
179
- img = renderer.image { _ in
180
- base.draw(in: CGRect(origin: .zero, size: size))
181
- }
182
- }
183
-
184
- cont.resume(returning: img)
185
- }
186
- }
177
+ private func renderUIImage(_ m: RNMarker, _ scale: CGFloat) async -> UIImage? {
178
+ guard let iconSvg = m.iconSvg,
179
+ let data = iconSvg.svgString.data(using: .utf8)
180
+ else { return nil }
187
181
 
188
- },
189
- onCancel: {}
182
+ let size = CGSize(
183
+ width: max(1, CGFloat(iconSvg.width)),
184
+ height: max(1, CGFloat(iconSvg.height))
190
185
  )
186
+
187
+ return await Task.detached(priority: .userInitiated) {
188
+ autoreleasepool {
189
+ guard let svgImg = SVGKImage(data: data) else { return nil }
190
+ svgImg.size = size
191
+
192
+ guard !Task.isCancelled else { return nil }
193
+ guard let base = svgImg.uiImage else { return nil }
194
+
195
+ if let cg = base.cgImage {
196
+ return UIImage(cgImage: cg, scale: scale, orientation: .up)
197
+ }
198
+ guard !Task.isCancelled else { return nil }
199
+ let fmt = UIGraphicsImageRendererFormat.default()
200
+ fmt.opaque = false
201
+ fmt.scale = scale
202
+ guard !Task.isCancelled else { return nil }
203
+ let renderer = UIGraphicsImageRenderer(size: size, format: fmt)
204
+ return renderer.image { _ in
205
+ base.draw(in: CGRect(origin: .zero, size: size))
206
+ }
207
+ }
208
+ }.value
191
209
  }
210
+
192
211
  }
@@ -5,7 +5,7 @@ final class MapPolygonBuilder {
5
5
  let path = GMSMutablePath()
6
6
  p.coordinates.forEach {
7
7
  path.add(
8
- CLLocationCoordinate2D(latitude: $0.latitude, longitude: $0.longitude)
8
+ $0.toCLLocationCoordinate2D()
9
9
  )
10
10
  }
11
11
 
@@ -15,24 +15,73 @@ final class MapPolygonBuilder {
15
15
  p.strokeColor.map { pg.strokeColor = $0.toUIColor() }
16
16
  p.strokeWidth.map { pg.strokeWidth = CGFloat($0) }
17
17
  p.pressable.map { pg.isTappable = $0 }
18
+ p.geodesic.map { pg.geodesic = $0 }
19
+ p.holes.map {
20
+ pg.holes = $0.map { hole in
21
+ let path = GMSMutablePath()
22
+ hole.coordinates.forEach { path.add($0.toCLLocationCoordinate2D()) }
23
+ return path
24
+ }
25
+ }
18
26
  p.zIndex.map { pg.zIndex = Int32($0) }
19
27
 
20
28
  return pg
21
29
  }
22
30
 
23
- func update(_ next: RNPolygon, _ pg: GMSPolygon) {
24
- let path = GMSMutablePath()
25
- next.coordinates.forEach {
26
- path.add(
27
- CLLocationCoordinate2D(latitude: $0.latitude, longitude: $0.longitude)
28
- )
31
+ func update(_ prev: RNPolygon, _ next: RNPolygon, _ pg: GMSPolygon) {
32
+ let coordsChanged =
33
+ prev.coordinates.count != next.coordinates.count
34
+ || !zip(prev.coordinates, next.coordinates).allSatisfy {
35
+ $0.latitude == $1.latitude && $0.longitude == $1.longitude
36
+ }
37
+
38
+ if coordsChanged {
39
+ let path = GMSMutablePath()
40
+ next.coordinates.forEach { path.add($0.toCLLocationCoordinate2D()) }
41
+ pg.path = path
42
+ }
43
+
44
+ let prevHoles = prev.holes ?? []
45
+ let nextHoles = next.holes ?? []
46
+ let holesChanged =
47
+ prevHoles.count != nextHoles.count
48
+ || !zip(prevHoles, nextHoles).allSatisfy { a, b in
49
+ a.coordinates.count == b.coordinates.count
50
+ && zip(a.coordinates, b.coordinates).allSatisfy {
51
+ $0.latitude == $1.latitude && $0.longitude == $1.longitude
52
+ }
53
+ }
54
+
55
+ if holesChanged {
56
+ pg.holes = nextHoles.map { hole in
57
+ let path = GMSMutablePath()
58
+ hole.coordinates.forEach { path.add($0.toCLLocationCoordinate2D()) }
59
+ return path
60
+ }
61
+ }
62
+
63
+ if prev.fillColor != next.fillColor {
64
+ pg.fillColor = next.fillColor?.toUIColor() ?? .clear
29
65
  }
30
- pg.path = path
31
66
 
32
- pg.fillColor = next.fillColor?.toUIColor() ?? .clear
33
- pg.strokeColor = next.strokeColor?.toUIColor() ?? .black
34
- pg.strokeWidth = CGFloat(next.strokeWidth ?? 1.0)
35
- pg.isTappable = next.pressable ?? false
36
- pg.zIndex = Int32(next.zIndex ?? 0)
67
+ if prev.strokeColor != next.strokeColor {
68
+ pg.strokeColor = next.strokeColor?.toUIColor() ?? .black
69
+ }
70
+
71
+ if prev.strokeWidth != next.strokeWidth {
72
+ pg.strokeWidth = CGFloat(next.strokeWidth ?? 1.0)
73
+ }
74
+
75
+ if prev.pressable != next.pressable {
76
+ pg.isTappable = next.pressable ?? false
77
+ }
78
+
79
+ if prev.geodesic != next.geodesic {
80
+ pg.geodesic = next.geodesic ?? false
81
+ }
82
+
83
+ if prev.zIndex != next.zIndex {
84
+ pg.zIndex = Int32(next.zIndex ?? 0)
85
+ }
37
86
  }
38
87
  }
@@ -5,7 +5,7 @@ final class MapPolylineBuilder {
5
5
  let path = GMSMutablePath()
6
6
  p.coordinates.forEach {
7
7
  path.add(
8
- CLLocationCoordinate2D(latitude: $0.latitude, longitude: $0.longitude)
8
+ $0.toCLLocationCoordinate2D()
9
9
  )
10
10
  }
11
11
 
@@ -16,25 +16,43 @@ final class MapPolylineBuilder {
16
16
  p.lineCap.map { _ in /* not supported */ }
17
17
  p.lineJoin.map { _ in /* not supported */ }
18
18
  p.pressable.map { pl.isTappable = $0 }
19
+ p.geodesic.map { pl.geodesic = $0 }
19
20
  p.zIndex.map { pl.zIndex = Int32($0) }
20
21
 
21
22
  return pl
22
23
  }
23
24
 
24
- func update(_ next: RNPolyline, _ pl: GMSPolyline) {
25
- let path = GMSMutablePath()
26
- next.coordinates.forEach {
27
- path.add(
28
- CLLocationCoordinate2D(latitude: $0.latitude, longitude: $0.longitude)
29
- )
25
+ func update(_ prev: RNPolyline, _ next: RNPolyline, _ pl: GMSPolyline) {
26
+ let coordsChanged =
27
+ prev.coordinates.count != next.coordinates.count
28
+ || !zip(prev.coordinates, next.coordinates).allSatisfy {
29
+ $0.latitude == $1.latitude && $0.longitude == $1.longitude
30
+ }
31
+
32
+ if coordsChanged {
33
+ let path = GMSMutablePath()
34
+ next.coordinates.forEach { path.add($0.toCLLocationCoordinate2D()) }
35
+ pl.path = path
36
+ }
37
+
38
+ if prev.width != next.width {
39
+ pl.strokeWidth = CGFloat(next.width ?? 1.0)
40
+ }
41
+
42
+ if prev.color != next.color {
43
+ pl.strokeColor = next.color?.toUIColor() ?? .black
44
+ }
45
+
46
+ if prev.pressable != next.pressable {
47
+ pl.isTappable = next.pressable ?? false
48
+ }
49
+
50
+ if prev.geodesic != next.geodesic {
51
+ pl.geodesic = next.geodesic ?? false
52
+ }
53
+
54
+ if prev.zIndex != next.zIndex {
55
+ pl.zIndex = Int32(next.zIndex ?? 0)
30
56
  }
31
- pl.path = path
32
-
33
- /* lineCap not supported */
34
- /* lineJoin not supported */
35
- pl.strokeWidth = CGFloat(next.width ?? 1.0)
36
- pl.strokeColor = next.color?.toUIColor() ?? .black
37
- pl.isTappable = next.pressable ?? false
38
- pl.zIndex = Int32(next.zIndex ?? 0)
39
57
  }
40
58
  }
@@ -30,19 +30,25 @@ final class RNGoogleMapsPlusView: HybridRNGoogleMapsPlusViewSpec {
30
30
  )
31
31
  }
32
32
 
33
+ @MainActor
33
34
  func afterUpdate() {
34
35
  if !propsInitialized {
35
36
  propsInitialized = true
36
- Task { @MainActor in
37
- impl.initMapView(
38
- mapId: self.initialProps?.mapId,
39
- liteMode: self.initialProps?.liteMode,
40
- camera: self.initialProps?.camera?.toGMSCameraPosition(current: nil)
41
- )
37
+ let options = GMSMapViewOptions()
38
+ initialProps?.mapId.map { options.mapID = GMSMapID(identifier: $0) }
39
+ initialProps?.liteMode.map { _ in /* not supported */ }
40
+ initialProps?.camera.map {
41
+ options.camera = $0.toGMSCameraPosition(current: nil)
42
42
  }
43
+ impl.initMapView(googleMapOptions: options)
43
44
  }
44
45
  }
45
46
 
47
+ @MainActor
48
+ func dispose() {
49
+ impl.deinitInternal()
50
+ }
51
+
46
52
  @MainActor
47
53
  var initialProps: RNInitialProps? {
48
54
  didSet {
@@ -167,7 +173,7 @@ final class RNGoogleMapsPlusView: HybridRNGoogleMapsPlusViewSpec {
167
173
  if let prev = prevById[id] {
168
174
  if !prev.polylineEquals(next) {
169
175
  impl.updatePolyline(id: id) { pl in
170
- self.polylineBuilder.update(next, pl)
176
+ self.polylineBuilder.update(prev, next, pl)
171
177
  }
172
178
  }
173
179
  } else {
@@ -199,7 +205,7 @@ final class RNGoogleMapsPlusView: HybridRNGoogleMapsPlusViewSpec {
199
205
  if let prev = prevById[id] {
200
206
  if !prev.polygonEquals(next) {
201
207
  impl.updatePolygon(id: id) { pg in
202
- self.polygonBuilder.update(next, pg)
208
+ self.polygonBuilder.update(prev, next, pg)
203
209
  }
204
210
  }
205
211
  } else {
@@ -228,7 +234,7 @@ final class RNGoogleMapsPlusView: HybridRNGoogleMapsPlusViewSpec {
228
234
  if let prev = prevById[id] {
229
235
  if !prev.circleEquals(next) {
230
236
  impl.updateCircle(id: id) { circle in
231
- self.circleBuilder.update(next, circle)
237
+ self.circleBuilder.update(prev, next, circle)
232
238
  }
233
239
  }
234
240
  } else {
@@ -0,0 +1,14 @@
1
+ import CoreLocation
2
+
3
+ extension CLError.Code {
4
+ var toRNLocationErrorCode: RNLocationErrorCode {
5
+ switch self {
6
+ case .denied:
7
+ return .permissionDenied
8
+ case .locationUnknown, .network:
9
+ return .positionUnavailable
10
+ default:
11
+ return .internalError
12
+ }
13
+ }
14
+ }
@@ -0,0 +1,27 @@
1
+ import CoreLocation
2
+
3
+ extension CLLocation {
4
+ func toRnLocation() -> RNLocation {
5
+ return RNLocation(
6
+ center: RNLatLng(
7
+ latitude: coordinate.latitude,
8
+ longitude: coordinate.longitude
9
+ ),
10
+ altitude: altitude,
11
+ accuracy: horizontalAccuracy,
12
+ bearing: course,
13
+ speed: speed,
14
+ time: timestamp.timeIntervalSince1970 * 1000,
15
+ android: nil,
16
+ ios: RNLocationIOS(
17
+ horizontalAccuracy: horizontalAccuracy,
18
+ verticalAccuracy: verticalAccuracy,
19
+ speedAccuracy: speedAccuracy,
20
+ courseAccuracy: courseAccuracy,
21
+ floor: floor.map { Double($0.level)},
22
+ isFromMockProvider: false,
23
+ timestamp: timestamp.timeIntervalSince1970 * 1000
24
+ )
25
+ )
26
+ }
27
+ }
@@ -0,0 +1,7 @@
1
+ import CoreLocation
2
+
3
+ extension CLLocationCoordinate2D {
4
+ func toRNLatLng() -> RNLatLng {
5
+ RNLatLng(latitude: latitude, longitude: longitude)
6
+ }
7
+ }
@@ -0,0 +1,12 @@
1
+ import GoogleMaps
2
+
3
+ extension GMSCameraPosition {
4
+ func toRNCamera() -> RNCamera {
5
+ return RNCamera(
6
+ center: target.toRNLatLng(),
7
+ zoom: Double(zoom),
8
+ bearing: bearing,
9
+ tilt: viewingAngle
10
+ )
11
+ }
12
+ }
@@ -0,0 +1,19 @@
1
+ import GoogleMaps
2
+
3
+ extension GMSCoordinateBounds {
4
+ func toRNRegion() -> RNRegion {
5
+ let center = CLLocationCoordinate2D(
6
+ latitude: (northEast.latitude + southWest.latitude) / 2.0,
7
+ longitude: (northEast.longitude + southWest.longitude) / 2.0
8
+ )
9
+
10
+ let latDelta = northEast.latitude - southWest.latitude
11
+ let lngDelta = northEast.longitude - southWest.longitude
12
+
13
+ return RNRegion(
14
+ center: center.toRNLatLng(),
15
+ latitudeDelta: latDelta,
16
+ longitudeDelta: lngDelta
17
+ )
18
+ }
19
+ }
@@ -0,0 +1,7 @@
1
+ import CoreLocation
2
+
3
+ extension RNLatLng {
4
+ func toCLLocationCoordinate2D() -> CLLocationCoordinate2D {
5
+ CLLocationCoordinate2D(latitude: latitude, longitude: longitude)
6
+ }
7
+ }
@@ -6,20 +6,24 @@ extension RNMarker {
6
6
  && coordinate.latitude == b.coordinate.latitude
7
7
  && coordinate.longitude == b.coordinate.longitude
8
8
  && anchor?.x == b.anchor?.x && anchor?.y == b.anchor?.y
9
+ && showInfoWindow == b.showInfoWindow && title == b.title
10
+ && snippet == b.snippet && opacity == b.opacity && flat == b.flat
11
+ && draggable == b.draggable && rotation == b.rotation
12
+ && infoWindowAnchor?.x == b.infoWindowAnchor?.x
13
+ && infoWindowAnchor?.y == b.infoWindowAnchor?.y
9
14
  && markerStyleEquals(b)
10
15
  }
11
16
 
12
17
  func markerStyleEquals(_ b: RNMarker) -> Bool {
13
18
  iconSvg?.width == b.iconSvg?.width && iconSvg?.height == b.iconSvg?.height
14
19
  && iconSvg?.svgString == b.iconSvg?.svgString
15
-
16
20
  }
17
21
 
18
- func styleHash() -> NSString {
22
+ func styleHash() -> NSNumber {
19
23
  var hasher = Hasher()
20
24
  hasher.combine(iconSvg?.width)
21
25
  hasher.combine(iconSvg?.height)
22
26
  hasher.combine(iconSvg?.svgString)
23
- return String(hasher.finalize()) as NSString
27
+ return NSNumber(value: hasher.finalize())
24
28
  }
25
29
  }
@@ -7,7 +7,9 @@ extension RNPolygon {
7
7
  strokeWidth == b.strokeWidth,
8
8
  fillColor == b.fillColor,
9
9
  strokeColor == b.strokeColor,
10
- coordinates.count == b.coordinates.count
10
+ geodesic == b.geodesic,
11
+ coordinates.count == b.coordinates.count,
12
+ holes?.count == b.holes?.count
11
13
  else { return false }
12
14
 
13
15
  for i in 0..<coordinates.count {
@@ -17,6 +19,19 @@ extension RNPolygon {
17
19
  }
18
20
  }
19
21
 
22
+ for i in 0..<(holes?.count ?? 0) {
23
+ let ha = holes![i]
24
+ let hb = b.holes![i]
25
+ if ha.coordinates.count != hb.coordinates.count { return false }
26
+
27
+ for j in 0..<ha.coordinates.count {
28
+ if ha.coordinates[j].latitude != hb.coordinates[j].latitude
29
+ || ha.coordinates[j].longitude != hb.coordinates[j].longitude {
30
+ return false
31
+ }
32
+ }
33
+ }
34
+
20
35
  return true
21
36
  }
22
37
  }
@@ -7,6 +7,7 @@ extension RNPolyline {
7
7
  lineCap == b.lineCap,
8
8
  lineJoin == b.lineJoin,
9
9
  color == b.color,
10
+ geodesic == b.geodesic,
10
11
  coordinates.count == b.coordinates.count
11
12
  else { return false }
12
13
 
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+
3
+ import { getHostComponent, NitroModules } from 'react-native-nitro-modules';
4
+ import ViewConfig from '../nitrogen/generated/shared/json/RNGoogleMapsPlusViewConfig.json' with { type: 'json' };
5
+ export const GoogleMapsView = getHostComponent('RNGoogleMapsPlusView', () => ViewConfig);
6
+ export const GoogleMapsModule = NitroModules.createHybridObject('RNGoogleMapsPlusModule');
7
+ //# sourceMappingURL=GoogleMapsPlus.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["getHostComponent","NitroModules","ViewConfig","type","GoogleMapsView","GoogleMapsModule","createHybridObject"],"sourceRoot":"../../src","sources":["GoogleMapsPlus.tsx"],"mappings":";;AAAA,SAASA,gBAAgB,EAAEC,YAAY,QAAQ,4BAA4B;AAE3E,OAAOC,UAAU,MAAM,mEAAmE,QAAQC,IAAI,EAAE,MAAM;AAS9G,OAAO,MAAMC,cAAc,GAAGJ,gBAAgB,CAG5C,sBAAsB,EAAE,MAAME,UAAU,CAAC;AAE3C,OAAO,MAAMG,gBAAgB,GAC3BJ,YAAY,CAACK,kBAAkB,CAC7B,wBACF,CAAC","ignoreList":[]}
@@ -1,8 +1,6 @@
1
1
  "use strict";
2
2
 
3
- import { getHostComponent, NitroModules } from 'react-native-nitro-modules';
4
- import ViewConfig from '../nitrogen/generated/shared/json/RNGoogleMapsPlusViewConfig.json';
5
- export * from "./types.js";
6
- export const GoogleMapsView = getHostComponent('RNGoogleMapsPlusView', () => ViewConfig);
7
- export const GoogleMapsModule = NitroModules.createHybridObject('RNGoogleMapsPlusModule');
3
+ import { GoogleMapsView, GoogleMapsModule } from './GoogleMapsPlus';
4
+ export * from './types';
5
+ export { GoogleMapsView, GoogleMapsModule };
8
6
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["getHostComponent","NitroModules","ViewConfig","GoogleMapsView","GoogleMapsModule","createHybridObject"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":";;AAAA,SAASA,gBAAgB,EAAEC,YAAY,QAAQ,4BAA4B;AAE3E,OAAOC,UAAU,MAAM,mEAAmE;AAS1F,cAAc,YAAS;AAIvB,OAAO,MAAMC,cAAc,GAAGH,gBAAgB,CAG5C,sBAAsB,EAAE,MAAME,UAAU,CAAC;AAE3C,OAAO,MAAME,gBAAgB,GAC3BH,YAAY,CAACI,kBAAkB,CAC7B,wBACF,CAAC","ignoreList":[]}
1
+ {"version":3,"names":["GoogleMapsView","GoogleMapsModule"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":";;AAAA,SAASA,cAAc,EAAEC,gBAAgB,QAAQ,kBAAkB;AAOnE,cAAc,SAAS;AAQvB,SAASD,cAAc,EAAEC,gBAAgB","ignoreList":[]}
@@ -1 +1 @@
1
- {"version":3,"names":["RNAndroidLocationPriority","RNIOSLocationAccuracy","RNAndroidLocationPermissionResult","RNIOSPermissionResult","RNLocationErrorCode","RNMapErrorCode"],"sourceRoot":"../../src","sources":["types.ts"],"mappings":";;AAgEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAIA;AACA;AACA;;AAmJA,WAAYA,yBAAyB,0BAAzBA,yBAAyB;EAAzBA,yBAAyB,CAAzBA,yBAAyB;EAAzBA,yBAAyB,CAAzBA,yBAAyB;EAAzBA,yBAAyB,CAAzBA,yBAAyB;EAAzBA,yBAAyB,CAAzBA,yBAAyB;EAAA,OAAzBA,yBAAyB;AAAA;AAYrC,WAAYC,qBAAqB,0BAArBA,qBAAqB;EAArBA,qBAAqB,CAArBA,qBAAqB;EAArBA,qBAAqB,CAArBA,qBAAqB;EAArBA,qBAAqB,CAArBA,qBAAqB;EAArBA,qBAAqB,CAArBA,qBAAqB;EAAA,OAArBA,qBAAqB;AAAA;AAYjC,WAAYC,iCAAiC,0BAAjCA,iCAAiC;EAAjCA,iCAAiC,CAAjCA,iCAAiC;EAAjCA,iCAAiC,CAAjCA,iCAAiC;EAAjCA,iCAAiC,CAAjCA,iCAAiC;EAAA,OAAjCA,iCAAiC;AAAA;AAM7C,WAAYC,qBAAqB,0BAArBA,qBAAqB;EAArBA,qBAAqB,CAArBA,qBAAqB;EAArBA,qBAAqB,CAArBA,qBAAqB;EAAA,OAArBA,qBAAqB;AAAA;AAUjC,WAAYC,mBAAmB,0BAAnBA,mBAAmB;EAAnBA,mBAAmB,CAAnBA,mBAAmB;EAAnBA,mBAAmB,CAAnBA,mBAAmB;EAAnBA,mBAAmB,CAAnBA,mBAAmB;EAAnBA,mBAAmB,CAAnBA,mBAAmB;EAAnBA,mBAAmB,CAAnBA,mBAAmB;EAAnBA,mBAAmB,CAAnBA,mBAAmB;EAAA,OAAnBA,mBAAmB;AAAA;AAS/B,WAAYC,cAAc,0BAAdA,cAAc;EAAdA,cAAc,CAAdA,cAAc;EAAdA,cAAc,CAAdA,cAAc;EAAdA,cAAc,CAAdA,cAAc;EAAdA,cAAc,CAAdA,cAAc;EAAdA,cAAc,CAAdA,cAAc;EAAdA,cAAc,CAAdA,cAAc;EAAdA,cAAc,CAAdA,cAAc;EAAA,OAAdA,cAAc;AAAA","ignoreList":[]}
1
+ {"version":3,"names":["RNAndroidLocationPriority","RNIOSLocationAccuracy","RNAndroidLocationPermissionResult","RNIOSPermissionResult","RNLocationErrorCode","RNMapErrorCode"],"sourceRoot":"../../src","sources":["types.ts"],"mappings":";;AAgEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAIA;AACA;AACA;;AA6JA,WAAYA,yBAAyB,0BAAzBA,yBAAyB;EAAzBA,yBAAyB,CAAzBA,yBAAyB;EAAzBA,yBAAyB,CAAzBA,yBAAyB;EAAzBA,yBAAyB,CAAzBA,yBAAyB;EAAzBA,yBAAyB,CAAzBA,yBAAyB;EAAA,OAAzBA,yBAAyB;AAAA;AAYrC,WAAYC,qBAAqB,0BAArBA,qBAAqB;EAArBA,qBAAqB,CAArBA,qBAAqB;EAArBA,qBAAqB,CAArBA,qBAAqB;EAArBA,qBAAqB,CAArBA,qBAAqB;EAArBA,qBAAqB,CAArBA,qBAAqB;EAAA,OAArBA,qBAAqB;AAAA;AAYjC,WAAYC,iCAAiC,0BAAjCA,iCAAiC;EAAjCA,iCAAiC,CAAjCA,iCAAiC;EAAjCA,iCAAiC,CAAjCA,iCAAiC;EAAjCA,iCAAiC,CAAjCA,iCAAiC;EAAA,OAAjCA,iCAAiC;AAAA;AAM7C,WAAYC,qBAAqB,0BAArBA,qBAAqB;EAArBA,qBAAqB,CAArBA,qBAAqB;EAArBA,qBAAqB,CAArBA,qBAAqB;EAAA,OAArBA,qBAAqB;AAAA;AAoCjC,WAAYC,mBAAmB,0BAAnBA,mBAAmB;EAAnBA,mBAAmB,CAAnBA,mBAAmB;EAAnBA,mBAAmB,CAAnBA,mBAAmB;EAAnBA,mBAAmB,CAAnBA,mBAAmB;EAAnBA,mBAAmB,CAAnBA,mBAAmB;EAAnBA,mBAAmB,CAAnBA,mBAAmB;EAAnBA,mBAAmB,CAAnBA,mBAAmB;EAAA,OAAnBA,mBAAmB;AAAA;AAS/B,WAAYC,cAAc,0BAAdA,cAAc;EAAdA,cAAc,CAAdA,cAAc;EAAdA,cAAc,CAAdA,cAAc;EAAdA,cAAc,CAAdA,cAAc;EAAdA,cAAc,CAAdA,cAAc;EAAdA,cAAc,CAAdA,cAAc;EAAdA,cAAc,CAAdA,cAAc;EAAdA,cAAc,CAAdA,cAAc;EAAA,OAAdA,cAAc;AAAA","ignoreList":[]}