react-native-nitro-geolocation 1.2.5 → 1.3.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 (223) hide show
  1. package/README.md +55 -278
  2. package/android/build.gradle +1 -0
  3. package/android/src/main/AndroidManifest.xml +39 -0
  4. package/android/src/main/java/com/margelo/nitro/nitrogeolocation/AndroidFusedLocationProvider.kt +310 -0
  5. package/android/src/main/java/com/margelo/nitro/nitrogeolocation/AndroidFusedRequestFactory.kt +31 -0
  6. package/android/src/main/java/com/margelo/nitro/nitrogeolocation/AndroidGeolocationConversions.kt +71 -0
  7. package/android/src/main/java/com/margelo/nitro/nitrogeolocation/AndroidGeolocationErrors.kt +85 -0
  8. package/android/src/main/java/com/margelo/nitro/nitrogeolocation/AndroidGeolocationOptions.kt +92 -0
  9. package/android/src/main/java/com/margelo/nitro/nitrogeolocation/AndroidLocationSettings.kt +3 -0
  10. package/android/src/main/java/com/margelo/nitro/nitrogeolocation/AndroidProviderRoute.kt +74 -0
  11. package/android/src/main/java/com/margelo/nitro/nitrogeolocation/NitroBackgroundLocation.kt +132 -0
  12. package/android/src/main/java/com/margelo/nitro/nitrogeolocation/NitroGeolocation.kt +219 -476
  13. package/android/src/main/java/com/margelo/nitro/nitrogeolocation/background/AndroidBackgroundHttpSync.kt +134 -0
  14. package/android/src/main/java/com/margelo/nitro/nitrogeolocation/background/AndroidBackgroundPermissions.kt +196 -0
  15. package/android/src/main/java/com/margelo/nitro/nitrogeolocation/background/AndroidBackgroundSerialization.kt +266 -0
  16. package/android/src/main/java/com/margelo/nitro/nitrogeolocation/background/NitroActivityRecognitionReceiver.kt +13 -0
  17. package/android/src/main/java/com/margelo/nitro/nitrogeolocation/background/NitroBackgroundEventHub.kt +65 -0
  18. package/android/src/main/java/com/margelo/nitro/nitrogeolocation/background/NitroBackgroundHeadlessTaskService.kt +58 -0
  19. package/android/src/main/java/com/margelo/nitro/nitrogeolocation/background/NitroBackgroundLocationController.kt +710 -0
  20. package/android/src/main/java/com/margelo/nitro/nitrogeolocation/background/NitroBackgroundLocationService.kt +48 -0
  21. package/android/src/main/java/com/margelo/nitro/nitrogeolocation/background/NitroBackgroundNotificationFactory.kt +37 -0
  22. package/android/src/main/java/com/margelo/nitro/nitrogeolocation/background/NitroBackgroundStore.kt +655 -0
  23. package/android/src/main/java/com/margelo/nitro/nitrogeolocation/background/NitroBootReceiver.kt +26 -0
  24. package/android/src/main/java/com/margelo/nitro/nitrogeolocation/background/NitroGeofenceReceiver.kt +14 -0
  25. package/android/src/main/java/com/margelo/nitro/nitrogeolocation/background/NitroLocationUpdateReceiver.kt +37 -0
  26. package/android/src/test/java/com/margelo/nitro/nitrogeolocation/AndroidFusedLocationProviderTest.kt +64 -0
  27. package/android/src/test/java/com/margelo/nitro/nitrogeolocation/AndroidProviderRouteTest.kt +116 -0
  28. package/ios/IOSBackgroundHttpSync.swift +126 -0
  29. package/ios/IOSBackgroundLocationDelegate.swift +36 -0
  30. package/ios/IOSBackgroundMotion.swift +55 -0
  31. package/ios/IOSBackgroundSerialization.swift +539 -0
  32. package/ios/IOSGeolocationConversions.swift +131 -0
  33. package/ios/IOSGeolocationDelegate.swift +31 -0
  34. package/ios/IOSGeolocationErrors.swift +39 -0
  35. package/ios/IOSGeolocationOptions.swift +135 -0
  36. package/ios/NitroBackgroundLocation.swift +849 -0
  37. package/ios/NitroGeolocation.swift +14 -347
  38. package/nitrogen/generated/android/c++/JActivityRecognitionOptions.hpp +69 -0
  39. package/nitrogen/generated/android/c++/JAndroidBackgroundLocationOptions.hpp +74 -0
  40. package/nitrogen/generated/android/c++/JAndroidBackgroundLocationStatus.hpp +67 -0
  41. package/nitrogen/generated/android/c++/JAndroidBackgroundProvider.hpp +61 -0
  42. package/nitrogen/generated/android/c++/JAndroidForegroundServiceOptions.hpp +90 -0
  43. package/nitrogen/generated/android/c++/JBackgroundEventEnvelope.hpp +129 -0
  44. package/nitrogen/generated/android/c++/JBackgroundEventType.hpp +70 -0
  45. package/nitrogen/generated/android/c++/JBackgroundHttpMethod.hpp +61 -0
  46. package/nitrogen/generated/android/c++/JBackgroundHttpSyncOptions.hpp +131 -0
  47. package/nitrogen/generated/android/c++/JBackgroundHttpSyncResult.hpp +111 -0
  48. package/nitrogen/generated/android/c++/JBackgroundLocation.hpp +110 -0
  49. package/nitrogen/generated/android/c++/JBackgroundLocationOptions.hpp +162 -0
  50. package/nitrogen/generated/android/c++/JBackgroundLocationSource.hpp +73 -0
  51. package/nitrogen/generated/android/c++/JBackgroundLocationState.hpp +70 -0
  52. package/nitrogen/generated/android/c++/JBackgroundLocationStatus.hpp +126 -0
  53. package/nitrogen/generated/android/c++/JBackgroundPermissionResult.hpp +79 -0
  54. package/nitrogen/generated/android/c++/JBackgroundPermissionStatus.hpp +64 -0
  55. package/nitrogen/generated/android/c++/JBackgroundTrackingMode.hpp +61 -0
  56. package/nitrogen/generated/android/c++/JBatterySnapshot.hpp +61 -0
  57. package/nitrogen/generated/android/c++/JDetectedActivity.hpp +66 -0
  58. package/nitrogen/generated/android/c++/JDetectedActivityType.hpp +76 -0
  59. package/nitrogen/generated/android/c++/JFunc_void_BackgroundEventEnvelope.hpp +114 -0
  60. package/nitrogen/generated/android/c++/JFunc_void_BackgroundLocation.hpp +95 -0
  61. package/nitrogen/generated/android/c++/JGeofenceEvent.hpp +94 -0
  62. package/nitrogen/generated/android/c++/JGeofenceRegion.hpp +112 -0
  63. package/nitrogen/generated/android/c++/JGeofenceTransition.hpp +61 -0
  64. package/nitrogen/generated/android/c++/JGeofencingOptions.hpp +82 -0
  65. package/nitrogen/generated/android/c++/JGetStoredBackgroundEventsOptions.hpp +90 -0
  66. package/nitrogen/generated/android/c++/JGetStoredBackgroundLocationsOptions.hpp +69 -0
  67. package/nitrogen/generated/android/c++/JHybridNitroBackgroundLocationSpec.cpp +662 -0
  68. package/nitrogen/generated/android/c++/JHybridNitroBackgroundLocationSpec.hpp +89 -0
  69. package/nitrogen/generated/android/c++/JIOSBackgroundActivityType.hpp +67 -0
  70. package/nitrogen/generated/android/c++/JIOSBackgroundLocationOptions.hpp +79 -0
  71. package/nitrogen/generated/android/c++/JIOSBackgroundLocationStatus.hpp +61 -0
  72. package/nitrogen/generated/android/c++/JLocationProviderStatus.hpp +5 -1
  73. package/nitrogen/generated/android/c++/JStoredBackgroundEventEnvelope.hpp +115 -0
  74. package/nitrogen/generated/android/c++/JStoredBackgroundLocation.hpp +122 -0
  75. package/nitrogen/generated/android/c++/JVariant_NullType_Boolean_String_Double.cpp +34 -0
  76. package/nitrogen/generated/android/c++/JVariant_NullType_Boolean_String_Double.hpp +100 -0
  77. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/ActivityRecognitionOptions.kt +66 -0
  78. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/AndroidBackgroundLocationOptions.kt +66 -0
  79. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/AndroidBackgroundLocationStatus.kt +61 -0
  80. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/AndroidBackgroundProvider.kt +24 -0
  81. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/AndroidForegroundServiceOptions.kt +91 -0
  82. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/BackgroundEventEnvelope.kt +96 -0
  83. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/BackgroundEventType.kt +27 -0
  84. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/BackgroundHttpMethod.kt +24 -0
  85. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/BackgroundHttpSyncOptions.kt +101 -0
  86. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/BackgroundHttpSyncResult.kt +71 -0
  87. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/BackgroundLocation.kt +96 -0
  88. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/BackgroundLocationOptions.kt +136 -0
  89. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/BackgroundLocationSource.kt +28 -0
  90. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/BackgroundLocationState.kt +27 -0
  91. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/BackgroundLocationStatus.kt +116 -0
  92. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/BackgroundPermissionResult.kt +71 -0
  93. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/BackgroundPermissionStatus.kt +25 -0
  94. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/BackgroundTrackingMode.kt +24 -0
  95. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/BatterySnapshot.kt +56 -0
  96. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/DetectedActivity.kt +61 -0
  97. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/DetectedActivityType.kt +29 -0
  98. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/Func_void_BackgroundEventEnvelope.kt +80 -0
  99. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/Func_void_BackgroundLocation.kt +80 -0
  100. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/GeofenceEvent.kt +66 -0
  101. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/GeofenceRegion.kt +96 -0
  102. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/GeofenceTransition.kt +24 -0
  103. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/GeofencingOptions.kt +56 -0
  104. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/GetStoredBackgroundEventsOptions.kt +66 -0
  105. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/GetStoredBackgroundLocationsOptions.kt +66 -0
  106. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/HybridNitroBackgroundLocationSpec.kt +174 -0
  107. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/IOSBackgroundActivityType.kt +26 -0
  108. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/IOSBackgroundLocationOptions.kt +76 -0
  109. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/IOSBackgroundLocationStatus.kt +56 -0
  110. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/LocationProviderStatus.kt +7 -2
  111. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/StoredBackgroundEventEnvelope.kt +76 -0
  112. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/StoredBackgroundLocation.kt +111 -0
  113. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/Variant_NullType_Boolean_String_Double.kt +88 -0
  114. package/nitrogen/generated/android/nitrogeolocation+autolinking.cmake +3 -0
  115. package/nitrogen/generated/android/nitrogeolocationOnLoad.cpp +20 -0
  116. package/nitrogen/generated/ios/NitroGeolocation-Swift-Cxx-Bridge.cpp +104 -15
  117. package/nitrogen/generated/ios/NitroGeolocation-Swift-Cxx-Bridge.hpp +1107 -50
  118. package/nitrogen/generated/ios/NitroGeolocation-Swift-Cxx-Umbrella.hpp +102 -0
  119. package/nitrogen/generated/ios/NitroGeolocationAutolinking.mm +8 -0
  120. package/nitrogen/generated/ios/NitroGeolocationAutolinking.swift +15 -3
  121. package/nitrogen/generated/ios/c++/HybridNitroBackgroundLocationSpecSwift.cpp +11 -0
  122. package/nitrogen/generated/ios/c++/HybridNitroBackgroundLocationSpecSwift.hpp +416 -0
  123. package/nitrogen/generated/ios/swift/ActivityRecognitionOptions.swift +96 -0
  124. package/nitrogen/generated/ios/swift/AndroidBackgroundLocationOptions.swift +76 -0
  125. package/nitrogen/generated/ios/swift/AndroidBackgroundLocationStatus.swift +58 -0
  126. package/nitrogen/generated/ios/swift/AndroidBackgroundProvider.swift +44 -0
  127. package/nitrogen/generated/ios/swift/AndroidForegroundServiceOptions.swift +160 -0
  128. package/nitrogen/generated/ios/swift/BackgroundEventEnvelope.swift +110 -0
  129. package/nitrogen/generated/ios/swift/BackgroundEventType.swift +56 -0
  130. package/nitrogen/generated/ios/swift/BackgroundHttpMethod.swift +44 -0
  131. package/nitrogen/generated/ios/swift/BackgroundHttpSyncOptions.swift +259 -0
  132. package/nitrogen/generated/ios/swift/BackgroundHttpSyncResult.swift +87 -0
  133. package/nitrogen/generated/ios/swift/BackgroundLocation.swift +118 -0
  134. package/nitrogen/generated/ios/swift/BackgroundLocationOptions.swift +292 -0
  135. package/nitrogen/generated/ios/swift/BackgroundLocationSource.swift +60 -0
  136. package/nitrogen/generated/ios/swift/BackgroundLocationState.swift +56 -0
  137. package/nitrogen/generated/ios/swift/BackgroundLocationStatus.swift +124 -0
  138. package/nitrogen/generated/ios/swift/BackgroundPermissionResult.swift +81 -0
  139. package/nitrogen/generated/ios/swift/BackgroundPermissionStatus.swift +48 -0
  140. package/nitrogen/generated/ios/swift/BackgroundTrackingMode.swift +44 -0
  141. package/nitrogen/generated/ios/swift/BatterySnapshot.swift +60 -0
  142. package/nitrogen/generated/ios/swift/DetectedActivity.swift +39 -0
  143. package/nitrogen/generated/ios/swift/DetectedActivityType.swift +64 -0
  144. package/nitrogen/generated/ios/swift/Func_void_BackgroundEventEnvelope.swift +46 -0
  145. package/nitrogen/generated/ios/swift/Func_void_BackgroundHttpSyncResult.swift +46 -0
  146. package/nitrogen/generated/ios/swift/Func_void_BackgroundLocation.swift +46 -0
  147. package/nitrogen/generated/ios/swift/Func_void_BackgroundLocationStatus.swift +46 -0
  148. package/nitrogen/generated/ios/swift/Func_void_BackgroundPermissionResult.swift +46 -0
  149. package/nitrogen/generated/ios/swift/Func_void_std__optional_BackgroundLocationOptions_.swift +46 -0
  150. package/nitrogen/generated/ios/swift/Func_void_std__vector_GeofenceRegion_.swift +46 -0
  151. package/nitrogen/generated/ios/swift/Func_void_std__vector_StoredBackgroundEventEnvelope_.swift +46 -0
  152. package/nitrogen/generated/ios/swift/Func_void_std__vector_StoredBackgroundLocation_.swift +46 -0
  153. package/nitrogen/generated/ios/swift/GeofenceEvent.swift +50 -0
  154. package/nitrogen/generated/ios/swift/GeofenceRegion.swift +195 -0
  155. package/nitrogen/generated/ios/swift/GeofenceTransition.swift +44 -0
  156. package/nitrogen/generated/ios/swift/GeofencingOptions.swift +66 -0
  157. package/nitrogen/generated/ios/swift/GetStoredBackgroundEventsOptions.swift +102 -0
  158. package/nitrogen/generated/ios/swift/GetStoredBackgroundLocationsOptions.swift +96 -0
  159. package/nitrogen/generated/ios/swift/HybridNitroBackgroundLocationSpec.swift +81 -0
  160. package/nitrogen/generated/ios/swift/HybridNitroBackgroundLocationSpec_cxx.swift +654 -0
  161. package/nitrogen/generated/ios/swift/IOSBackgroundActivityType.swift +52 -0
  162. package/nitrogen/generated/ios/swift/IOSBackgroundLocationOptions.swift +125 -0
  163. package/nitrogen/generated/ios/swift/IOSBackgroundLocationStatus.swift +34 -0
  164. package/nitrogen/generated/ios/swift/LocationProviderStatus.swift +19 -1
  165. package/nitrogen/generated/ios/swift/StoredBackgroundEventEnvelope.swift +54 -0
  166. package/nitrogen/generated/ios/swift/StoredBackgroundLocation.swift +120 -0
  167. package/nitrogen/generated/ios/swift/Variant_NullType_Bool_String_Double.swift +34 -0
  168. package/nitrogen/generated/shared/c++/ActivityRecognitionOptions.hpp +95 -0
  169. package/nitrogen/generated/shared/c++/AndroidBackgroundLocationOptions.hpp +100 -0
  170. package/nitrogen/generated/shared/c++/AndroidBackgroundLocationStatus.hpp +93 -0
  171. package/nitrogen/generated/shared/c++/AndroidBackgroundProvider.hpp +80 -0
  172. package/nitrogen/generated/shared/c++/AndroidForegroundServiceOptions.hpp +116 -0
  173. package/nitrogen/generated/shared/c++/BackgroundEventEnvelope.hpp +140 -0
  174. package/nitrogen/generated/shared/c++/BackgroundEventType.hpp +92 -0
  175. package/nitrogen/generated/shared/c++/BackgroundHttpMethod.hpp +80 -0
  176. package/nitrogen/generated/shared/c++/BackgroundHttpSyncOptions.hpp +129 -0
  177. package/nitrogen/generated/shared/c++/BackgroundHttpSyncResult.hpp +101 -0
  178. package/nitrogen/generated/shared/c++/BackgroundLocation.hpp +134 -0
  179. package/nitrogen/generated/shared/c++/BackgroundLocationOptions.hpp +174 -0
  180. package/nitrogen/generated/shared/c++/BackgroundLocationSource.hpp +96 -0
  181. package/nitrogen/generated/shared/c++/BackgroundLocationState.hpp +92 -0
  182. package/nitrogen/generated/shared/c++/BackgroundLocationStatus.hpp +158 -0
  183. package/nitrogen/generated/shared/c++/BackgroundPermissionResult.hpp +107 -0
  184. package/nitrogen/generated/shared/c++/BackgroundPermissionStatus.hpp +84 -0
  185. package/nitrogen/generated/shared/c++/BackgroundTrackingMode.hpp +80 -0
  186. package/nitrogen/generated/shared/c++/BatterySnapshot.hpp +87 -0
  187. package/nitrogen/generated/shared/c++/DetectedActivity.hpp +92 -0
  188. package/nitrogen/generated/shared/c++/DetectedActivityType.hpp +100 -0
  189. package/nitrogen/generated/shared/c++/GeofenceEvent.hpp +103 -0
  190. package/nitrogen/generated/shared/c++/GeofenceRegion.hpp +123 -0
  191. package/nitrogen/generated/shared/c++/GeofenceTransition.hpp +80 -0
  192. package/nitrogen/generated/shared/c++/GeofencingOptions.hpp +90 -0
  193. package/nitrogen/generated/shared/c++/GetStoredBackgroundEventsOptions.hpp +98 -0
  194. package/nitrogen/generated/shared/c++/GetStoredBackgroundLocationsOptions.hpp +95 -0
  195. package/nitrogen/generated/shared/c++/HybridNitroBackgroundLocationSpec.cpp +47 -0
  196. package/nitrogen/generated/shared/c++/HybridNitroBackgroundLocationSpec.hpp +133 -0
  197. package/nitrogen/generated/shared/c++/IOSBackgroundActivityType.hpp +88 -0
  198. package/nitrogen/generated/shared/c++/IOSBackgroundLocationOptions.hpp +105 -0
  199. package/nitrogen/generated/shared/c++/IOSBackgroundLocationStatus.hpp +87 -0
  200. package/nitrogen/generated/shared/c++/LocationProviderStatus.hpp +5 -1
  201. package/nitrogen/generated/shared/c++/StoredBackgroundEventEnvelope.hpp +108 -0
  202. package/nitrogen/generated/shared/c++/StoredBackgroundLocation.hpp +146 -0
  203. package/package.json +17 -6
  204. package/src/NitroGeolocation.nitro.ts +4 -4
  205. package/src/api/getCurrentPosition.ts +1 -1
  206. package/src/api/requestLocationSettings.ts +3 -2
  207. package/src/background/NitroBackgroundLocation.nitro.ts +83 -0
  208. package/src/background/index.ts +200 -0
  209. package/src/background/index.web.ts +120 -0
  210. package/src/background/task.ts +13 -0
  211. package/src/background/types.ts +328 -0
  212. package/src/compat/index.web.ts +141 -0
  213. package/src/index.tsx +3 -0
  214. package/src/index.web.tsx +41 -0
  215. package/src/publicTypes.ts +6 -5
  216. package/src/types.ts +3 -0
  217. package/src/web/browser.ts +171 -0
  218. package/src/web/index.ts +167 -0
  219. package/src/web/useWatchPosition.ts +76 -0
  220. package/src/web/watch.ts +81 -0
  221. package/src/devtools/index.test.ts +0 -54
  222. package/src/utils/errors.test.ts +0 -65
  223. package/src/utils/provider.test.ts +0 -303
@@ -0,0 +1,539 @@
1
+ import Foundation
2
+ import NitroModules
3
+
4
+ internal func makeStoredLocation(_ dictionary: [String: Any]) -> StoredBackgroundLocation? {
5
+ guard
6
+ let id = dictionary["id"] as? String,
7
+ let coordsDictionary = dictionary["coords"] as? [String: Any],
8
+ let coords = makeCoordinates(coordsDictionary),
9
+ let sourceValue = dictionary["source"] as? String,
10
+ let source = BackgroundLocationSource(fromString: sourceValue),
11
+ let recordedAt = dictionary["recordedAt"] as? Double,
12
+ let createdAt = dictionary["createdAt"] as? Double,
13
+ let timestamp = dictionary["timestamp"] as? Double
14
+ else {
15
+ return nil
16
+ }
17
+ return StoredBackgroundLocation(
18
+ id: id,
19
+ deliveredToJS: dictionary["deliveredToJS"] as? Bool ?? false,
20
+ synced: dictionary["synced"] as? Bool ?? false,
21
+ createdAt: createdAt,
22
+ source: source,
23
+ isFromBackground: dictionary["isFromBackground"] as? Bool ?? true,
24
+ provider: (dictionary["provider"] as? String).flatMap(LocationProviderUsed.init(fromString:)),
25
+ mocked: dictionary["mocked"] as? Bool,
26
+ recordedAt: recordedAt,
27
+ activity: nil,
28
+ battery: nil,
29
+ coords: coords,
30
+ timestamp: timestamp
31
+ )
32
+ }
33
+
34
+ internal func makeStoredEvent(
35
+ _ dictionary: [String: Any],
36
+ storedLocations: [StoredBackgroundLocation] = []
37
+ ) -> StoredBackgroundEventEnvelope? {
38
+ guard
39
+ let id = dictionary["id"] as? String,
40
+ let typeValue = dictionary["type"] as? String,
41
+ let type = BackgroundEventType(fromString: typeValue),
42
+ let timestamp = dictionary["timestamp"] as? Double,
43
+ let createdAt = dictionary["createdAt"] as? Double
44
+ else {
45
+ return nil
46
+ }
47
+ let persistedLocation = (dictionary["location"] as? [String: Any])
48
+ .flatMap(makeBackgroundLocation)
49
+ let referencedLocation = (dictionary["locationId"] as? String)
50
+ .flatMap { locationId in storedLocations.first { $0.id == locationId } }
51
+ .map(backgroundLocation)
52
+ let location = persistedLocation ?? referencedLocation
53
+ let geofence = (dictionary["geofence"] as? [String: Any]).flatMap(makeGeofenceEvent)
54
+ let activity = (dictionary["activity"] as? [String: Any]).flatMap(makeActivity)
55
+ let event = BackgroundEventEnvelope(
56
+ location: location,
57
+ geofence: geofence,
58
+ activity: activity,
59
+ providerStatus: nil,
60
+ result: (dictionary["result"] as? [String: Any]).flatMap(makeHttpSyncResult),
61
+ error: nil,
62
+ id: id,
63
+ type: type,
64
+ timestamp: timestamp,
65
+ deliveredToJS: dictionary["deliveredToJS"] as? Bool ?? false
66
+ )
67
+ return StoredBackgroundEventEnvelope(
68
+ event: event,
69
+ createdAt: createdAt,
70
+ id: id,
71
+ type: type,
72
+ timestamp: timestamp,
73
+ deliveredToJS: event.deliveredToJS
74
+ )
75
+ }
76
+
77
+ internal func makeBackgroundLocation(_ dictionary: [String: Any]) -> BackgroundLocation? {
78
+ guard
79
+ let id = dictionary["id"] as? String,
80
+ let coordsDictionary = dictionary["coords"] as? [String: Any],
81
+ let coords = makeCoordinates(coordsDictionary),
82
+ let sourceValue = dictionary["source"] as? String,
83
+ let source = BackgroundLocationSource(fromString: sourceValue),
84
+ let recordedAt = dictionary["recordedAt"] as? Double,
85
+ let timestamp = dictionary["timestamp"] as? Double
86
+ else {
87
+ return nil
88
+ }
89
+ return BackgroundLocation(
90
+ id: id,
91
+ source: source,
92
+ isFromBackground: dictionary["isFromBackground"] as? Bool ?? true,
93
+ provider: (dictionary["provider"] as? String).flatMap(LocationProviderUsed.init(fromString:)),
94
+ mocked: dictionary["mocked"] as? Bool,
95
+ recordedAt: recordedAt,
96
+ activity: nil,
97
+ battery: nil,
98
+ coords: coords,
99
+ timestamp: timestamp
100
+ )
101
+ }
102
+
103
+ internal func makeActivity(_ dictionary: [String: Any]) -> DetectedActivity? {
104
+ guard
105
+ let typeValue = dictionary["type"] as? String,
106
+ let type = DetectedActivityType(fromString: typeValue),
107
+ let confidence = dictionary["confidence"] as? Double,
108
+ let timestamp = dictionary["timestamp"] as? Double
109
+ else {
110
+ return nil
111
+ }
112
+ return DetectedActivity(type: type, confidence: confidence, timestamp: timestamp)
113
+ }
114
+
115
+ internal func makeCoordinates(_ dictionary: [String: Any]) -> GeolocationCoordinates? {
116
+ guard
117
+ let latitude = dictionary["latitude"] as? Double,
118
+ let longitude = dictionary["longitude"] as? Double,
119
+ let accuracy = dictionary["accuracy"] as? Double
120
+ else {
121
+ return nil
122
+ }
123
+ return GeolocationCoordinates(
124
+ latitude: latitude,
125
+ longitude: longitude,
126
+ altitude: nullableDouble(dictionary["altitude"]),
127
+ accuracy: accuracy,
128
+ altitudeAccuracy: nullableDouble(dictionary["altitudeAccuracy"]),
129
+ heading: nullableDouble(dictionary["heading"]),
130
+ speed: nullableDouble(dictionary["speed"])
131
+ )
132
+ }
133
+
134
+ internal func makeGeofenceRegion(_ dictionary: [String: Any]) -> GeofenceRegion? {
135
+ guard
136
+ let identifier = dictionary["identifier"] as? String,
137
+ let latitude = dictionary["latitude"] as? Double,
138
+ let longitude = dictionary["longitude"] as? Double,
139
+ let radius = dictionary["radius"] as? Double
140
+ else {
141
+ return nil
142
+ }
143
+ return GeofenceRegion(
144
+ identifier: identifier,
145
+ latitude: latitude,
146
+ longitude: longitude,
147
+ radius: radius,
148
+ notifyOnEntry: dictionary["notifyOnEntry"] as? Bool,
149
+ notifyOnExit: dictionary["notifyOnExit"] as? Bool,
150
+ notifyOnDwell: dictionary["notifyOnDwell"] as? Bool,
151
+ loiteringDelay: dictionary["loiteringDelay"] as? Double,
152
+ expirationDuration: dictionary["expirationDuration"] as? Double,
153
+ metadata: (dictionary["metadata"] as? [String: Any]).map(makeMetadata)
154
+ )
155
+ }
156
+
157
+ internal func sanitizedGeofence(_ region: GeofenceRegion) -> GeofenceRegion {
158
+ return GeofenceRegion(
159
+ identifier: region.identifier,
160
+ latitude: region.latitude,
161
+ longitude: region.longitude,
162
+ radius: region.radius,
163
+ notifyOnEntry: region.notifyOnEntry,
164
+ notifyOnExit: region.notifyOnExit,
165
+ notifyOnDwell: region.notifyOnDwell,
166
+ loiteringDelay: region.loiteringDelay,
167
+ expirationDuration: region.expirationDuration,
168
+ metadata: region.metadata
169
+ )
170
+ }
171
+
172
+ internal func bridgeSafeGeofence(_ region: GeofenceRegion) -> GeofenceRegion {
173
+ return GeofenceRegion(
174
+ identifier: region.identifier,
175
+ latitude: region.latitude,
176
+ longitude: region.longitude,
177
+ radius: region.radius,
178
+ notifyOnEntry: region.notifyOnEntry,
179
+ notifyOnExit: region.notifyOnExit,
180
+ notifyOnDwell: region.notifyOnDwell,
181
+ loiteringDelay: region.loiteringDelay,
182
+ expirationDuration: region.expirationDuration,
183
+ metadata: region.metadata
184
+ )
185
+ }
186
+
187
+ internal func makeGeofenceEvent(_ dictionary: [String: Any]) -> GeofenceEvent? {
188
+ guard
189
+ let regionDictionary = dictionary["region"] as? [String: Any],
190
+ let region = makeGeofenceRegion(regionDictionary),
191
+ let transitionValue = dictionary["transition"] as? String,
192
+ let transition = GeofenceTransition(fromString: transitionValue),
193
+ let timestamp = dictionary["timestamp"] as? Double
194
+ else {
195
+ return nil
196
+ }
197
+ return GeofenceEvent(
198
+ region: region,
199
+ transition: transition,
200
+ location: nil,
201
+ timestamp: timestamp
202
+ )
203
+ }
204
+
205
+ internal func storedLocationDictionary(_ location: StoredBackgroundLocation) -> [String: Any] {
206
+ var dictionary: [String: Any] = [
207
+ "id": location.id,
208
+ "deliveredToJS": location.deliveredToJS,
209
+ "synced": location.synced,
210
+ "createdAt": location.createdAt,
211
+ "source": location.source.stringValue,
212
+ "isFromBackground": location.isFromBackground,
213
+ "recordedAt": location.recordedAt,
214
+ "coords": coordinatesDictionary(location.coords),
215
+ "timestamp": location.timestamp
216
+ ]
217
+ if let provider = location.provider {
218
+ dictionary["provider"] = provider.stringValue
219
+ }
220
+ if let mocked = location.mocked {
221
+ dictionary["mocked"] = mocked
222
+ }
223
+ return dictionary
224
+ }
225
+
226
+ internal func storedEventDictionary(_ event: StoredBackgroundEventEnvelope) -> [String: Any] {
227
+ var dictionary: [String: Any] = [
228
+ "id": event.id,
229
+ "type": event.type.stringValue,
230
+ "timestamp": event.timestamp,
231
+ "deliveredToJS": event.deliveredToJS,
232
+ "createdAt": event.createdAt
233
+ ]
234
+ if let locationId = event.event.location?.id {
235
+ dictionary["locationId"] = locationId
236
+ }
237
+ if let location = event.event.location {
238
+ dictionary["location"] = backgroundLocationDictionary(location)
239
+ }
240
+ if let geofence = event.event.geofence {
241
+ dictionary["geofence"] = geofenceDictionary(geofence)
242
+ }
243
+ if let activity = event.event.activity {
244
+ dictionary["activity"] = activityDictionary(activity)
245
+ }
246
+ if let result = event.event.result {
247
+ dictionary["result"] = httpSyncResultDictionary(result)
248
+ }
249
+ return dictionary
250
+ }
251
+
252
+ internal func backgroundLocationDictionary(_ location: BackgroundLocation) -> [String: Any]? {
253
+ guard let id = location.id else {
254
+ return nil
255
+ }
256
+ var dictionary: [String: Any] = [
257
+ "id": id,
258
+ "source": location.source.stringValue,
259
+ "isFromBackground": location.isFromBackground,
260
+ "recordedAt": location.recordedAt,
261
+ "coords": coordinatesDictionary(location.coords),
262
+ "timestamp": location.timestamp
263
+ ]
264
+ if let provider = location.provider {
265
+ dictionary["provider"] = provider.stringValue
266
+ }
267
+ if let mocked = location.mocked {
268
+ dictionary["mocked"] = mocked
269
+ }
270
+ return dictionary
271
+ }
272
+
273
+ internal func coordinatesDictionary(_ coords: GeolocationCoordinates) -> [String: Any] {
274
+ var dictionary: [String: Any] = [
275
+ "latitude": coords.latitude,
276
+ "longitude": coords.longitude,
277
+ "accuracy": coords.accuracy
278
+ ]
279
+ dictionary["altitude"] = variantDouble(coords.altitude)
280
+ dictionary["altitudeAccuracy"] = variantDouble(coords.altitudeAccuracy)
281
+ dictionary["heading"] = variantDouble(coords.heading)
282
+ dictionary["speed"] = variantDouble(coords.speed)
283
+ return dictionary
284
+ }
285
+
286
+ internal func geofenceDictionary(_ region: GeofenceRegion) -> [String: Any] {
287
+ var dictionary: [String: Any] = [
288
+ "identifier": region.identifier,
289
+ "latitude": region.latitude,
290
+ "longitude": region.longitude,
291
+ "radius": region.radius
292
+ ]
293
+ dictionary["notifyOnEntry"] = region.notifyOnEntry
294
+ dictionary["notifyOnExit"] = region.notifyOnExit
295
+ dictionary["notifyOnDwell"] = region.notifyOnDwell
296
+ dictionary["loiteringDelay"] = region.loiteringDelay
297
+ dictionary["expirationDuration"] = region.expirationDuration
298
+ dictionary["metadata"] = region.metadata.map(metadataDictionary)
299
+ return dictionary
300
+ }
301
+
302
+ internal func geofenceDictionary(_ event: GeofenceEvent) -> [String: Any] {
303
+ return [
304
+ "region": geofenceDictionary(event.region),
305
+ "transition": event.transition.stringValue,
306
+ "timestamp": event.timestamp
307
+ ]
308
+ }
309
+
310
+ internal func activityDictionary(_ activity: DetectedActivity) -> [String: Any] {
311
+ return [
312
+ "type": activity.type.stringValue,
313
+ "confidence": activity.confidence,
314
+ "timestamp": activity.timestamp
315
+ ]
316
+ }
317
+
318
+ internal func makeHttpSyncResult(_ dictionary: [String: Any]) -> BackgroundHttpSyncResult? {
319
+ guard let success = dictionary["success"] as? Bool else {
320
+ return nil
321
+ }
322
+ return BackgroundHttpSyncResult(
323
+ success: success,
324
+ statusCode: dictionary["statusCode"] as? Double,
325
+ syncedLocationIds: dictionary["syncedLocationIds"] as? [String] ?? [],
326
+ failedLocationIds: dictionary["failedLocationIds"] as? [String] ?? [],
327
+ error: dictionary["error"] as? String
328
+ )
329
+ }
330
+
331
+ internal func httpSyncResultDictionary(_ result: BackgroundHttpSyncResult) -> [String: Any] {
332
+ var dictionary: [String: Any] = [
333
+ "success": result.success,
334
+ "syncedLocationIds": result.syncedLocationIds,
335
+ "failedLocationIds": result.failedLocationIds
336
+ ]
337
+ dictionary["statusCode"] = result.statusCode
338
+ dictionary["error"] = result.error
339
+ return dictionary
340
+ }
341
+
342
+ internal func backgroundOptionsDictionary(_ options: BackgroundLocationOptions) -> [String: Any] {
343
+ var dictionary: [String: Any] = [:]
344
+ dictionary["trackingMode"] = options.trackingMode?.stringValue
345
+ dictionary["interval"] = options.interval
346
+ dictionary["fastestInterval"] = options.fastestInterval
347
+ dictionary["distanceFilter"] = options.distanceFilter
348
+ dictionary["maxUpdateDelay"] = options.maxUpdateDelay
349
+ dictionary["waitForAccurateLocation"] = options.waitForAccurateLocation
350
+ dictionary["persist"] = options.persist
351
+ dictionary["maxStoredLocations"] = options.maxStoredLocations
352
+ dictionary["maxStoredEvents"] = options.maxStoredEvents
353
+ dictionary["stopOnTerminate"] = options.stopOnTerminate
354
+ dictionary["startOnBoot"] = options.startOnBoot
355
+ dictionary["ios"] = options.ios.map(iosOptionsDictionary)
356
+ dictionary["activityRecognition"] = options.activityRecognition.map(activityOptionsDictionary)
357
+ dictionary["sync"] = options.sync.map(httpSyncOptionsDictionary)
358
+ return dictionary
359
+ }
360
+
361
+ internal func makeBackgroundOptions(_ dictionary: [String: Any]) -> BackgroundLocationOptions {
362
+ return BackgroundLocationOptions(
363
+ trackingMode: (dictionary["trackingMode"] as? String).flatMap(BackgroundTrackingMode.init(fromString:)),
364
+ accuracy: nil,
365
+ granularity: nil,
366
+ interval: dictionary["interval"] as? Double,
367
+ fastestInterval: dictionary["fastestInterval"] as? Double,
368
+ distanceFilter: dictionary["distanceFilter"] as? Double,
369
+ maxUpdateDelay: dictionary["maxUpdateDelay"] as? Double,
370
+ waitForAccurateLocation: dictionary["waitForAccurateLocation"] as? Bool,
371
+ persist: dictionary["persist"] as? Bool,
372
+ maxStoredLocations: dictionary["maxStoredLocations"] as? Double,
373
+ maxStoredEvents: dictionary["maxStoredEvents"] as? Double,
374
+ stopOnTerminate: dictionary["stopOnTerminate"] as? Bool,
375
+ startOnBoot: dictionary["startOnBoot"] as? Bool,
376
+ android: nil,
377
+ ios: (dictionary["ios"] as? [String: Any]).map(makeIOSOptions),
378
+ geofencing: nil,
379
+ activityRecognition: (dictionary["activityRecognition"] as? [String: Any]).map(makeActivityOptions),
380
+ sync: (dictionary["sync"] as? [String: Any]).flatMap(makeHttpSyncOptions)
381
+ )
382
+ }
383
+
384
+ internal func iosOptionsDictionary(_ options: IOSBackgroundLocationOptions) -> [String: Any] {
385
+ var dictionary: [String: Any] = [:]
386
+ dictionary["activityType"] = options.activityType?.stringValue
387
+ dictionary["pausesLocationUpdatesAutomatically"] = options.pausesLocationUpdatesAutomatically
388
+ dictionary["showsBackgroundLocationIndicator"] = options.showsBackgroundLocationIndicator
389
+ dictionary["useSignificantChanges"] = options.useSignificantChanges
390
+ dictionary["deferredUpdatesDistance"] = options.deferredUpdatesDistance
391
+ dictionary["deferredUpdatesInterval"] = options.deferredUpdatesInterval
392
+ return dictionary
393
+ }
394
+
395
+ internal func makeIOSOptions(_ dictionary: [String: Any]) -> IOSBackgroundLocationOptions {
396
+ return IOSBackgroundLocationOptions(
397
+ activityType: (dictionary["activityType"] as? String).flatMap(IOSBackgroundActivityType.init(fromString:)),
398
+ pausesLocationUpdatesAutomatically: dictionary["pausesLocationUpdatesAutomatically"] as? Bool,
399
+ showsBackgroundLocationIndicator: dictionary["showsBackgroundLocationIndicator"] as? Bool,
400
+ useSignificantChanges: dictionary["useSignificantChanges"] as? Bool,
401
+ deferredUpdatesDistance: dictionary["deferredUpdatesDistance"] as? Double,
402
+ deferredUpdatesInterval: dictionary["deferredUpdatesInterval"] as? Double
403
+ )
404
+ }
405
+
406
+ internal func activityOptionsDictionary(_ options: ActivityRecognitionOptions) -> [String: Any] {
407
+ var dictionary: [String: Any] = [:]
408
+ dictionary["enabled"] = options.enabled
409
+ dictionary["interval"] = options.interval
410
+ dictionary["stopOnStill"] = options.stopOnStill
411
+ dictionary["minimumConfidence"] = options.minimumConfidence
412
+ return dictionary
413
+ }
414
+
415
+ internal func makeActivityOptions(_ dictionary: [String: Any]) -> ActivityRecognitionOptions {
416
+ return ActivityRecognitionOptions(
417
+ enabled: dictionary["enabled"] as? Bool,
418
+ interval: dictionary["interval"] as? Double,
419
+ stopOnStill: dictionary["stopOnStill"] as? Bool,
420
+ minimumConfidence: dictionary["minimumConfidence"] as? Double
421
+ )
422
+ }
423
+
424
+ internal func httpSyncOptionsDictionary(_ options: BackgroundHttpSyncOptions) -> [String: Any] {
425
+ var dictionary: [String: Any] = [
426
+ "url": options.url
427
+ ]
428
+ dictionary["method"] = options.method?.stringValue
429
+ dictionary["headers"] = options.headers
430
+ dictionary["batch"] = options.batch
431
+ dictionary["batchSize"] = options.batchSize
432
+ dictionary["syncThreshold"] = options.syncThreshold
433
+ dictionary["syncInterval"] = options.syncInterval
434
+ dictionary["retry"] = options.retry
435
+ dictionary["maxRetries"] = options.maxRetries
436
+ dictionary["bodyTemplate"] = options.bodyTemplate.map(metadataDictionary)
437
+ dictionary["autoClear"] = options.autoClear
438
+ return dictionary
439
+ }
440
+
441
+ internal func makeHttpSyncOptions(_ dictionary: [String: Any]) -> BackgroundHttpSyncOptions? {
442
+ guard let url = dictionary["url"] as? String else {
443
+ return nil
444
+ }
445
+ return BackgroundHttpSyncOptions(
446
+ url: url,
447
+ method: (dictionary["method"] as? String).flatMap(BackgroundHttpMethod.init(fromString:)),
448
+ headers: dictionary["headers"] as? [String: String],
449
+ batch: dictionary["batch"] as? Bool,
450
+ batchSize: dictionary["batchSize"] as? Double,
451
+ syncThreshold: dictionary["syncThreshold"] as? Double,
452
+ syncInterval: dictionary["syncInterval"] as? Double,
453
+ retry: dictionary["retry"] as? Bool,
454
+ maxRetries: dictionary["maxRetries"] as? Double,
455
+ bodyTemplate: (dictionary["bodyTemplate"] as? [String: Any]).map(makeMetadata),
456
+ autoClear: dictionary["autoClear"] as? Bool
457
+ )
458
+ }
459
+
460
+ internal func backgroundLocation(_ location: StoredBackgroundLocation) -> BackgroundLocation {
461
+ return BackgroundLocation(
462
+ id: location.id,
463
+ source: location.source,
464
+ isFromBackground: location.isFromBackground,
465
+ provider: location.provider,
466
+ mocked: location.mocked,
467
+ recordedAt: location.recordedAt,
468
+ activity: location.activity,
469
+ battery: location.battery,
470
+ coords: location.coords,
471
+ timestamp: location.timestamp
472
+ )
473
+ }
474
+
475
+ internal func nullableDouble(_ value: Any?) -> NullableDouble? {
476
+ guard let value = value as? Double else { return nil }
477
+ return .second(value)
478
+ }
479
+
480
+ internal func variantDouble(_ value: NullableDouble?) -> Double? {
481
+ return value?.asType(Double.self)
482
+ }
483
+
484
+ internal func metadataDictionary(
485
+ _ metadata: [String: Variant_NullType_Bool_String_Double]
486
+ ) -> [String: Any] {
487
+ var dictionary: [String: Any] = [:]
488
+ metadata.forEach { key, value in
489
+ switch value {
490
+ case .first:
491
+ dictionary[key] = ["__nitroNull": true]
492
+ case .second(let bool):
493
+ dictionary[key] = bool
494
+ case .third(let string):
495
+ dictionary[key] = string
496
+ case .fourth(let double):
497
+ dictionary[key] = double
498
+ }
499
+ }
500
+ return dictionary
501
+ }
502
+
503
+ internal func bodyTemplateDictionary(
504
+ _ metadata: [String: Variant_NullType_Bool_String_Double]
505
+ ) -> [String: Any] {
506
+ var dictionary: [String: Any] = [:]
507
+ metadata.forEach { key, value in
508
+ switch value {
509
+ case .first:
510
+ dictionary[key] = NSNull()
511
+ case .second(let bool):
512
+ dictionary[key] = bool
513
+ case .third(let string):
514
+ dictionary[key] = string
515
+ case .fourth(let double):
516
+ dictionary[key] = double
517
+ }
518
+ }
519
+ return dictionary
520
+ }
521
+
522
+ internal func makeMetadata(_ dictionary: [String: Any]) -> [String: Variant_NullType_Bool_String_Double] {
523
+ var metadata: [String: Variant_NullType_Bool_String_Double] = [:]
524
+ dictionary.forEach { key, value in
525
+ switch value {
526
+ case let nullMarker as [String: Any] where nullMarker["__nitroNull"] as? Bool == true:
527
+ metadata[key] = .first(NullType.null)
528
+ case let bool as Bool:
529
+ metadata[key] = .second(bool)
530
+ case let string as String:
531
+ metadata[key] = .third(string)
532
+ case let number as NSNumber:
533
+ metadata[key] = .fourth(number.doubleValue)
534
+ default:
535
+ metadata[key] = .third(String(describing: value))
536
+ }
537
+ }
538
+ return metadata
539
+ }
@@ -0,0 +1,131 @@
1
+ import CoreLocation
2
+ import Foundation
3
+
4
+ func headingToResponse(_ clHeading: CLHeading) -> Heading {
5
+ let trueHeading = clHeading.trueHeading >= 0
6
+ ? clHeading.trueHeading
7
+ : nil
8
+ let accuracy = clHeading.headingAccuracy >= 0
9
+ ? clHeading.headingAccuracy
10
+ : nil
11
+
12
+ return Heading(
13
+ magneticHeading: normalizeHeading(clHeading.magneticHeading),
14
+ trueHeading: trueHeading.map(normalizeHeading),
15
+ accuracy: accuracy,
16
+ timestamp: clHeading.timestamp.timeIntervalSince1970 * 1000
17
+ )
18
+ }
19
+
20
+ func angularDistance(_ first: Double, _ second: Double) -> Double {
21
+ let distance = Swift.abs(first - second).truncatingRemainder(dividingBy: 360)
22
+ return distance > 180 ? 360 - distance : distance
23
+ }
24
+
25
+ func normalizeHeading(_ value: Double) -> Double {
26
+ let normalized = value.truncatingRemainder(dividingBy: 360)
27
+ return normalized < 0 ? normalized + 360 : normalized
28
+ }
29
+
30
+ extension CLLocation {
31
+ func toGeolocationResponse() -> GeolocationResponse {
32
+ let coords = GeolocationCoordinates(
33
+ latitude: coordinate.latitude,
34
+ longitude: coordinate.longitude,
35
+ altitude: nitroGeolocationAltitude,
36
+ accuracy: horizontalAccuracy,
37
+ altitudeAccuracy: nitroGeolocationAltitudeAccuracy,
38
+ heading: nitroGeolocationHeading,
39
+ speed: nitroGeolocationSpeed
40
+ )
41
+
42
+ return GeolocationResponse(
43
+ coords: coords,
44
+ timestamp: timestamp.timeIntervalSince1970 * 1000,
45
+ mocked: nitroGeolocationMocked,
46
+ provider: nitroGeolocationProvider
47
+ )
48
+ }
49
+ }
50
+
51
+ extension CLPlacemark {
52
+ func toGeocodedLocation() -> GeocodedLocation? {
53
+ guard let location else {
54
+ return nil
55
+ }
56
+
57
+ let accuracy = location.horizontalAccuracy >= 0
58
+ ? location.horizontalAccuracy
59
+ : nil
60
+
61
+ return GeocodedLocation(
62
+ latitude: location.coordinate.latitude,
63
+ longitude: location.coordinate.longitude,
64
+ accuracy: accuracy
65
+ )
66
+ }
67
+
68
+ func toReverseGeocodedAddress() -> ReverseGeocodedAddress {
69
+ return ReverseGeocodedAddress(
70
+ country: country.nonEmptyTrimmed,
71
+ region: administrativeArea.nonEmptyTrimmed,
72
+ city: locality.nonEmptyTrimmed,
73
+ district: subLocality.nonEmptyTrimmed,
74
+ street: formatStreet(),
75
+ postalCode: postalCode.nonEmptyTrimmed,
76
+ formattedAddress: formatAddress()
77
+ )
78
+ }
79
+
80
+ func formatStreet() -> String? {
81
+ return [
82
+ subThoroughfare.nonEmptyTrimmed,
83
+ thoroughfare.nonEmptyTrimmed
84
+ ]
85
+ .compactMap { $0 }
86
+ .joined(separator: " ")
87
+ .nonEmptyTrimmed
88
+ }
89
+
90
+ func formatAddress() -> String? {
91
+ var parts: [String] = []
92
+
93
+ appendDistinct(name.nonEmptyTrimmed, to: &parts)
94
+ appendDistinct(formatStreet(), to: &parts)
95
+ appendDistinct(subLocality.nonEmptyTrimmed, to: &parts)
96
+ appendDistinct(locality.nonEmptyTrimmed, to: &parts)
97
+ appendDistinct(administrativeArea.nonEmptyTrimmed, to: &parts)
98
+ appendDistinct(postalCode.nonEmptyTrimmed, to: &parts)
99
+ appendDistinct(country.nonEmptyTrimmed, to: &parts)
100
+
101
+ return parts.joined(separator: ", ").nonEmptyTrimmed
102
+ }
103
+
104
+ private func appendDistinct(_ value: String?, to parts: inout [String]) {
105
+ guard let value, !parts.contains(value) else {
106
+ return
107
+ }
108
+
109
+ parts.append(value)
110
+ }
111
+ }
112
+
113
+ extension Optional where Wrapped == String {
114
+ var nonEmptyTrimmed: String? {
115
+ guard let trimmed = self?.trimmingCharacters(in: .whitespacesAndNewlines) else {
116
+ return nil
117
+ }
118
+
119
+ return trimmed.isEmpty ? nil : trimmed
120
+ }
121
+ }
122
+
123
+ extension String {
124
+ var nonEmptyTrimmed: String? {
125
+ return trimmingCharacters(in: .whitespacesAndNewlines).nilIfEmpty
126
+ }
127
+
128
+ var nilIfEmpty: String? {
129
+ return isEmpty ? nil : self
130
+ }
131
+ }
@@ -0,0 +1,31 @@
1
+ import CoreLocation
2
+ import Foundation
3
+
4
+ final class LocationManagerDelegate: NSObject, CLLocationManagerDelegate {
5
+ weak var geolocation: NitroGeolocation?
6
+
7
+ init(geolocation: NitroGeolocation) {
8
+ self.geolocation = geolocation
9
+ super.init()
10
+ }
11
+
12
+ func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) {
13
+ geolocation?.handleAuthorizationChange(manager)
14
+ }
15
+
16
+ func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
17
+ geolocation?.handleLocationUpdate(locations)
18
+ }
19
+
20
+ func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
21
+ geolocation?.handleLocationError(error)
22
+ }
23
+
24
+ func locationManager(_ manager: CLLocationManager, didUpdateHeading newHeading: CLHeading) {
25
+ geolocation?.handleHeadingUpdate(newHeading)
26
+ }
27
+
28
+ func locationManagerShouldDisplayHeadingCalibration(_ manager: CLLocationManager) -> Bool {
29
+ return false
30
+ }
31
+ }