react-native-google-maps-plus 1.7.0-dev.9 → 1.8.0

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 (71) 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 +120 -124
  4. package/android/src/main/java/com/rngooglemapsplus/MapCircleBuilder.kt +2 -3
  5. package/android/src/main/java/com/rngooglemapsplus/MapMarkerBuilder.kt +83 -53
  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 +30 -12
  9. package/android/src/main/java/com/rngooglemapsplus/extensions/BitmapExtension.kt +35 -0
  10. package/android/src/main/java/com/rngooglemapsplus/extensions/LatLngBoundsExtension.kt +31 -0
  11. package/android/src/main/java/com/rngooglemapsplus/extensions/MapObjectTagExtensions.kt +84 -0
  12. package/android/src/main/java/com/rngooglemapsplus/extensions/RNLineCapTypeExtension.kt +14 -0
  13. package/android/src/main/java/com/rngooglemapsplus/extensions/RNLineJoinTypeExtension.kt +12 -0
  14. package/android/src/main/java/com/rngooglemapsplus/extensions/RNMapCircleExtension.kt +7 -1
  15. package/android/src/main/java/com/rngooglemapsplus/extensions/RNMarkerExtension.kt +54 -17
  16. package/android/src/main/java/com/rngooglemapsplus/extensions/RNPolygonExtension.kt +31 -1
  17. package/android/src/main/java/com/rngooglemapsplus/extensions/RNPolylineExtension.kt +6 -1
  18. package/ios/GoogleMapViewImpl.swift +81 -64
  19. package/ios/MapCircleBuilder.swift +2 -3
  20. package/ios/MapMarkerBuilder.swift +106 -50
  21. package/ios/MapPolygonBuilder.swift +6 -41
  22. package/ios/MapPolylineBuilder.swift +2 -10
  23. package/ios/RNGoogleMapsPlusView.swift +24 -11
  24. package/ios/extensions/MapObjectTag+Extension.swift +93 -0
  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/UIImage+Extension.swift +45 -0
  33. package/lib/module/types.js.map +1 -1
  34. package/lib/typescript/src/RNGoogleMapsPlusView.nitro.d.ts +12 -10
  35. package/lib/typescript/src/RNGoogleMapsPlusView.nitro.d.ts.map +1 -1
  36. package/lib/typescript/src/types.d.ts +2 -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_std__string.hpp +75 -0
  40. package/nitrogen/generated/android/c++/JFunc_void_std__string_RNLatLng.hpp +77 -0
  41. package/nitrogen/generated/android/c++/JHybridRNGoogleMapsPlusViewSpec.cpp +100 -92
  42. package/nitrogen/generated/android/c++/JHybridRNGoogleMapsPlusViewSpec.hpp +22 -20
  43. package/nitrogen/generated/android/c++/JRNInitialProps.hpp +7 -3
  44. package/nitrogen/generated/android/c++/JRNMarker.hpp +7 -7
  45. package/nitrogen/generated/android/kotlin/com/margelo/nitro/rngooglemapsplus/{Func_void_std__optional_std__string_.kt → Func_void_std__string.kt} +12 -12
  46. package/nitrogen/generated/android/kotlin/com/margelo/nitro/rngooglemapsplus/{Func_void_std__optional_std__string__RNLatLng.kt → Func_void_std__string_RNLatLng.kt} +12 -12
  47. package/nitrogen/generated/android/kotlin/com/margelo/nitro/rngooglemapsplus/HybridRNGoogleMapsPlusViewSpec.kt +38 -30
  48. package/nitrogen/generated/android/kotlin/com/margelo/nitro/rngooglemapsplus/RNInitialProps.kt +6 -3
  49. package/nitrogen/generated/android/kotlin/com/margelo/nitro/rngooglemapsplus/RNMarker.kt +6 -6
  50. package/nitrogen/generated/ios/RNGoogleMapsPlus-Swift-Cxx-Bridge.cpp +16 -8
  51. package/nitrogen/generated/ios/RNGoogleMapsPlus-Swift-Cxx-Bridge.hpp +58 -36
  52. package/nitrogen/generated/ios/c++/HybridRNGoogleMapsPlusViewSpecSwift.hpp +32 -20
  53. package/nitrogen/generated/ios/swift/Func_void_std__optional_std__string_.swift +6 -6
  54. package/nitrogen/generated/ios/swift/Func_void_std__string.swift +47 -0
  55. package/nitrogen/generated/ios/swift/Func_void_std__string_RNLatLng.swift +47 -0
  56. package/nitrogen/generated/ios/swift/HybridRNGoogleMapsPlusViewSpec.swift +12 -10
  57. package/nitrogen/generated/ios/swift/HybridRNGoogleMapsPlusViewSpec_cxx.swift +142 -180
  58. package/nitrogen/generated/ios/swift/RNInitialProps.swift +31 -1
  59. package/nitrogen/generated/ios/swift/RNMarker.swift +24 -31
  60. package/nitrogen/generated/shared/c++/HybridRNGoogleMapsPlusViewSpec.cpp +2 -0
  61. package/nitrogen/generated/shared/c++/HybridRNGoogleMapsPlusViewSpec.hpp +22 -20
  62. package/nitrogen/generated/shared/c++/RNInitialProps.hpp +6 -2
  63. package/nitrogen/generated/shared/c++/RNMarker.hpp +6 -6
  64. package/nitrogen/generated/shared/c++/views/HybridRNGoogleMapsPlusViewComponent.cpp +20 -20
  65. package/nitrogen/generated/shared/c++/views/HybridRNGoogleMapsPlusViewComponent.hpp +10 -10
  66. package/package.json +1 -1
  67. package/src/RNGoogleMapsPlusView.nitro.ts +14 -10
  68. package/src/types.ts +2 -1
  69. package/nitrogen/generated/android/c++/JFunc_void_std__optional_std__string_.hpp +0 -76
  70. package/nitrogen/generated/android/c++/JFunc_void_std__optional_std__string__RNLatLng.hpp +0 -78
  71. package/nitrogen/generated/ios/swift/Func_void_std__optional_std__string__RNLatLng.swift +0 -54
@@ -15,12 +15,13 @@ final class MapMarkerBuilder {
15
15
  let marker = GMSMarker(
16
16
  position: m.coordinate.toCLLocationCoordinate2D()
17
17
  )
18
- marker.userData = m.id
19
- marker.tracksViewChanges = true
20
18
  marker.icon = icon
21
19
  m.title.map { marker.title = $0 }
22
20
  m.snippet.map { marker.snippet = $0 }
23
- m.opacity.map { marker.iconView?.alpha = CGFloat($0) }
21
+ m.opacity.map {
22
+ marker.opacity = Float($0)
23
+ marker.iconView?.alpha = CGFloat($0)
24
+ }
24
25
  m.flat.map { marker.isFlat = $0 }
25
26
  m.draggable.map { marker.isDraggable = $0 }
26
27
  m.rotation.map { marker.rotation = $0 }
@@ -35,65 +36,33 @@ final class MapMarkerBuilder {
35
36
  }
36
37
  m.zIndex.map { marker.zIndex = Int32($0) }
37
38
 
38
- onMainAsync { [weak marker] in
39
- try? await Task.sleep(nanoseconds: 250_000_000)
40
- marker?.tracksViewChanges = false
41
- }
39
+ marker.tagData = MarkerTag(
40
+ id: m.id,
41
+ iconSvg: m.infoWindowIconSvg
42
+ )
42
43
 
43
44
  return marker
44
45
  }
45
46
 
46
47
  @MainActor
47
48
  func update(_ prev: RNMarker, _ next: RNMarker, _ m: GMSMarker) {
48
- if prev.coordinate.latitude != next.coordinate.latitude
49
- || prev.coordinate.longitude != next.coordinate.longitude {
49
+ if !prev.coordinateEquals(next) {
50
50
  m.position = next.coordinate.toCLLocationCoordinate2D()
51
51
  }
52
52
 
53
- if prev.title != next.title {
54
- m.title = next.title
55
- }
56
-
57
- if prev.snippet != next.snippet {
58
- m.snippet = next.snippet
59
- }
60
-
61
- if prev.opacity != next.opacity {
62
- let opacity = Float(next.opacity ?? 1)
63
- m.opacity = opacity
64
- m.iconView?.alpha = CGFloat(opacity)
65
- }
66
-
67
- if prev.flat != next.flat {
68
- m.isFlat = next.flat ?? false
69
- }
70
-
71
- if prev.draggable != next.draggable {
72
- m.isDraggable = next.draggable ?? false
73
- }
74
-
75
- if prev.rotation != next.rotation {
76
- m.rotation = next.rotation ?? 0
77
- }
78
-
79
- if prev.zIndex != next.zIndex {
80
- m.zIndex = Int32(next.zIndex ?? 0)
81
- }
82
-
83
53
  if !prev.markerStyleEquals(next) {
84
- buildIconAsync(next.id, next) { img in
54
+ buildIconAsync(next) { img in
85
55
  m.tracksViewChanges = true
86
56
  m.icon = img
87
57
 
88
- if prev.anchor?.x != next.anchor?.x || prev.anchor?.y != next.anchor?.y {
58
+ if !prev.anchorEquals(next) {
89
59
  m.groundAnchor = CGPoint(
90
60
  x: next.anchor?.x ?? 0.5,
91
61
  y: next.anchor?.y ?? 1
92
62
  )
93
63
  }
94
64
 
95
- if prev.infoWindowAnchor?.x != next.infoWindowAnchor?.x
96
- || prev.infoWindowAnchor?.y != next.infoWindowAnchor?.y {
65
+ if !prev.infoWindowAnchorEquals(next) {
97
66
  m.infoWindowAnchor = CGPoint(
98
67
  x: next.infoWindowAnchor?.x ?? 0.5,
99
68
  y: next.infoWindowAnchor?.y ?? 0
@@ -106,30 +75,77 @@ final class MapMarkerBuilder {
106
75
  }
107
76
  }
108
77
  } else {
109
- if prev.anchor?.x != next.anchor?.x || prev.anchor?.y != next.anchor?.y {
78
+ if !prev.anchorEquals(next) {
110
79
  m.groundAnchor = CGPoint(
111
80
  x: next.anchor?.x ?? 0.5,
112
81
  y: next.anchor?.y ?? 1
113
82
  )
114
83
  }
115
84
 
116
- if prev.infoWindowAnchor?.x != next.infoWindowAnchor?.x
117
- || prev.infoWindowAnchor?.y != next.infoWindowAnchor?.y {
85
+ if !prev.infoWindowAnchorEquals(next) {
118
86
  m.infoWindowAnchor = CGPoint(
119
87
  x: next.infoWindowAnchor?.x ?? 0.5,
120
88
  y: next.infoWindowAnchor?.y ?? 0
121
89
  )
122
90
  }
123
91
  }
92
+
93
+ var tracksInfoWindowChanges = false
94
+
95
+ if prev.title != next.title {
96
+ tracksInfoWindowChanges = true
97
+ m.title = next.title
98
+ }
99
+
100
+ if prev.snippet != next.snippet {
101
+ tracksInfoWindowChanges = true
102
+ m.snippet = next.snippet
103
+ }
104
+
105
+ if(tracksInfoWindowChanges) {
106
+ m.tracksInfoWindowChanges = true
107
+ onMainAsync { [weak m] in
108
+ try? await Task.sleep(nanoseconds: 250_000_000)
109
+ m?.tracksInfoWindowChanges = false
110
+ }
111
+ }
112
+
113
+ if prev.opacity != next.opacity {
114
+ let opacity = Float(next.opacity ?? 1)
115
+ m.opacity = opacity
116
+ m.iconView?.alpha = CGFloat(opacity)
117
+ }
118
+
119
+ if prev.flat != next.flat {
120
+ m.isFlat = next.flat ?? false
121
+ }
122
+
123
+ if prev.draggable != next.draggable {
124
+ m.isDraggable = next.draggable ?? false
125
+ }
126
+
127
+ if prev.rotation != next.rotation {
128
+ m.rotation = next.rotation ?? 0
129
+ }
130
+
131
+ if prev.zIndex != next.zIndex {
132
+ m.zIndex = Int32(next.zIndex ?? 0)
133
+ }
134
+
135
+ if !prev.markerInfoWindowStyleEquals(next) {
136
+ m.tagData = MarkerTag(
137
+ id: next.id,
138
+ iconSvg: next.infoWindowIconSvg
139
+ )
140
+ }
124
141
  }
125
142
 
126
143
  @MainActor
127
144
  func buildIconAsync(
128
- _ id: String,
129
145
  _ m: RNMarker,
130
146
  onReady: @escaping (UIImage?) -> Void
131
147
  ) {
132
- tasks[id]?.cancel()
148
+ tasks[m.id]?.cancel()
133
149
 
134
150
  if m.iconSvg == nil {
135
151
  onReady(nil)
@@ -144,7 +160,7 @@ final class MapMarkerBuilder {
144
160
 
145
161
  let task = Task(priority: .userInitiated) { [weak self] in
146
162
  guard let self else { return }
147
- defer { self.tasks.removeValue(forKey: id) }
163
+ defer { self.tasks.removeValue(forKey: m.id) }
148
164
 
149
165
  let scale = UIScreen.main.scale
150
166
  let img = await self.renderUIImage(m, scale)
@@ -158,7 +174,7 @@ final class MapMarkerBuilder {
158
174
  }
159
175
  }
160
176
 
161
- tasks[id] = task
177
+ tasks[m.id] = task
162
178
  }
163
179
 
164
180
  @MainActor
@@ -177,6 +193,46 @@ final class MapMarkerBuilder {
177
193
  iconCache.removeAllObjects()
178
194
  }
179
195
 
196
+ @MainActor
197
+ func buildInfoWindow(iconSvg: RNMarkerSvg?) -> UIImageView? {
198
+ guard let iconSvg = iconSvg else {
199
+ return nil
200
+ }
201
+
202
+ guard let data = iconSvg.svgString.data(using: .utf8),
203
+ let svgImg = SVGKImage(data: data)
204
+ else {
205
+ return nil
206
+ }
207
+
208
+ let size = CGSize(
209
+ width: max(1, CGFloat(iconSvg.width)),
210
+ height: max(1, CGFloat(iconSvg.height))
211
+ )
212
+
213
+ svgImg.size = size
214
+
215
+ guard let base = svgImg.uiImage else {
216
+ return nil
217
+ }
218
+
219
+ let fmt = UIGraphicsImageRendererFormat.default()
220
+ fmt.opaque = false
221
+ fmt.scale = UIScreen.main.scale
222
+ let renderer = UIGraphicsImageRenderer(size: size, format: fmt)
223
+
224
+ let finalImage = renderer.image { _ in
225
+ base.draw(in: CGRect(origin: .zero, size: size))
226
+ }
227
+
228
+ let imageView = UIImageView(image: finalImage)
229
+ imageView.frame = CGRect(origin: .zero, size: size)
230
+ imageView.contentMode = .scaleAspectFit
231
+ imageView.backgroundColor = .clear
232
+
233
+ return imageView
234
+ }
235
+
180
236
  @MainActor
181
237
  private func renderUIImage(_ m: RNMarker, _ scale: CGFloat) async -> UIImage? {
182
238
  guard let iconSvg = m.iconSvg,
@@ -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
  }
@@ -143,7 +146,7 @@ final class RNGoogleMapsPlusView: HybridRNGoogleMapsPlusViewSpec {
143
146
  }
144
147
  }
145
148
  } else {
146
- self.markerBuilder.buildIconAsync(next.id, next) { icon in
149
+ self.markerBuilder.buildIconAsync(next) { icon in
147
150
  let marker = self.markerBuilder.build(next, icon: icon)
148
151
  self.impl.addMarker(id: id, marker: marker)
149
152
  }
@@ -349,31 +352,31 @@ final class RNGoogleMapsPlusView: HybridRNGoogleMapsPlusViewSpec {
349
352
  didSet { impl.onPoiPress = onPoiPress }
350
353
  }
351
354
  @MainActor
352
- var onMarkerPress: ((String?) -> Void)? {
355
+ var onMarkerPress: ((String) -> Void)? {
353
356
  didSet { impl.onMarkerPress = onMarkerPress }
354
357
  }
355
358
  @MainActor
356
- var onPolylinePress: ((String?) -> Void)? {
359
+ var onPolylinePress: ((String) -> Void)? {
357
360
  didSet { impl.onPolylinePress = onPolylinePress }
358
361
  }
359
362
  @MainActor
360
- var onPolygonPress: ((String?) -> Void)? {
363
+ var onPolygonPress: ((String) -> Void)? {
361
364
  didSet { impl.onPolygonPress = onPolygonPress }
362
365
  }
363
366
  @MainActor
364
- var onCirclePress: ((String?) -> Void)? {
367
+ var onCirclePress: ((String) -> Void)? {
365
368
  didSet { impl.onCirclePress = onCirclePress }
366
369
  }
367
370
  @MainActor
368
- var onMarkerDragStart: ((String?, RNLatLng) -> Void)? {
371
+ var onMarkerDragStart: ((String, RNLatLng) -> Void)? {
369
372
  didSet { impl.onMarkerDragStart = onMarkerDragStart }
370
373
  }
371
374
  @MainActor
372
- var onMarkerDrag: ((String?, RNLatLng) -> Void)? {
375
+ var onMarkerDrag: ((String, RNLatLng) -> Void)? {
373
376
  didSet { impl.onMarkerDrag = onMarkerDrag }
374
377
  }
375
378
  @MainActor
376
- var onMarkerDragEnd: ((String?, RNLatLng) -> Void)? {
379
+ var onMarkerDragEnd: ((String, RNLatLng) -> Void)? {
377
380
  didSet { impl.onMarkerDragEnd = onMarkerDragEnd }
378
381
  }
379
382
  @MainActor
@@ -385,15 +388,15 @@ final class RNGoogleMapsPlusView: HybridRNGoogleMapsPlusViewSpec {
385
388
  didSet { impl.onIndoorLevelActivated = onIndoorLevelActivated }
386
389
  }
387
390
  @MainActor
388
- var onInfoWindowPress: ((String?) -> Void)? {
391
+ var onInfoWindowPress: ((String) -> Void)? {
389
392
  didSet { impl.onInfoWindowPress = onInfoWindowPress }
390
393
  }
391
394
  @MainActor
392
- var onInfoWindowClose: ((String?) -> Void)? {
395
+ var onInfoWindowClose: ((String) -> Void)? {
393
396
  didSet { impl.onInfoWindowClose = onInfoWindowClose }
394
397
  }
395
398
  @MainActor
396
- var onInfoWindowLongPress: ((String?) -> Void)? {
399
+ var onInfoWindowLongPress: ((String) -> Void)? {
397
400
  didSet { impl.onInfoWindowLongPress = onInfoWindowLongPress }
398
401
  }
399
402
  @MainActor
@@ -417,6 +420,16 @@ final class RNGoogleMapsPlusView: HybridRNGoogleMapsPlusViewSpec {
417
420
  didSet { impl.onCameraChangeComplete = onCameraChangeComplete }
418
421
  }
419
422
 
423
+ @MainActor
424
+ func showMarkerInfoWindow(id: String) {
425
+ impl.showMarkerInfoWindow(id: id);
426
+ }
427
+
428
+ @MainActor
429
+ func hideMarkerInfoWindow(id: String) {
430
+ impl.hideMarkerInfoWindow(id: id);
431
+ }
432
+
420
433
  @MainActor
421
434
  func setCamera(camera: RNCamera, animated: Bool?, durationMs: Double?) {
422
435
  let cam = camera.toGMSCameraPosition(current: impl.currentCamera)
@@ -0,0 +1,93 @@
1
+ import GoogleMaps
2
+ import Foundation
3
+
4
+ protocol MapObjectTag {
5
+ var id: String { get }
6
+ }
7
+
8
+ struct MarkerTag: MapObjectTag {
9
+ let id: String
10
+ let iconSvg: RNMarkerSvg?
11
+ init(id: String, iconSvg: RNMarkerSvg? = nil) {
12
+ self.id = id
13
+ self.iconSvg = iconSvg
14
+ }
15
+ }
16
+
17
+ struct PolylineTag: MapObjectTag { let id: String }
18
+ struct PolygonTag: MapObjectTag { let id: String }
19
+ struct CircleTag: MapObjectTag { let id: String }
20
+
21
+ extension GMSMarker {
22
+ var tagData: MarkerTag {
23
+ get {
24
+ if let tag = userData as? MarkerTag {
25
+ return tag
26
+ } else {
27
+ print("[MapTag] Marker without tag detected at \(position)")
28
+ let fallback = MarkerTag(id: "unknown")
29
+ userData = fallback
30
+ return fallback
31
+ }
32
+ }
33
+ set {
34
+ userData = newValue
35
+ }
36
+ }
37
+
38
+ var idTag: String { tagData.id }
39
+ }
40
+
41
+ extension GMSPolyline {
42
+ var tagData: PolylineTag {
43
+ get {
44
+ if let tag = userData as? PolylineTag {
45
+ return tag
46
+ } else {
47
+ print("[MapTag] Polyline without tag detected")
48
+ let fallback = PolylineTag(id: "unknown")
49
+ userData = fallback
50
+ return fallback
51
+ }
52
+ }
53
+ set { userData = newValue }
54
+ }
55
+
56
+ var idTag: String { tagData.id }
57
+ }
58
+
59
+ extension GMSPolygon {
60
+ var tagData: PolygonTag {
61
+ get {
62
+ if let tag = userData as? PolygonTag {
63
+ return tag
64
+ } else {
65
+ print("[MapTag] Polygon without tag detected")
66
+ let fallback = PolygonTag(id: "unknown")
67
+ userData = fallback
68
+ return fallback
69
+ }
70
+ }
71
+ set { userData = newValue }
72
+ }
73
+
74
+ var idTag: String { tagData.id }
75
+ }
76
+
77
+ extension GMSCircle {
78
+ var tagData: CircleTag {
79
+ get {
80
+ if let tag = userData as? CircleTag {
81
+ return tag
82
+ } else {
83
+ print("[MapTag] Circle without tag detected")
84
+ let fallback = CircleTag(id: "unknown")
85
+ userData = fallback
86
+ return fallback
87
+ }
88
+ }
89
+ set { userData = newValue }
90
+ }
91
+
92
+ var idTag: String { tagData.id }
93
+ }
@@ -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
+
@@ -2,21 +2,52 @@ import GoogleMaps
2
2
 
3
3
  extension RNMarker {
4
4
  func markerEquals(_ b: RNMarker) -> Bool {
5
- id == b.id && zIndex == b.zIndex
6
- && coordinate.latitude == b.coordinate.latitude
7
- && coordinate.longitude == b.coordinate.longitude
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
14
- && markerStyleEquals(b)
5
+ if id != b.id { return false }
6
+ if zIndex != b.zIndex { return false }
7
+ if !coordinateEquals(b) { return false }
8
+ if !anchorEquals(b) { return false }
9
+ if title != b.title { return false }
10
+ if snippet != b.snippet { return false }
11
+ if opacity != b.opacity { return false }
12
+ if flat != b.flat { return false }
13
+ if draggable != b.draggable { return false }
14
+ if rotation != b.rotation { return false }
15
+ if !infoWindowAnchorEquals(b) { return false }
16
+ if !markerInfoWindowStyleEquals(b) { return false }
17
+ if !markerStyleEquals(b) { return false }
18
+ return true
19
+ }
20
+
21
+ func coordinateEquals(_ b: RNMarker) -> Bool {
22
+ if coordinate.latitude != b.coordinate.latitude { return false }
23
+ if coordinate.longitude != b.coordinate.longitude { return false }
24
+ return true
25
+ }
26
+
27
+ func anchorEquals(_ b: RNMarker) -> Bool {
28
+ if anchor?.x != b.anchor?.x { return false }
29
+ if anchor?.y != b.anchor?.y { return false }
30
+ return true
31
+ }
32
+
33
+ func infoWindowAnchorEquals(_ b: RNMarker) -> Bool {
34
+ if infoWindowAnchor?.x != b.infoWindowAnchor?.x { return false }
35
+ if infoWindowAnchor?.y != b.infoWindowAnchor?.y { return false }
36
+ return true
37
+ }
38
+
39
+ func markerInfoWindowStyleEquals(_ b: RNMarker) -> Bool {
40
+ if infoWindowIconSvg?.width != b.infoWindowIconSvg?.width { return false }
41
+ if infoWindowIconSvg?.height != b.infoWindowIconSvg?.height { return false }
42
+ if infoWindowIconSvg?.svgString != b.infoWindowIconSvg?.svgString { return false }
43
+ return true
15
44
  }
16
45
 
17
46
  func markerStyleEquals(_ b: RNMarker) -> Bool {
18
- iconSvg?.width == b.iconSvg?.width && iconSvg?.height == b.iconSvg?.height
19
- && iconSvg?.svgString == b.iconSvg?.svgString
47
+ if iconSvg?.width != b.iconSvg?.width { return false }
48
+ if iconSvg?.height != b.iconSvg?.height { return false }
49
+ if iconSvg?.svgString != b.iconSvg?.svgString { return false }
50
+ return true
20
51
  }
21
52
 
22
53
  func styleHash() -> NSNumber {