react-native-google-maps-plus 1.4.1 → 1.5.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 (53) 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/extensions/CameraPositionExtension.kt +12 -0
  4. package/android/src/main/java/com/rngooglemapsplus/extensions/IntExtension.kt +28 -0
  5. package/android/src/main/java/com/rngooglemapsplus/extensions/LatLngBounds.kt +15 -0
  6. package/android/src/main/java/com/rngooglemapsplus/extensions/LocationExtension.kt +59 -0
  7. package/ios/GoogleMapViewImpl.swift +28 -138
  8. package/ios/LocationHandler.swift +5 -13
  9. package/ios/MapHelper.swift +20 -0
  10. package/ios/MapMarkerBuilder.swift +44 -69
  11. package/ios/RNGoogleMapsPlusView.swift +12 -8
  12. package/ios/extensions/CLError+Extension.swift +14 -0
  13. package/ios/extensions/CLLocation+Extension.swift +27 -0
  14. package/ios/extensions/GMSCameraPosition+Extension.swift +12 -0
  15. package/ios/extensions/GMSCoordinateBounds+Extension.swift +19 -0
  16. package/ios/extensions/RNMarker+Extension.swift +2 -3
  17. package/lib/module/GoogleMapsPlus.js +7 -0
  18. package/lib/module/GoogleMapsPlus.js.map +1 -0
  19. package/lib/module/index.js +3 -5
  20. package/lib/module/index.js.map +1 -1
  21. package/lib/module/types.js.map +1 -1
  22. package/lib/nitrogen/generated/shared/json/RNGoogleMapsPlusViewConfig.json +44 -0
  23. package/lib/typescript/src/GoogleMapsPlus.d.ts +5 -0
  24. package/lib/typescript/src/GoogleMapsPlus.d.ts.map +1 -0
  25. package/lib/typescript/src/index.d.ts +3 -3
  26. package/lib/typescript/src/index.d.ts.map +1 -1
  27. package/lib/typescript/src/types.d.ts +25 -0
  28. package/lib/typescript/src/types.d.ts.map +1 -1
  29. package/nitrogen/generated/android/c++/JFunc_void_RNLocation.hpp +6 -0
  30. package/nitrogen/generated/android/c++/JHybridRNGoogleMapsPlusViewSpec.cpp +8 -0
  31. package/nitrogen/generated/android/c++/JRNLocation.hpp +32 -2
  32. package/nitrogen/generated/android/c++/JRNLocationAndroid.hpp +82 -0
  33. package/nitrogen/generated/android/c++/JRNLocationIOS.hpp +77 -0
  34. package/nitrogen/generated/android/kotlin/com/margelo/nitro/rngooglemapsplus/RNLocation.kt +19 -1
  35. package/nitrogen/generated/android/kotlin/com/margelo/nitro/rngooglemapsplus/RNLocationAndroid.kt +50 -0
  36. package/nitrogen/generated/android/kotlin/com/margelo/nitro/rngooglemapsplus/RNLocationIOS.kt +47 -0
  37. package/nitrogen/generated/android/kotlin/com/margelo/nitro/rngooglemapsplus/views/HybridRNGoogleMapsPlusViewManager.kt +7 -2
  38. package/nitrogen/generated/ios/RNGoogleMapsPlus-Swift-Cxx-Bridge.hpp +36 -0
  39. package/nitrogen/generated/ios/RNGoogleMapsPlus-Swift-Cxx-Umbrella.hpp +6 -0
  40. package/nitrogen/generated/ios/c++/HybridRNGoogleMapsPlusViewSpecSwift.hpp +6 -0
  41. package/nitrogen/generated/ios/c++/views/HybridRNGoogleMapsPlusViewComponent.mm +8 -0
  42. package/nitrogen/generated/ios/swift/RNLocation.swift +92 -2
  43. package/nitrogen/generated/ios/swift/RNLocationAndroid.swift +215 -0
  44. package/nitrogen/generated/ios/swift/RNLocationIOS.swift +185 -0
  45. package/nitrogen/generated/shared/c++/RNLocation.hpp +33 -2
  46. package/nitrogen/generated/shared/c++/RNLocationAndroid.hpp +104 -0
  47. package/nitrogen/generated/shared/c++/RNLocationIOS.hpp +99 -0
  48. package/package.json +6 -13
  49. package/src/GoogleMapsPlus.tsx +20 -0
  50. package/src/index.tsx +6 -14
  51. package/src/types.ts +27 -0
  52. package/lib/module/package.json +0 -1
  53. package/lib/typescript/package.json +0 -1
@@ -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
  }
@@ -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
+ }
@@ -3,13 +3,12 @@ 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(
@@ -35,7 +34,8 @@ final class MapMarkerBuilder {
35
34
  }
36
35
  m.zIndex.map { marker.zIndex = Int32($0) }
37
36
 
38
- DispatchQueue.main.asyncAfter(deadline: .now() + 0.25) { [weak marker] in
37
+ onMainAsync { [weak marker] in
38
+ try? await Task.sleep(nanoseconds: 250_000_000)
39
39
  marker?.tracksViewChanges = false
40
40
  }
41
41
 
@@ -84,7 +84,7 @@ final class MapMarkerBuilder {
84
84
  m.tracksViewChanges = true
85
85
  m.icon = img
86
86
 
87
- if prev.anchor?.x != next.anchor?.x || prev.anchor?.y != next.anchor?.y{
87
+ if prev.anchor?.x != next.anchor?.x || prev.anchor?.y != next.anchor?.y {
88
88
  m.groundAnchor = CGPoint(
89
89
  x: next.anchor?.x ?? 0.5,
90
90
  y: next.anchor?.y ?? 1
@@ -99,12 +99,13 @@ final class MapMarkerBuilder {
99
99
  )
100
100
  }
101
101
 
102
- DispatchQueue.main.asyncAfter(deadline: .now() + 0.25) { [weak m] in
102
+ onMainAsync { [weak m] in
103
+ try? await Task.sleep(nanoseconds: 250_000_000)
103
104
  m?.tracksViewChanges = false
104
105
  }
105
106
  }
106
107
  } else {
107
- if prev.anchor?.x != next.anchor?.x || prev.anchor?.y != next.anchor?.y{
108
+ if prev.anchor?.x != next.anchor?.x || prev.anchor?.y != next.anchor?.y {
108
109
  m.groundAnchor = CGPoint(
109
110
  x: next.anchor?.x ?? 0.5,
110
111
  y: next.anchor?.y ?? 1
@@ -144,7 +145,8 @@ final class MapMarkerBuilder {
144
145
  guard let self else { return }
145
146
  defer { self.tasks.removeValue(forKey: id) }
146
147
 
147
- let img = await self.renderUIImage(m)
148
+ let scale = UIScreen.main.scale
149
+ let img = await self.renderUIImage(m, scale)
148
150
  guard let img, !Task.isCancelled else { return }
149
151
 
150
152
  self.iconCache.setObject(img, forKey: key)
@@ -172,65 +174,38 @@ final class MapMarkerBuilder {
172
174
  iconCache.removeAllObjects()
173
175
  }
174
176
 
175
- private func renderUIImage(_ m: RNMarker) async -> UIImage? {
176
- guard let iconSvg = m.iconSvg else {
177
- return nil
178
- }
179
-
180
- return await withTaskCancellationHandler(
181
- operation: {
182
- await withCheckedContinuation {
183
- (cont: CheckedContinuation<UIImage?, Never>) in
184
- queue.async {
185
- if Task.isCancelled {
186
- cont.resume(returning: nil)
187
- return
188
- }
189
-
190
- let targetW = max(1, Int(CGFloat(iconSvg.width)))
191
- let targetH = max(1, Int(CGFloat(iconSvg.height)))
192
- let size = CGSize(width: targetW, height: targetH)
193
-
194
- guard
195
- let data = iconSvg.svgString.data(using: .utf8),
196
- let svgImg = SVGKImage(data: data)
197
- else {
198
- cont.resume(returning: nil)
199
- return
200
- }
201
-
202
- svgImg.size = size
203
-
204
- if Task.isCancelled {
205
- cont.resume(returning: nil)
206
- return
207
- }
208
-
209
- guard let base = svgImg.uiImage else {
210
- cont.resume(returning: nil)
211
- return
212
- }
213
-
214
- let scale = UIScreen.main.scale
215
- let img: UIImage
216
- if let cg = base.cgImage {
217
- img = UIImage(cgImage: cg, scale: scale, orientation: .up)
218
- } else {
219
- let fmt = UIGraphicsImageRendererFormat.default()
220
- fmt.opaque = false
221
- fmt.scale = scale
222
- let renderer = UIGraphicsImageRenderer(size: size, format: fmt)
223
- img = renderer.image { _ in
224
- base.draw(in: CGRect(origin: .zero, size: size))
225
- }
226
- }
227
-
228
- cont.resume(returning: img)
229
- }
230
- }
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 }
231
181
 
232
- },
233
- onCancel: {}
182
+ let size = CGSize(
183
+ width: max(1, CGFloat(iconSvg.width)),
184
+ height: max(1, CGFloat(iconSvg.height))
234
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
235
209
  }
210
+
236
211
  }
@@ -30,21 +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
- 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
- }
43
- impl.initMapView(googleMapOptions: options)
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)
44
42
  }
43
+ impl.initMapView(googleMapOptions: options)
45
44
  }
46
45
  }
47
46
 
47
+ @MainActor
48
+ func dispose() {
49
+ impl.deinitInternal()
50
+ }
51
+
48
52
  @MainActor
49
53
  var initialProps: RNInitialProps? {
50
54
  didSet {
@@ -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,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
+ }
@@ -17,14 +17,13 @@ extension RNMarker {
17
17
  func markerStyleEquals(_ b: RNMarker) -> Bool {
18
18
  iconSvg?.width == b.iconSvg?.width && iconSvg?.height == b.iconSvg?.height
19
19
  && iconSvg?.svgString == b.iconSvg?.svgString
20
-
21
20
  }
22
21
 
23
- func styleHash() -> NSString {
22
+ func styleHash() -> NSNumber {
24
23
  var hasher = Hasher()
25
24
  hasher.combine(iconSvg?.width)
26
25
  hasher.combine(iconSvg?.height)
27
26
  hasher.combine(iconSvg?.svgString)
28
- return String(hasher.finalize()) as NSString
27
+ return NSNumber(value: hasher.finalize())
29
28
  }
30
29
  }
@@ -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;;AA4JA,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":[]}