react-native-google-maps-plus 0.1.0 → 1.0.0-dev.2

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 (197) hide show
  1. package/LICENSE +20 -0
  2. package/README.md +156 -0
  3. package/RNGoogleMapsPlus.podspec +34 -0
  4. package/android/CMakeLists.txt +32 -0
  5. package/android/build.gradle +135 -0
  6. package/android/fix-prefab.gradle +51 -0
  7. package/android/gradle.properties +8 -0
  8. package/android/src/main/AndroidManifest.xml +2 -0
  9. package/android/src/main/cpp/cpp-adapter.cpp +6 -0
  10. package/android/src/main/java/com/rngooglemapsplus/Color.kt +65 -0
  11. package/android/src/main/java/com/rngooglemapsplus/GoogleMapsViewImpl.kt +847 -0
  12. package/android/src/main/java/com/rngooglemapsplus/LocationHandler.kt +205 -0
  13. package/android/src/main/java/com/rngooglemapsplus/MapCircle.kt +29 -0
  14. package/android/src/main/java/com/rngooglemapsplus/MapMarker.kt +146 -0
  15. package/android/src/main/java/com/rngooglemapsplus/MapPolygon.kt +38 -0
  16. package/android/src/main/java/com/rngooglemapsplus/MapPolyline.kt +61 -0
  17. package/android/src/main/java/com/rngooglemapsplus/PermissionHandler.kt +116 -0
  18. package/android/src/main/java/com/rngooglemapsplus/PlayServicesHandler.kt +25 -0
  19. package/android/src/main/java/com/rngooglemapsplus/RNGoogleMapsPlusModule.kt +22 -0
  20. package/android/src/main/java/com/rngooglemapsplus/RNGoogleMapsPlusPackage.kt +35 -0
  21. package/android/src/main/java/com/rngooglemapsplus/RNGoogleMapsPlusView.kt +364 -0
  22. package/ios/Color.swift +109 -0
  23. package/ios/GoogleMapViewImpl.swift +645 -0
  24. package/ios/LocationHandler.swift +205 -0
  25. package/ios/MapCircle.swift +43 -0
  26. package/ios/MapHelper.swift +18 -0
  27. package/ios/MapMarker.swift +200 -0
  28. package/ios/MapPolygon.swift +58 -0
  29. package/ios/MapPolyline.swift +85 -0
  30. package/ios/PermissionHandler.swift +73 -0
  31. package/ios/RNGoogleMapsPlusModule.swift +27 -0
  32. package/ios/RNGoogleMapsPlusView.swift +391 -0
  33. package/lib/module/RNGoogleMapsPlusModule.nitro.js +4 -0
  34. package/lib/module/RNGoogleMapsPlusModule.nitro.js.map +1 -0
  35. package/lib/module/RNGoogleMapsPlusView.nitro.js +4 -0
  36. package/lib/module/RNGoogleMapsPlusView.nitro.js.map +1 -0
  37. package/lib/module/index.js +8 -0
  38. package/lib/module/index.js.map +1 -0
  39. package/lib/module/package.json +1 -0
  40. package/lib/module/types.js +78 -0
  41. package/lib/module/types.js.map +1 -0
  42. package/lib/typescript/package.json +1 -0
  43. package/lib/typescript/src/RNGoogleMapsPlusModule.nitro.d.ts +12 -0
  44. package/lib/typescript/src/RNGoogleMapsPlusModule.nitro.d.ts.map +1 -0
  45. package/lib/typescript/src/RNGoogleMapsPlusView.nitro.d.ts +39 -0
  46. package/lib/typescript/src/RNGoogleMapsPlusView.nitro.d.ts.map +1 -0
  47. package/lib/typescript/src/index.d.ts +7 -0
  48. package/lib/typescript/src/index.d.ts.map +1 -0
  49. package/lib/typescript/src/types.d.ts +131 -0
  50. package/lib/typescript/src/types.d.ts.map +1 -0
  51. package/nitro.json +28 -0
  52. package/nitrogen/generated/.gitattributes +1 -0
  53. package/nitrogen/generated/android/RNGoogleMapsPlus+autolinking.cmake +85 -0
  54. package/nitrogen/generated/android/RNGoogleMapsPlus+autolinking.gradle +27 -0
  55. package/nitrogen/generated/android/RNGoogleMapsPlusOnLoad.cpp +70 -0
  56. package/nitrogen/generated/android/RNGoogleMapsPlusOnLoad.hpp +25 -0
  57. package/nitrogen/generated/android/c++/JFunc_void_RNLatLng.hpp +76 -0
  58. package/nitrogen/generated/android/c++/JFunc_void_RNLocation.hpp +78 -0
  59. package/nitrogen/generated/android/c++/JFunc_void_RNLocationErrorCode.hpp +76 -0
  60. package/nitrogen/generated/android/c++/JFunc_void_RNMapErrorCode.hpp +76 -0
  61. package/nitrogen/generated/android/c++/JFunc_void_RNRegion_RNCamera_bool.hpp +81 -0
  62. package/nitrogen/generated/android/c++/JFunc_void_bool.hpp +74 -0
  63. package/nitrogen/generated/android/c++/JFunc_void_std__string.hpp +75 -0
  64. package/nitrogen/generated/android/c++/JHybridRNGoogleMapsPlusModuleSpec.cpp +83 -0
  65. package/nitrogen/generated/android/c++/JHybridRNGoogleMapsPlusModuleSpec.hpp +67 -0
  66. package/nitrogen/generated/android/c++/JHybridRNGoogleMapsPlusViewSpec.cpp +589 -0
  67. package/nitrogen/generated/android/c++/JHybridRNGoogleMapsPlusViewSpec.hpp +118 -0
  68. package/nitrogen/generated/android/c++/JRNAndroidLocationPermissionResult.hpp +62 -0
  69. package/nitrogen/generated/android/c++/JRNCamera.hpp +67 -0
  70. package/nitrogen/generated/android/c++/JRNCircle.hpp +84 -0
  71. package/nitrogen/generated/android/c++/JRNIOSPermissionResult.hpp +59 -0
  72. package/nitrogen/generated/android/c++/JRNInitialProps.hpp +66 -0
  73. package/nitrogen/generated/android/c++/JRNLatLng.hpp +57 -0
  74. package/nitrogen/generated/android/c++/JRNLineCapType.hpp +62 -0
  75. package/nitrogen/generated/android/c++/JRNLineJoinType.hpp +62 -0
  76. package/nitrogen/generated/android/c++/JRNLocation.hpp +58 -0
  77. package/nitrogen/generated/android/c++/JRNLocationErrorCode.hpp +71 -0
  78. package/nitrogen/generated/android/c++/JRNLocationPermissionResult.hpp +61 -0
  79. package/nitrogen/generated/android/c++/JRNMapErrorCode.hpp +74 -0
  80. package/nitrogen/generated/android/c++/JRNMapPadding.hpp +65 -0
  81. package/nitrogen/generated/android/c++/JRNMapType.hpp +68 -0
  82. package/nitrogen/generated/android/c++/JRNMarker.hpp +82 -0
  83. package/nitrogen/generated/android/c++/JRNPolygon.hpp +98 -0
  84. package/nitrogen/generated/android/c++/JRNPolyline.hpp +106 -0
  85. package/nitrogen/generated/android/c++/JRNPosition.hpp +57 -0
  86. package/nitrogen/generated/android/c++/JRNRegion.hpp +62 -0
  87. package/nitrogen/generated/android/c++/JRNUserInterfaceStyle.hpp +62 -0
  88. package/nitrogen/generated/android/c++/views/JHybridRNGoogleMapsPlusViewStateUpdater.cpp +152 -0
  89. package/nitrogen/generated/android/c++/views/JHybridRNGoogleMapsPlusViewStateUpdater.hpp +49 -0
  90. package/nitrogen/generated/android/kotlin/com/margelo/nitro/rngooglemapsplus/Func_void_RNLatLng.kt +81 -0
  91. package/nitrogen/generated/android/kotlin/com/margelo/nitro/rngooglemapsplus/Func_void_RNLocation.kt +81 -0
  92. package/nitrogen/generated/android/kotlin/com/margelo/nitro/rngooglemapsplus/Func_void_RNLocationErrorCode.kt +81 -0
  93. package/nitrogen/generated/android/kotlin/com/margelo/nitro/rngooglemapsplus/Func_void_RNMapErrorCode.kt +81 -0
  94. package/nitrogen/generated/android/kotlin/com/margelo/nitro/rngooglemapsplus/Func_void_RNRegion_RNCamera_bool.kt +81 -0
  95. package/nitrogen/generated/android/kotlin/com/margelo/nitro/rngooglemapsplus/Func_void_bool.kt +81 -0
  96. package/nitrogen/generated/android/kotlin/com/margelo/nitro/rngooglemapsplus/Func_void_std__string.kt +81 -0
  97. package/nitrogen/generated/android/kotlin/com/margelo/nitro/rngooglemapsplus/HybridRNGoogleMapsPlusModuleSpec.kt +64 -0
  98. package/nitrogen/generated/android/kotlin/com/margelo/nitro/rngooglemapsplus/HybridRNGoogleMapsPlusViewSpec.kt +317 -0
  99. package/nitrogen/generated/android/kotlin/com/margelo/nitro/rngooglemapsplus/RNAndroidLocationPermissionResult.kt +22 -0
  100. package/nitrogen/generated/android/kotlin/com/margelo/nitro/rngooglemapsplus/RNCamera.kt +38 -0
  101. package/nitrogen/generated/android/kotlin/com/margelo/nitro/rngooglemapsplus/RNCircle.kt +50 -0
  102. package/nitrogen/generated/android/kotlin/com/margelo/nitro/rngooglemapsplus/RNGoogleMapsPlusOnLoad.kt +35 -0
  103. package/nitrogen/generated/android/kotlin/com/margelo/nitro/rngooglemapsplus/RNIOSPermissionResult.kt +21 -0
  104. package/nitrogen/generated/android/kotlin/com/margelo/nitro/rngooglemapsplus/RNInitialProps.kt +35 -0
  105. package/nitrogen/generated/android/kotlin/com/margelo/nitro/rngooglemapsplus/RNLatLng.kt +32 -0
  106. package/nitrogen/generated/android/kotlin/com/margelo/nitro/rngooglemapsplus/RNLineCapType.kt +22 -0
  107. package/nitrogen/generated/android/kotlin/com/margelo/nitro/rngooglemapsplus/RNLineJoinType.kt +22 -0
  108. package/nitrogen/generated/android/kotlin/com/margelo/nitro/rngooglemapsplus/RNLocation.kt +32 -0
  109. package/nitrogen/generated/android/kotlin/com/margelo/nitro/rngooglemapsplus/RNLocationErrorCode.kt +25 -0
  110. package/nitrogen/generated/android/kotlin/com/margelo/nitro/rngooglemapsplus/RNLocationPermissionResult.kt +32 -0
  111. package/nitrogen/generated/android/kotlin/com/margelo/nitro/rngooglemapsplus/RNMapErrorCode.kt +26 -0
  112. package/nitrogen/generated/android/kotlin/com/margelo/nitro/rngooglemapsplus/RNMapPadding.kt +38 -0
  113. package/nitrogen/generated/android/kotlin/com/margelo/nitro/rngooglemapsplus/RNMapType.kt +24 -0
  114. package/nitrogen/generated/android/kotlin/com/margelo/nitro/rngooglemapsplus/RNMarker.kt +47 -0
  115. package/nitrogen/generated/android/kotlin/com/margelo/nitro/rngooglemapsplus/RNPolygon.kt +47 -0
  116. package/nitrogen/generated/android/kotlin/com/margelo/nitro/rngooglemapsplus/RNPolyline.kt +50 -0
  117. package/nitrogen/generated/android/kotlin/com/margelo/nitro/rngooglemapsplus/RNPosition.kt +32 -0
  118. package/nitrogen/generated/android/kotlin/com/margelo/nitro/rngooglemapsplus/RNRegion.kt +35 -0
  119. package/nitrogen/generated/android/kotlin/com/margelo/nitro/rngooglemapsplus/RNUserInterfaceStyle.kt +22 -0
  120. package/nitrogen/generated/android/kotlin/com/margelo/nitro/rngooglemapsplus/views/HybridRNGoogleMapsPlusViewManager.kt +56 -0
  121. package/nitrogen/generated/android/kotlin/com/margelo/nitro/rngooglemapsplus/views/HybridRNGoogleMapsPlusViewStateUpdater.kt +23 -0
  122. package/nitrogen/generated/ios/RNGoogleMapsPlus+autolinking.rb +60 -0
  123. package/nitrogen/generated/ios/RNGoogleMapsPlus-Swift-Cxx-Bridge.cpp +121 -0
  124. package/nitrogen/generated/ios/RNGoogleMapsPlus-Swift-Cxx-Bridge.hpp +792 -0
  125. package/nitrogen/generated/ios/RNGoogleMapsPlus-Swift-Cxx-Umbrella.hpp +113 -0
  126. package/nitrogen/generated/ios/RNGoogleMapsPlusAutolinking.mm +41 -0
  127. package/nitrogen/generated/ios/RNGoogleMapsPlusAutolinking.swift +40 -0
  128. package/nitrogen/generated/ios/c++/HybridRNGoogleMapsPlusModuleSpecSwift.cpp +11 -0
  129. package/nitrogen/generated/ios/c++/HybridRNGoogleMapsPlusModuleSpecSwift.hpp +102 -0
  130. package/nitrogen/generated/ios/c++/HybridRNGoogleMapsPlusViewSpecSwift.cpp +11 -0
  131. package/nitrogen/generated/ios/c++/HybridRNGoogleMapsPlusViewSpecSwift.hpp +342 -0
  132. package/nitrogen/generated/ios/c++/views/HybridRNGoogleMapsPlusViewComponent.mm +216 -0
  133. package/nitrogen/generated/ios/swift/Func_void_RNLatLng.swift +47 -0
  134. package/nitrogen/generated/ios/swift/Func_void_RNLocation.swift +47 -0
  135. package/nitrogen/generated/ios/swift/Func_void_RNLocationErrorCode.swift +47 -0
  136. package/nitrogen/generated/ios/swift/Func_void_RNLocationPermissionResult.swift +47 -0
  137. package/nitrogen/generated/ios/swift/Func_void_RNMapErrorCode.swift +47 -0
  138. package/nitrogen/generated/ios/swift/Func_void_RNRegion_RNCamera_bool.swift +47 -0
  139. package/nitrogen/generated/ios/swift/Func_void_bool.swift +47 -0
  140. package/nitrogen/generated/ios/swift/Func_void_std__exception_ptr.swift +47 -0
  141. package/nitrogen/generated/ios/swift/Func_void_std__string.swift +47 -0
  142. package/nitrogen/generated/ios/swift/HybridRNGoogleMapsPlusModuleSpec.swift +52 -0
  143. package/nitrogen/generated/ios/swift/HybridRNGoogleMapsPlusModuleSpec_cxx.swift +164 -0
  144. package/nitrogen/generated/ios/swift/HybridRNGoogleMapsPlusViewSpec.swift +78 -0
  145. package/nitrogen/generated/ios/swift/HybridRNGoogleMapsPlusViewSpec_cxx.swift +881 -0
  146. package/nitrogen/generated/ios/swift/RNAndroidLocationPermissionResult.swift +44 -0
  147. package/nitrogen/generated/ios/swift/RNCamera.swift +123 -0
  148. package/nitrogen/generated/ios/swift/RNCircle.swift +198 -0
  149. package/nitrogen/generated/ios/swift/RNIOSPermissionResult.swift +40 -0
  150. package/nitrogen/generated/ios/swift/RNInitialProps.swift +107 -0
  151. package/nitrogen/generated/ios/swift/RNLatLng.swift +46 -0
  152. package/nitrogen/generated/ios/swift/RNLineCapType.swift +44 -0
  153. package/nitrogen/generated/ios/swift/RNLineJoinType.swift +44 -0
  154. package/nitrogen/generated/ios/swift/RNLocation.swift +46 -0
  155. package/nitrogen/generated/ios/swift/RNLocationErrorCode.swift +56 -0
  156. package/nitrogen/generated/ios/swift/RNLocationPermissionResult.swift +70 -0
  157. package/nitrogen/generated/ios/swift/RNMapErrorCode.swift +60 -0
  158. package/nitrogen/generated/ios/swift/RNMapPadding.swift +68 -0
  159. package/nitrogen/generated/ios/swift/RNMapType.swift +52 -0
  160. package/nitrogen/generated/ios/swift/RNMarker.swift +132 -0
  161. package/nitrogen/generated/ios/swift/RNPolygon.swift +187 -0
  162. package/nitrogen/generated/ios/swift/RNPolyline.swift +203 -0
  163. package/nitrogen/generated/ios/swift/RNPosition.swift +46 -0
  164. package/nitrogen/generated/ios/swift/RNRegion.swift +57 -0
  165. package/nitrogen/generated/ios/swift/RNUserInterfaceStyle.swift +44 -0
  166. package/nitrogen/generated/shared/c++/HybridRNGoogleMapsPlusModuleSpec.cpp +24 -0
  167. package/nitrogen/generated/shared/c++/HybridRNGoogleMapsPlusModuleSpec.hpp +67 -0
  168. package/nitrogen/generated/shared/c++/HybridRNGoogleMapsPlusViewSpec.cpp +76 -0
  169. package/nitrogen/generated/shared/c++/HybridRNGoogleMapsPlusViewSpec.hpp +164 -0
  170. package/nitrogen/generated/shared/c++/RNAndroidLocationPermissionResult.hpp +67 -0
  171. package/nitrogen/generated/shared/c++/RNCamera.hpp +81 -0
  172. package/nitrogen/generated/shared/c++/RNCircle.hpp +98 -0
  173. package/nitrogen/generated/shared/c++/RNIOSPermissionResult.hpp +65 -0
  174. package/nitrogen/generated/shared/c++/RNInitialProps.hpp +78 -0
  175. package/nitrogen/generated/shared/c++/RNLatLng.hpp +71 -0
  176. package/nitrogen/generated/shared/c++/RNLineCapType.hpp +80 -0
  177. package/nitrogen/generated/shared/c++/RNLineJoinType.hpp +80 -0
  178. package/nitrogen/generated/shared/c++/RNLocation.hpp +72 -0
  179. package/nitrogen/generated/shared/c++/RNLocationErrorCode.hpp +73 -0
  180. package/nitrogen/generated/shared/c++/RNLocationPermissionResult.hpp +76 -0
  181. package/nitrogen/generated/shared/c++/RNMapErrorCode.hpp +67 -0
  182. package/nitrogen/generated/shared/c++/RNMapPadding.hpp +79 -0
  183. package/nitrogen/generated/shared/c++/RNMapType.hpp +88 -0
  184. package/nitrogen/generated/shared/c++/RNMarker.hpp +97 -0
  185. package/nitrogen/generated/shared/c++/RNPolygon.hpp +95 -0
  186. package/nitrogen/generated/shared/c++/RNPolyline.hpp +105 -0
  187. package/nitrogen/generated/shared/c++/RNPosition.hpp +71 -0
  188. package/nitrogen/generated/shared/c++/RNRegion.hpp +76 -0
  189. package/nitrogen/generated/shared/c++/RNUserInterfaceStyle.hpp +80 -0
  190. package/nitrogen/generated/shared/c++/views/HybridRNGoogleMapsPlusViewComponent.cpp +375 -0
  191. package/nitrogen/generated/shared/c++/views/HybridRNGoogleMapsPlusViewComponent.hpp +147 -0
  192. package/nitrogen/generated/shared/json/RNGoogleMapsPlusViewConfig.json +34 -0
  193. package/package.json +24 -8
  194. package/src/RNGoogleMapsPlusModule.nitro.ts +13 -0
  195. package/src/RNGoogleMapsPlusView.nitro.ts +86 -0
  196. package/src/index.tsx +24 -0
  197. package/src/types.ts +195 -0
@@ -0,0 +1,205 @@
1
+ import CoreLocation
2
+ import Foundation
3
+ import UIKit
4
+
5
+ final class LocationHandler: NSObject, CLLocationManagerDelegate {
6
+
7
+ private let manager = CLLocationManager()
8
+ private var priority: Int = Priority.highAccuracy.rawValue
9
+ private var interval: TimeInterval = 5.0
10
+ private var minUpdateInterval: TimeInterval = 5.0
11
+ private var distanceFilterMeters: CLLocationDistance = kCLDistanceFilterNone
12
+
13
+ var onUpdate: ((CLLocation) -> Void)?
14
+ var onError: ((_ error: RNLocationErrorCode) -> Void)?
15
+
16
+ private var lastEmit: Date?
17
+
18
+ override init() {
19
+ super.init()
20
+ manager.delegate = self
21
+ manager.pausesLocationUpdatesAutomatically = true
22
+ manager.activityType = .other
23
+ applyPriority()
24
+ }
25
+
26
+ func setPriority(_ priority: Int) {
27
+ self.priority = priority
28
+ applyPriority()
29
+ }
30
+
31
+ func setInterval(_ seconds: Int) {
32
+ self.interval = max(0, TimeInterval(seconds))
33
+ }
34
+
35
+ func setFastestInterval(_ seconds: Int) {
36
+ self.minUpdateInterval = max(0, TimeInterval(seconds))
37
+ }
38
+
39
+ func setDistanceFilter(_ meters: Double) {
40
+ self.distanceFilterMeters = meters >= 0 ? meters : kCLDistanceFilterNone
41
+ manager.distanceFilter = distanceFilterMeters
42
+ }
43
+
44
+ func showLocationDialog() {
45
+ DispatchQueue.main.async {
46
+ guard let vc = Self.topMostViewController() else { return }
47
+ let title =
48
+ Bundle.main.object(forInfoDictionaryKey: "LocationNotAvailableTitle")
49
+ as? String
50
+ let message =
51
+ Bundle.main.object(forInfoDictionaryKey: "LocationNotAvailableMessage")
52
+ as? String
53
+ let cancelButton =
54
+ Bundle.main.object(forInfoDictionaryKey: "CancelButton") as? String
55
+ let openLocationSettingsButton =
56
+ Bundle.main.object(forInfoDictionaryKey: "OpenLocationAlertButton")
57
+ as? String
58
+
59
+ let alert = UIAlertController(
60
+ title: title ?? "Location not available",
61
+ message: message ?? "Please check your location settings.",
62
+ preferredStyle: .alert
63
+ )
64
+ alert.addAction(
65
+ UIAlertAction(title: cancelButton ?? "Cancel", style: .cancel)
66
+ )
67
+ alert.addAction(
68
+ UIAlertAction(
69
+ title: openLocationSettingsButton ?? "Open settings",
70
+ style: .default
71
+ ) { _ in
72
+ self.openLocationSettings()
73
+ }
74
+ )
75
+ vc.present(alert, animated: true, completion: nil)
76
+ }
77
+ }
78
+
79
+ func start() {
80
+ stop()
81
+ startUpdates()
82
+ }
83
+
84
+ func stop() {
85
+ manager.stopUpdatingLocation()
86
+ }
87
+
88
+ func openLocationSettings() {
89
+ DispatchQueue.main.async {
90
+ let openSettings = {
91
+ if #available(iOS 18.3, *) {
92
+ guard
93
+ let url = URL(
94
+ string: UIApplication.openDefaultApplicationsSettingsURLString
95
+ )
96
+ else {
97
+ return
98
+ }
99
+ UIApplication.shared.open(url, options: [:], completionHandler: nil)
100
+ } else {
101
+ guard let url = URL(string: UIApplication.openSettingsURLString)
102
+ else {
103
+ return
104
+ }
105
+ UIApplication.shared.open(url, options: [:], completionHandler: nil)
106
+ }
107
+ }
108
+
109
+ openSettings()
110
+ }
111
+ }
112
+
113
+ private func applyPriority() {
114
+ guard let p = Priority(rawValue: priority) else {
115
+ manager.desiredAccuracy = kCLLocationAccuracyBest
116
+ return
117
+ }
118
+ switch p {
119
+ case .highAccuracy:
120
+ manager.desiredAccuracy = kCLLocationAccuracyBest
121
+ case .balanced:
122
+ manager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters
123
+ case .lowPower:
124
+ manager.desiredAccuracy = kCLLocationAccuracyHundredMeters
125
+ case .passive:
126
+ manager.desiredAccuracy = kCLLocationAccuracyKilometer
127
+ }
128
+ }
129
+
130
+ private func startUpdates() {
131
+ manager.distanceFilter = distanceFilterMeters
132
+ manager.startUpdatingLocation()
133
+ }
134
+
135
+ private func shouldEmit(now: Date) -> Bool {
136
+ if let last = lastEmit {
137
+ let delta = now.timeIntervalSince(last)
138
+ if delta < minUpdateInterval { return false }
139
+ }
140
+ return true
141
+ }
142
+
143
+ func locationManager(
144
+ _ manager: CLLocationManager,
145
+ didFailWithError error: Error
146
+ ) {
147
+ let code: RNLocationErrorCode
148
+
149
+ if let clError = error as? CLError {
150
+ switch clError.code {
151
+ case .denied:
152
+ code = RNLocationErrorCode.permissionDenied
153
+ case .locationUnknown, .network:
154
+ code = RNLocationErrorCode.positionUnavailable
155
+ default:
156
+ code = RNLocationErrorCode.internalError
157
+ }
158
+ } else {
159
+ code = RNLocationErrorCode.internalError
160
+ }
161
+ onError?(code)
162
+ }
163
+
164
+ func locationManager(
165
+ _ manager: CLLocationManager,
166
+ didUpdateLocations locations: [CLLocation]
167
+ ) {
168
+ guard let loc = locations.last else { return }
169
+ let now = Date()
170
+
171
+ if shouldEmit(now: now) {
172
+ lastEmit = now
173
+ onUpdate?(loc)
174
+ }
175
+ }
176
+
177
+ private static func topMostViewController() -> UIViewController? {
178
+ let scenes = UIApplication.shared.connectedScenes
179
+ .compactMap { $0 as? UIWindowScene }
180
+ .filter { $0.activationState == .foregroundActive }
181
+
182
+ guard
183
+ let window = scenes.flatMap({ $0.windows }).first(where: {
184
+ $0.isKeyWindow
185
+ }),
186
+ var top = window.rootViewController
187
+ else { return nil }
188
+
189
+ while let presented = top.presentedViewController { top = presented }
190
+ return top
191
+ }
192
+
193
+ }
194
+
195
+ extension LocationHandler {
196
+ enum Priority: Int {
197
+ case highAccuracy = 100
198
+ /// Android: PRIORITY_BALANCED_POWER_ACCURACY
199
+ case balanced = 102
200
+ /// Android: PRIORITY_LOW_POWER
201
+ case lowPower = 104
202
+ /// Android: PRIORITY_PASSIVE
203
+ case passive = 105
204
+ }
205
+ }
@@ -0,0 +1,43 @@
1
+ import GoogleMaps
2
+
3
+ class MapCircleOptions {
4
+
5
+ func buildCircle(_ c: RNCircle) -> GMSCircle {
6
+ let circle = GMSCircle()
7
+ circle.position = CLLocationCoordinate2D(
8
+ latitude: c.center.latitude,
9
+ longitude: c.center.longitude
10
+ )
11
+ if let r = c.radius { circle.radius = r }
12
+ if let fc = c.fillColor?.toUIColor() { circle.fillColor = fc }
13
+ if let sc = c.strokeColor?.toUIColor() { circle.strokeColor = sc }
14
+ if let sw = c.strokeWidth { circle.strokeWidth = CGFloat(sw) }
15
+ if let pr = c.pressable { circle.isTappable = pr }
16
+ if let zi = c.zIndex { circle.zIndex = Int32(zi) }
17
+
18
+ return circle
19
+ }
20
+ }
21
+
22
+ extension RNCircle {
23
+ func updateCircle(_ next: RNCircle, _ c: GMSCircle) {
24
+ c.position = CLLocationCoordinate2D(
25
+ latitude: next.center.latitude,
26
+ longitude: next.center.longitude
27
+ )
28
+ if let r = next.radius { c.radius = r }
29
+ if let fc = next.fillColor?.toUIColor() { c.fillColor = fc }
30
+ if let sc = next.strokeColor?.toUIColor() { c.strokeColor = sc }
31
+ if let sw = next.strokeWidth { c.strokeWidth = CGFloat(sw) }
32
+ if let pr = next.pressable { c.isTappable = pr }
33
+ if let zi = next.zIndex { c.zIndex = Int32(zi) }
34
+ }
35
+
36
+ func circleEquals(_ b: RNCircle) -> Bool {
37
+ zIndex == b.zIndex && pressable == b.pressable
38
+ && center.latitude == b.center.latitude
39
+ && center.longitude == b.center.longitude && radius == b.radius
40
+ && strokeWidth == b.strokeWidth && strokeColor == b.strokeColor
41
+ && fillColor == b.fillColor
42
+ }
43
+ }
@@ -0,0 +1,18 @@
1
+ import QuartzCore
2
+
3
+ @inline(__always)
4
+ func withCATransaction(
5
+ disableActions: Bool = true,
6
+ duration: CFTimeInterval? = nil,
7
+ timingFunction: CAMediaTimingFunction? = nil,
8
+ completion: (() -> Void)? = nil,
9
+ _ body: () -> Void
10
+ ) {
11
+ CATransaction.begin()
12
+ if disableActions { CATransaction.setDisableActions(true) }
13
+ if let d = duration { CATransaction.setAnimationDuration(d) }
14
+ if let tf = timingFunction { CATransaction.setAnimationTimingFunction(tf) }
15
+ if let c = completion { CATransaction.setCompletionBlock(c) }
16
+ body()
17
+ CATransaction.commit()
18
+ }
@@ -0,0 +1,200 @@
1
+ import GoogleMaps
2
+ import SVGKit
3
+ import UIKit
4
+
5
+ final class MapMarkerOptions {
6
+ private let iconCache = NSCache<NSString, UIImage>()
7
+ 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
+
14
+ func build(_ m: RNMarker, icon: UIImage) -> GMSMarker {
15
+ let marker = GMSMarker(
16
+ position: CLLocationCoordinate2D(
17
+ latitude: m.coordinate.latitude,
18
+ longitude: m.coordinate.longitude
19
+ )
20
+ )
21
+ marker.userData = m.id
22
+ marker.tracksViewChanges = true
23
+ marker.icon = icon
24
+ marker.groundAnchor = CGPoint(
25
+ x: m.anchor?.x ?? 0.5,
26
+ y: m.anchor?.y ?? 0.5
27
+ )
28
+ if let zi = m.zIndex { marker.zIndex = Int32(zi) }
29
+ DispatchQueue.main.asyncAfter(deadline: .now() + 0.25) { [weak marker] in
30
+ marker?.tracksViewChanges = false
31
+ }
32
+ return marker
33
+ }
34
+
35
+ @MainActor
36
+ func buildIconAsync(
37
+ _ id: String,
38
+ _ m: RNMarker,
39
+ onReady: @escaping (UIImage?) -> Void
40
+ ) {
41
+ tasks[id]?.cancel()
42
+
43
+ let key = m.styleHash()
44
+ if let cached = iconCache.object(forKey: key) {
45
+ onReady(cached)
46
+ return
47
+ }
48
+
49
+ let task = Task(priority: .userInitiated) { [weak self] in
50
+ guard let self else { return }
51
+ defer {
52
+ self.tasks.removeValue(forKey: id)
53
+ }
54
+
55
+ let img = await self.renderUIImage(m)
56
+ guard let img, !Task.isCancelled else {
57
+ return
58
+ }
59
+
60
+ self.iconCache.setObject(img, forKey: key)
61
+
62
+ await MainActor.run {
63
+ guard !Task.isCancelled else { return }
64
+ onReady(img)
65
+ }
66
+
67
+ }
68
+
69
+ tasks[id] = task
70
+ }
71
+
72
+ @MainActor
73
+ func updateMarker(_ prev: RNMarker, _ next: RNMarker, _ m: GMSMarker) {
74
+ m.position = CLLocationCoordinate2D(
75
+ latitude: next.coordinate.latitude,
76
+ longitude: next.coordinate.longitude
77
+ )
78
+
79
+ if let zi = next.zIndex { m.zIndex = Int32(zi) }
80
+
81
+ m.groundAnchor = CGPoint(
82
+ x: next.anchor?.x ?? 0.5,
83
+ y: next.anchor?.y ?? 0.5
84
+ )
85
+
86
+ if !prev.markerStyleEquals(next) {
87
+ buildIconAsync(next.id, next) { img in
88
+ guard let img else { return }
89
+ m.tracksViewChanges = true
90
+ m.icon = img
91
+ if prev.anchor?.x != next.anchor?.x || prev.anchor?.y != next.anchor?.y {
92
+ m.groundAnchor = CGPoint(
93
+ x: next.anchor?.x ?? 0.5,
94
+ y: next.anchor?.y ?? 0.5
95
+ )
96
+ }
97
+
98
+ DispatchQueue.main.asyncAfter(deadline: .now() + 0.25) { [weak m] in
99
+ m?.tracksViewChanges = false
100
+ }
101
+ }
102
+ }
103
+ }
104
+
105
+ func cancelIconTask(_ id: String) {
106
+ tasks[id]?.cancel()
107
+ tasks.removeValue(forKey: id)
108
+ }
109
+
110
+ func cancelAllIconTasks() {
111
+ let ids = Array(tasks.keys)
112
+ for id in ids {
113
+ tasks[id]?.cancel()
114
+ }
115
+ tasks.removeAll()
116
+ iconCache.removeAllObjects()
117
+ }
118
+
119
+ private func renderUIImage(_ m: RNMarker) async -> UIImage? {
120
+ await withTaskCancellationHandler(
121
+ operation: {
122
+ await withCheckedContinuation { cont in
123
+ queue.async {
124
+ if Task.isCancelled {
125
+ cont.resume(returning: nil)
126
+ return
127
+ }
128
+
129
+ let targetW = max(1, Int(CGFloat(m.width)))
130
+ let targetH = max(1, Int(CGFloat(m.height)))
131
+ let size = CGSize(width: targetW, height: targetH)
132
+
133
+ guard
134
+ let data = m.iconSvg.data(using: .utf8),
135
+ let svgImg = SVGKImage(data: data)
136
+ else {
137
+ cont.resume(returning: nil)
138
+ return
139
+ }
140
+
141
+ svgImg.size = size
142
+
143
+ if Task.isCancelled {
144
+ cont.resume(returning: nil)
145
+ return
146
+ }
147
+
148
+ guard let base = svgImg.uiImage else {
149
+ cont.resume(returning: nil)
150
+ return
151
+ }
152
+
153
+ let scale = UIScreen.main.scale
154
+ let img: UIImage
155
+ if let cg = base.cgImage {
156
+ img = UIImage(cgImage: cg, scale: scale, orientation: .up)
157
+ } else {
158
+ let fmt = UIGraphicsImageRendererFormat.default()
159
+ fmt.opaque = false
160
+ fmt.scale = scale
161
+ let renderer = UIGraphicsImageRenderer(size: size, format: fmt)
162
+ img = renderer.image { _ in
163
+ base.draw(in: CGRect(origin: .zero, size: size))
164
+ }
165
+ }
166
+
167
+ cont.resume(returning: img)
168
+ }
169
+ }
170
+
171
+ },
172
+ onCancel: {}
173
+ )
174
+ }
175
+
176
+ }
177
+
178
+ extension RNMarker {
179
+ func markerEquals(_ b: RNMarker) -> Bool {
180
+ id == b.id && zIndex == b.zIndex
181
+ && coordinate.latitude == b.coordinate.latitude
182
+ && coordinate.longitude == b.coordinate.longitude
183
+ && anchor?.x == b.anchor?.x && anchor?.y == b.anchor?.y
184
+ && markerStyleEquals(b)
185
+ }
186
+
187
+ func markerStyleEquals(_ b: RNMarker) -> Bool {
188
+ width == b.width && height == b.height
189
+ && iconSvg == b.iconSvg
190
+ }
191
+
192
+ func styleHash() -> NSString {
193
+ var hasher = Hasher()
194
+ hasher.combine(width)
195
+ hasher.combine(height)
196
+ hasher.combine(iconSvg)
197
+ return String(hasher.finalize()) as NSString
198
+ }
199
+
200
+ }
@@ -0,0 +1,58 @@
1
+ import GoogleMaps
2
+
3
+ class MapPolygonOptions {
4
+
5
+ func buildPolygon(_ p: RNPolygon) -> GMSPolygon {
6
+ let path = GMSMutablePath()
7
+ p.coordinates.forEach {
8
+ path.add(
9
+ CLLocationCoordinate2D(latitude: $0.latitude, longitude: $0.longitude)
10
+ )
11
+ }
12
+ let pg = GMSPolygon(path: path)
13
+ if let fc = p.fillColor?.toUIColor() { pg.fillColor = fc }
14
+ if let sc = p.strokeColor?.toUIColor() { pg.strokeColor = sc }
15
+ if let sw = p.strokeWidth { pg.strokeWidth = CGFloat(sw) }
16
+ if let pr = p.pressable { pg.isTappable = pr }
17
+ if let zi = p.zIndex { pg.zIndex = Int32(zi) }
18
+ return pg
19
+ }
20
+ }
21
+
22
+ extension RNPolygon {
23
+ func updatePolygon(_ next: RNPolygon, _ pg: GMSPolygon) {
24
+ let path = GMSMutablePath()
25
+ next.coordinates.forEach {
26
+ path.add(
27
+ CLLocationCoordinate2D(
28
+ latitude: $0.latitude,
29
+ longitude: $0.longitude
30
+ )
31
+ )
32
+ }
33
+ pg.path = path
34
+
35
+ if let fc = next.fillColor?.toUIColor() { pg.fillColor = fc }
36
+ if let sc = next.strokeColor?.toUIColor() { pg.strokeColor = sc }
37
+ if let sw = next.strokeWidth { pg.strokeWidth = CGFloat(sw) }
38
+ if let pr = next.pressable { pg.isTappable = pr }
39
+ if let zi = next.zIndex { pg.zIndex = Int32(zi) }
40
+ }
41
+
42
+ func polygonEquals(_ b: RNPolygon) -> Bool {
43
+ guard zIndex == b.zIndex,
44
+ pressable == b.pressable,
45
+ strokeWidth == b.strokeWidth,
46
+ fillColor == b.fillColor,
47
+ strokeColor == b.strokeColor,
48
+ coordinates.count == b.coordinates.count
49
+ else { return false }
50
+ for i in 0..<coordinates.count {
51
+ if coordinates[i].latitude != b.coordinates[i].latitude
52
+ || coordinates[i].longitude != b.coordinates[i].longitude {
53
+ return false
54
+ }
55
+ }
56
+ return true
57
+ }
58
+ }
@@ -0,0 +1,85 @@
1
+ import GoogleMaps
2
+
3
+ class MapPolylineOptions {
4
+ func buildPolyline(_ p: RNPolyline) -> GMSPolyline {
5
+ let path = GMSMutablePath()
6
+ p.coordinates.forEach {
7
+ path.add(
8
+ CLLocationCoordinate2D(latitude: $0.latitude, longitude: $0.longitude)
9
+ )
10
+ }
11
+ let pl = GMSPolyline(path: path)
12
+ if let w = p.width { pl.strokeWidth = CGFloat(w) }
13
+ if let c = p.color?.toUIColor() { pl.strokeColor = c }
14
+ if let cap = p.lineCap {
15
+ /// pl.lineCap = mapLineCap(cap)
16
+ }
17
+ if let join = p.lineJoin {
18
+ /// pl.strokeJoin = mapLineJoin(join)
19
+ }
20
+ if let pr = p.pressable { pl.isTappable = pr }
21
+ if let zi = p.zIndex { pl.zIndex = Int32(zi) }
22
+ return pl
23
+ }
24
+ }
25
+
26
+ func mapLineCap(_ t: RNLineCapType?) -> CGLineCap {
27
+ switch t {
28
+ case .round: return .round
29
+ case .square: return .square
30
+ default: return .butt
31
+ }
32
+ }
33
+
34
+ func mapLineJoin(_ t: RNLineJoinType?) -> CGLineJoin {
35
+ switch t {
36
+ case .round: return .round
37
+ case .bevel: return .bevel
38
+ default: return .miter
39
+ }
40
+ }
41
+
42
+ extension RNPolyline {
43
+ func updatePolyline(_ next: RNPolyline, _ pl: GMSPolyline) {
44
+ let path = GMSMutablePath()
45
+ next.coordinates.forEach {
46
+ path.add(
47
+ CLLocationCoordinate2D(
48
+ latitude: $0.latitude,
49
+ longitude: $0.longitude
50
+ )
51
+ )
52
+ }
53
+ pl.path = path
54
+ if let w = next.width { pl.strokeWidth = CGFloat(w) }
55
+ if let cap = next.lineCap {
56
+ pl.spans = nil
57
+ /// gms.lineCap = mapLineCap(cap)
58
+ }
59
+ if let join = next.lineJoin {
60
+ /// gms.strokeJoin = mapLineJoin(join)
61
+ }
62
+ if let c = next.color?.toUIColor() {
63
+ pl.strokeColor = c
64
+ }
65
+ if let pr = next.pressable { pl.isTappable = pr }
66
+ if let zi = next.zIndex { pl.zIndex = Int32(zi) }
67
+ }
68
+
69
+ func polylineEquals(_ b: RNPolyline) -> Bool {
70
+ guard zIndex == b.zIndex,
71
+ (width ?? 0) == (b.width ?? 0),
72
+ lineCap == b.lineCap,
73
+ lineJoin == b.lineJoin,
74
+ color == b.color,
75
+ coordinates.count == b.coordinates.count
76
+ else { return false }
77
+ for i in 0..<coordinates.count {
78
+ if coordinates[i].latitude != b.coordinates[i].latitude
79
+ || coordinates[i].longitude != b.coordinates[i].longitude {
80
+ return false
81
+ }
82
+ }
83
+ return true
84
+ }
85
+ }
@@ -0,0 +1,73 @@
1
+ import CoreLocation
2
+ import Foundation
3
+ import NitroModules
4
+ import UIKit
5
+
6
+ final class PermissionHandler: NSObject, CLLocationManagerDelegate {
7
+ private let manager = CLLocationManager()
8
+ private var pendingPromises:
9
+ [NitroModules.Promise<RNLocationPermissionResult>] = []
10
+
11
+ override init() {
12
+ super.init()
13
+ manager.delegate = self
14
+ }
15
+
16
+ func requestLocationPermission()
17
+ -> NitroModules.Promise<RNLocationPermissionResult> {
18
+ let promise = NitroModules.Promise<RNLocationPermissionResult>()
19
+
20
+ let status = manager.authorizationStatus
21
+ switch status {
22
+ case .authorizedAlways, .authorizedWhenInUse:
23
+ promise.resolve(
24
+ withResult: RNLocationPermissionResult(
25
+ android: nil,
26
+ ios: RNIOSPermissionResult.authorized
27
+ )
28
+ )
29
+ return promise
30
+ case .denied, .restricted:
31
+ promise.resolve(
32
+ withResult: RNLocationPermissionResult(
33
+ android: nil,
34
+ ios: RNIOSPermissionResult.denied
35
+ )
36
+ )
37
+ return promise
38
+ case .notDetermined:
39
+ break
40
+ @unknown default:
41
+ break
42
+ }
43
+
44
+ pendingPromises.append(promise)
45
+ manager.requestWhenInUseAuthorization()
46
+
47
+ return promise
48
+ }
49
+
50
+ func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) {
51
+ guard !pendingPromises.isEmpty else { return }
52
+
53
+ let status: RNIOSPermissionResult
54
+ switch manager.authorizationStatus {
55
+ case .authorizedWhenInUse, .authorizedAlways:
56
+ status = RNIOSPermissionResult.authorized
57
+ case .denied, .restricted:
58
+ status = RNIOSPermissionResult.denied
59
+ case .notDetermined:
60
+ return
61
+ @unknown default:
62
+ status = RNIOSPermissionResult.denied
63
+ }
64
+
65
+ let promises = pendingPromises
66
+ pendingPromises.removeAll()
67
+ promises.forEach {
68
+ $0.resolve(
69
+ withResult: RNLocationPermissionResult(android: nil, ios: status)
70
+ )
71
+ }
72
+ }
73
+ }
@@ -0,0 +1,27 @@
1
+ final class RNGoogleMapsPlusModule: HybridRNGoogleMapsPlusModuleSpec {
2
+ private let permissionHandler: PermissionHandler
3
+ private let locationHandler: LocationHandler
4
+
5
+ override init() {
6
+ self.permissionHandler = PermissionHandler()
7
+ self.locationHandler = LocationHandler()
8
+ }
9
+
10
+ func showLocationDialog() {
11
+ locationHandler.showLocationDialog()
12
+ }
13
+
14
+ func openLocationSettings() {
15
+ locationHandler.openLocationSettings()
16
+ }
17
+
18
+ func requestLocationPermission()
19
+ -> NitroModules.Promise<RNLocationPermissionResult> {
20
+ return permissionHandler.requestLocationPermission()
21
+ }
22
+
23
+ func isGooglePlayServicesAvailable() -> Bool {
24
+ /// not supported
25
+ return true
26
+ }
27
+ }