react-native-nitro-geolocation 0.1.1 → 0.2.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 (128) hide show
  1. package/android/src/main/java/com/margelo/nitro/nitrogeolocation/GetCurrentPosition.kt +4 -4
  2. package/android/src/main/java/com/margelo/nitro/nitrogeolocation/NitroGeolocation.kt +642 -50
  3. package/android/src/main/java/com/margelo/nitro/nitrogeolocation/NitroGeolocationCompat.kt +81 -0
  4. package/android/src/main/java/com/margelo/nitro/nitrogeolocation/WatchPosition.kt +4 -4
  5. package/ios/LocationManager.swift +113 -128
  6. package/ios/NitroGeolocation.swift +546 -61
  7. package/ios/NitroGeolocationCompat.swift +109 -0
  8. package/nitrogen/generated/android/c++/JAuthorizationLevel.hpp +61 -0
  9. package/nitrogen/generated/android/c++/JAuthorizationLevelInternal.hpp +3 -4
  10. package/nitrogen/generated/android/c++/JFunc_void.hpp +2 -1
  11. package/nitrogen/generated/android/c++/JFunc_void_GeolocationError.hpp +2 -1
  12. package/nitrogen/generated/android/c++/JFunc_void_GeolocationResponse.hpp +6 -1
  13. package/nitrogen/generated/android/c++/JFunc_void_LocationError.hpp +78 -0
  14. package/nitrogen/generated/android/c++/JGeolocationCoordinates.hpp +25 -17
  15. package/nitrogen/generated/android/c++/JGeolocationError.hpp +5 -1
  16. package/nitrogen/generated/android/c++/JGeolocationOptions.hpp +5 -1
  17. package/nitrogen/generated/android/c++/JGeolocationResponse.hpp +9 -1
  18. package/nitrogen/generated/android/c++/JHybridNitroGeolocationCompatSpec.cpp +109 -0
  19. package/nitrogen/generated/android/c++/JHybridNitroGeolocationCompatSpec.hpp +70 -0
  20. package/nitrogen/generated/android/c++/JHybridNitroGeolocationSpec.cpp +98 -42
  21. package/nitrogen/generated/android/c++/JHybridNitroGeolocationSpec.hpp +7 -5
  22. package/nitrogen/generated/android/c++/JLocationError.hpp +61 -0
  23. package/nitrogen/generated/android/c++/JLocationProvider.hpp +61 -0
  24. package/nitrogen/generated/android/c++/JLocationProviderInternal.hpp +3 -4
  25. package/nitrogen/generated/android/c++/JLocationRequestOptions.hpp +81 -0
  26. package/nitrogen/generated/android/c++/JModernGeolocationConfiguration.hpp +73 -0
  27. package/nitrogen/generated/android/c++/JNullableDouble.cpp +26 -0
  28. package/nitrogen/generated/android/c++/JNullableDouble.hpp +69 -0
  29. package/nitrogen/generated/android/c++/JPermissionStatus.hpp +64 -0
  30. package/nitrogen/generated/android/c++/JRNConfigurationInternal.hpp +5 -1
  31. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/AuthorizationLevel.kt +24 -0
  32. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/AuthorizationLevelInternal.kt +2 -0
  33. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/Func_void.kt +0 -1
  34. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/Func_void_GeolocationError.kt +0 -1
  35. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/Func_void_GeolocationResponse.kt +0 -1
  36. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/Func_void_LocationError.kt +80 -0
  37. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/GeolocationCoordinates.kt +34 -25
  38. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/GeolocationError.kt +27 -18
  39. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/GeolocationOptions.kt +33 -24
  40. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/GeolocationResponse.kt +18 -9
  41. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/HybridNitroGeolocationCompatSpec.kt +92 -0
  42. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/HybridNitroGeolocationSpec.kt +17 -17
  43. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/LocationError.kt +41 -0
  44. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/LocationProvider.kt +24 -0
  45. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/LocationProviderInternal.kt +2 -0
  46. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/LocationRequestOptions.kt +56 -0
  47. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/ModernGeolocationConfiguration.kt +47 -0
  48. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/NullableDouble.kt +59 -0
  49. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/PermissionStatus.kt +25 -0
  50. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/RNConfigurationInternal.kt +24 -15
  51. package/nitrogen/generated/android/nitrogeolocation+autolinking.cmake +3 -0
  52. package/nitrogen/generated/android/nitrogeolocationOnLoad.cpp +14 -2
  53. package/nitrogen/generated/ios/NitroGeolocation+autolinking.rb +1 -1
  54. package/nitrogen/generated/ios/NitroGeolocation-Swift-Cxx-Bridge.cpp +55 -13
  55. package/nitrogen/generated/ios/NitroGeolocation-Swift-Cxx-Bridge.hpp +325 -68
  56. package/nitrogen/generated/ios/NitroGeolocation-Swift-Cxx-Umbrella.hpp +26 -0
  57. package/nitrogen/generated/ios/NitroGeolocationAutolinking.mm +8 -0
  58. package/nitrogen/generated/ios/NitroGeolocationAutolinking.swift +15 -0
  59. package/nitrogen/generated/ios/c++/HybridNitroGeolocationCompatSpecSwift.cpp +11 -0
  60. package/nitrogen/generated/ios/c++/HybridNitroGeolocationCompatSpecSwift.hpp +130 -0
  61. package/nitrogen/generated/ios/c++/HybridNitroGeolocationSpecSwift.hpp +47 -26
  62. package/nitrogen/generated/ios/swift/AuthorizationLevel.swift +44 -0
  63. package/nitrogen/generated/ios/swift/Func_void.swift +1 -1
  64. package/nitrogen/generated/ios/swift/Func_void_GeolocationError.swift +1 -1
  65. package/nitrogen/generated/ios/swift/Func_void_GeolocationResponse.swift +1 -1
  66. package/nitrogen/generated/ios/swift/Func_void_LocationError.swift +47 -0
  67. package/nitrogen/generated/ios/swift/Func_void_PermissionStatus.swift +47 -0
  68. package/nitrogen/generated/ios/swift/Func_void_std__exception_ptr.swift +47 -0
  69. package/nitrogen/generated/ios/swift/GeolocationCoordinates.swift +132 -93
  70. package/nitrogen/generated/ios/swift/GeolocationError.swift +11 -40
  71. package/nitrogen/generated/ios/swift/GeolocationOptions.swift +29 -98
  72. package/nitrogen/generated/ios/swift/GeolocationResponse.swift +5 -16
  73. package/nitrogen/generated/ios/swift/HybridNitroGeolocationCompatSpec.swift +61 -0
  74. package/nitrogen/generated/ios/swift/HybridNitroGeolocationCompatSpec_cxx.swift +244 -0
  75. package/nitrogen/generated/ios/swift/HybridNitroGeolocationSpec.swift +13 -5
  76. package/nitrogen/generated/ios/swift/HybridNitroGeolocationSpec_cxx.swift +66 -64
  77. package/nitrogen/generated/ios/swift/LocationError.swift +35 -0
  78. package/nitrogen/generated/ios/swift/LocationProvider.swift +44 -0
  79. package/nitrogen/generated/ios/swift/LocationRequestOptions.swift +116 -0
  80. package/nitrogen/generated/ios/swift/ModernGeolocationConfiguration.swift +83 -0
  81. package/nitrogen/generated/ios/swift/NullableDouble.swift +18 -0
  82. package/nitrogen/generated/ios/swift/PermissionStatus.swift +48 -0
  83. package/nitrogen/generated/ios/swift/RNConfigurationInternal.swift +16 -50
  84. package/nitrogen/generated/shared/c++/AuthorizationLevel.hpp +80 -0
  85. package/nitrogen/generated/shared/c++/GeolocationCoordinates.hpp +45 -27
  86. package/nitrogen/generated/shared/c++/GeolocationError.hpp +32 -16
  87. package/nitrogen/generated/shared/c++/GeolocationOptions.hpp +38 -22
  88. package/nitrogen/generated/shared/c++/GeolocationResponse.hpp +23 -7
  89. package/nitrogen/generated/shared/c++/HybridNitroGeolocationCompatSpec.cpp +26 -0
  90. package/nitrogen/generated/shared/c++/HybridNitroGeolocationCompatSpec.hpp +79 -0
  91. package/nitrogen/generated/shared/c++/HybridNitroGeolocationSpec.cpp +4 -3
  92. package/nitrogen/generated/shared/c++/HybridNitroGeolocationSpec.hpp +22 -16
  93. package/nitrogen/generated/shared/c++/LocationError.hpp +87 -0
  94. package/nitrogen/generated/shared/c++/LocationProvider.hpp +80 -0
  95. package/nitrogen/generated/shared/c++/LocationRequestOptions.hpp +107 -0
  96. package/nitrogen/generated/shared/c++/ModernGeolocationConfiguration.hpp +100 -0
  97. package/nitrogen/generated/shared/c++/PermissionStatus.hpp +84 -0
  98. package/nitrogen/generated/shared/c++/RNConfigurationInternal.hpp +29 -13
  99. package/package.json +16 -7
  100. package/src/GeolocationClient.ts +116 -0
  101. package/src/NitroGeolocation.nitro.ts +177 -30
  102. package/src/NitroGeolocationCompat.nitro.ts +41 -0
  103. package/src/NitroGeolocationModule.ts +6 -0
  104. package/src/compat/clearWatch.ts +9 -0
  105. package/src/{getCurrentPosition.ts → compat/getCurrentPosition.ts} +7 -3
  106. package/src/compat/index.tsx +34 -0
  107. package/src/compat/requestAuthorization.ts +9 -0
  108. package/src/{setRNConfiguration.ts → compat/setRNConfiguration.ts} +6 -4
  109. package/src/{stopObserving.ts → compat/stopObserving.ts} +4 -2
  110. package/src/{watchPosition.ts → compat/watchPosition.ts} +7 -6
  111. package/src/components/GeolocationProvider.tsx +91 -0
  112. package/src/components/index.ts +13 -0
  113. package/src/hooks/index.ts +9 -0
  114. package/src/hooks/useCheckPermission.ts +46 -0
  115. package/src/hooks/useGetCurrentPosition.ts +44 -0
  116. package/src/hooks/useRequestPermission.ts +38 -0
  117. package/src/hooks/useWatchPosition.ts +127 -0
  118. package/src/index.tsx +72 -27
  119. package/src/types.ts +32 -4
  120. package/src/utils/cache.ts +25 -0
  121. package/src/utils/config.ts +93 -0
  122. package/src/utils/errors.ts +82 -0
  123. package/src/utils/index.ts +27 -0
  124. package/src/utils/provider.ts +61 -0
  125. package/src/utils/quality.ts +98 -0
  126. package/README.md +0 -318
  127. package/src/clearWatch.ts +0 -13
  128. package/src/requestAuthorization.ts +0 -9
@@ -0,0 +1,93 @@
1
+ /**
2
+ * Represents a location request with its configuration options.
3
+ */
4
+ export interface LocationRequest {
5
+ /** Whether high accuracy mode is enabled */
6
+ enableHighAccuracy: boolean;
7
+ /** Minimum distance change (in meters) for updates */
8
+ distanceFilter: number;
9
+ }
10
+
11
+ /**
12
+ * Accuracy level for location services.
13
+ * - 'high': GPS-level accuracy (~5-10 meters)
14
+ * - 'medium': Network-assisted accuracy (~100 meters)
15
+ * - 'low': Cell tower accuracy (~1000+ meters)
16
+ */
17
+ export type AccuracyLevel = "high" | "medium" | "low";
18
+
19
+ /**
20
+ * Merged configuration representing the optimal settings
21
+ * for multiple concurrent location requests.
22
+ */
23
+ export interface MergedConfiguration {
24
+ /** The best (highest) accuracy level among all requests */
25
+ bestAccuracy: AccuracyLevel;
26
+ /** The smallest (most sensitive) distance filter among all requests */
27
+ smallestDistanceFilter: number;
28
+ }
29
+
30
+ /**
31
+ * Merges multiple location request configurations to determine
32
+ * the optimal settings that satisfy all requests.
33
+ *
34
+ * This is important for battery optimization - when multiple watches
35
+ * or getCurrentPosition calls are active simultaneously, we should use
36
+ * the most demanding settings to satisfy all requests with a single
37
+ * location subscription.
38
+ *
39
+ * Strategy:
40
+ * - Use the highest accuracy level requested by any client
41
+ * - Use the smallest distance filter to ensure all clients get updates
42
+ *
43
+ * @param requests - Array of location requests to merge
44
+ * @returns Merged configuration with optimal settings
45
+ *
46
+ * @example
47
+ * ```ts
48
+ * const requests = [
49
+ * { enableHighAccuracy: false, distanceFilter: 100 },
50
+ * { enableHighAccuracy: true, distanceFilter: 10 },
51
+ * { enableHighAccuracy: false, distanceFilter: 50 }
52
+ * ];
53
+ *
54
+ * const merged = mergeConfigurations(requests);
55
+ * // Result: { bestAccuracy: 'high', smallestDistanceFilter: 10 }
56
+ * ```
57
+ */
58
+ export function mergeConfigurations(
59
+ requests: LocationRequest[]
60
+ ): MergedConfiguration {
61
+ // If no requests, return default low-power settings
62
+ if (requests.length === 0) {
63
+ return {
64
+ bestAccuracy: "low",
65
+ smallestDistanceFilter: 0
66
+ };
67
+ }
68
+
69
+ let bestAccuracy: AccuracyLevel = "low";
70
+ let smallestDistanceFilter = Number.POSITIVE_INFINITY;
71
+
72
+ // Iterate through all requests to find the most demanding settings
73
+ for (const request of requests) {
74
+ // If any request needs high accuracy, use high accuracy
75
+ if (request.enableHighAccuracy) {
76
+ bestAccuracy = "high";
77
+ }
78
+
79
+ // Use the smallest distance filter
80
+ smallestDistanceFilter = Math.min(
81
+ smallestDistanceFilter,
82
+ request.distanceFilter
83
+ );
84
+ }
85
+
86
+ return {
87
+ bestAccuracy,
88
+ smallestDistanceFilter:
89
+ smallestDistanceFilter === Number.POSITIVE_INFINITY
90
+ ? 0
91
+ : smallestDistanceFilter
92
+ };
93
+ }
@@ -0,0 +1,82 @@
1
+ /**
2
+ * Error codes for geolocation errors.
3
+ * These codes match the W3C Geolocation API specification.
4
+ */
5
+ export enum LocationErrorCode {
6
+ /** User denied the request for Geolocation */
7
+ PERMISSION_DENIED = 1,
8
+ /** Location provider is unavailable */
9
+ POSITION_UNAVAILABLE = 2,
10
+ /** The request to get location timed out */
11
+ TIMEOUT = 3
12
+ }
13
+
14
+ /**
15
+ * Geolocation error object.
16
+ */
17
+ export interface LocationError extends Error {
18
+ code: LocationErrorCode;
19
+ message: string;
20
+ PERMISSION_DENIED: LocationErrorCode.PERMISSION_DENIED;
21
+ POSITION_UNAVAILABLE: LocationErrorCode.POSITION_UNAVAILABLE;
22
+ TIMEOUT: LocationErrorCode.TIMEOUT;
23
+ }
24
+
25
+ /**
26
+ * Creates a standardized LocationError object.
27
+ *
28
+ * @param code - The error code from LocationErrorCode enum
29
+ * @param message - A human-readable error message
30
+ * @returns A LocationError object
31
+ *
32
+ * @example
33
+ * ```ts
34
+ * const error = createLocationError(
35
+ * LocationErrorCode.PERMISSION_DENIED,
36
+ * 'User denied location permission'
37
+ * );
38
+ * ```
39
+ */
40
+ export function createLocationError(
41
+ code: LocationErrorCode,
42
+ message: string
43
+ ): LocationError {
44
+ const error = new Error(message) as LocationError;
45
+ error.code = code;
46
+ error.PERMISSION_DENIED = LocationErrorCode.PERMISSION_DENIED;
47
+ error.POSITION_UNAVAILABLE = LocationErrorCode.POSITION_UNAVAILABLE;
48
+ error.TIMEOUT = LocationErrorCode.TIMEOUT;
49
+ return error;
50
+ }
51
+
52
+ /**
53
+ * Maps iOS CLError codes to LocationErrorCode.
54
+ *
55
+ * @param clErrorCode - The iOS CLError code
56
+ * @returns The corresponding LocationErrorCode
57
+ *
58
+ * @see https://developer.apple.com/documentation/corelocation/clerror/code
59
+ */
60
+ export function mapCLErrorCode(clErrorCode: number): LocationErrorCode {
61
+ switch (clErrorCode) {
62
+ case 0: // kCLErrorDenied
63
+ return LocationErrorCode.PERMISSION_DENIED;
64
+ case 1: // kCLErrorLocationUnknown
65
+ return LocationErrorCode.POSITION_UNAVAILABLE;
66
+ default:
67
+ return LocationErrorCode.POSITION_UNAVAILABLE;
68
+ }
69
+ }
70
+
71
+ /**
72
+ * Maps Android exception types to LocationErrorCode.
73
+ *
74
+ * @param exceptionType - The Android exception class name
75
+ * @returns The corresponding LocationErrorCode
76
+ */
77
+ export function mapAndroidException(exceptionType: string): LocationErrorCode {
78
+ if (exceptionType === "SecurityException") {
79
+ return LocationErrorCode.PERMISSION_DENIED;
80
+ }
81
+ return LocationErrorCode.POSITION_UNAVAILABLE;
82
+ }
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Pure utility functions for geolocation operations.
3
+ * These functions are platform-independent and can be tested with Jest.
4
+ */
5
+
6
+ export { isCachedLocationValid } from "./cache";
7
+ export {
8
+ LocationErrorCode,
9
+ createLocationError,
10
+ mapCLErrorCode,
11
+ mapAndroidException,
12
+ type LocationError
13
+ } from "./errors";
14
+ export {
15
+ isBetterLocation,
16
+ type LocationQuality
17
+ } from "./quality";
18
+ export {
19
+ selectProvider,
20
+ type Provider
21
+ } from "./provider";
22
+ export {
23
+ mergeConfigurations,
24
+ type LocationRequest,
25
+ type AccuracyLevel,
26
+ type MergedConfiguration
27
+ } from "./config";
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Location provider types supported on Android.
3
+ */
4
+ export type Provider = "gps" | "network" | null;
5
+
6
+ /**
7
+ * Selects the best available location provider based on user preferences
8
+ * and provider availability.
9
+ *
10
+ * This function implements a fallback strategy:
11
+ * - If high accuracy is requested, prefer GPS, fallback to Network
12
+ * - If low power is preferred, prefer Network, fallback to GPS
13
+ *
14
+ * @param enableHighAccuracy - Whether high accuracy mode is requested
15
+ * @param gpsAvailable - Whether GPS provider is available and enabled
16
+ * @param networkAvailable - Whether Network provider is available and enabled
17
+ * @returns The selected provider, or null if no providers are available
18
+ *
19
+ * @example
20
+ * ```ts
21
+ * // High accuracy mode with both providers available
22
+ * selectProvider(true, true, true); // 'gps'
23
+ *
24
+ * // High accuracy mode but GPS is disabled
25
+ * selectProvider(true, false, true); // 'network'
26
+ *
27
+ * // Low power mode with both providers available
28
+ * selectProvider(false, true, true); // 'network'
29
+ *
30
+ * // No providers available
31
+ * selectProvider(true, false, false); // null
32
+ * ```
33
+ */
34
+ export function selectProvider(
35
+ enableHighAccuracy: boolean,
36
+ gpsAvailable: boolean,
37
+ networkAvailable: boolean
38
+ ): Provider {
39
+ // Determine preferred and fallback providers based on accuracy requirement
40
+ const preferredProvider = enableHighAccuracy ? "gps" : "network";
41
+ const fallbackProvider = enableHighAccuracy ? "network" : "gps";
42
+
43
+ // Check if preferred provider is available
44
+ const isPreferredAvailable =
45
+ preferredProvider === "gps" ? gpsAvailable : networkAvailable;
46
+
47
+ // Check if fallback provider is available
48
+ const isFallbackAvailable =
49
+ fallbackProvider === "gps" ? gpsAvailable : networkAvailable;
50
+
51
+ // Return the best available provider
52
+ if (isPreferredAvailable) {
53
+ return preferredProvider;
54
+ }
55
+
56
+ if (isFallbackAvailable) {
57
+ return fallbackProvider;
58
+ }
59
+
60
+ return null;
61
+ }
@@ -0,0 +1,98 @@
1
+ /**
2
+ * Represents the quality characteristics of a location reading.
3
+ */
4
+ export interface LocationQuality {
5
+ /** Timestamp in milliseconds since epoch */
6
+ timestampMs: number;
7
+ /** Horizontal accuracy in meters */
8
+ accuracyMeters: number;
9
+ /** Location provider type */
10
+ provider: "gps" | "network";
11
+ }
12
+
13
+ /** Time threshold for considering locations significantly newer/older (2 minutes) */
14
+ const TWO_MINUTES_MS = 2 * 60 * 1000;
15
+
16
+ /** Accuracy threshold for considering locations significantly less accurate (200 meters) */
17
+ const SIGNIFICANT_ACCURACY_DIFFERENCE_METERS = 200;
18
+
19
+ /**
20
+ * Determines whether a new location is better than the current best location.
21
+ * This algorithm considers both recency and accuracy of location readings.
22
+ *
23
+ * Based on Android's location quality evaluation best practices:
24
+ * @see https://developer.android.com/develop/sensors-and-location/location/strategies#BestEstimate
25
+ *
26
+ * @param newLocation - The new location to evaluate
27
+ * @param currentBest - The current best location, or null if none exists
28
+ * @returns true if the new location is better, false otherwise
29
+ *
30
+ * @example
31
+ * ```ts
32
+ * const newLoc: LocationQuality = {
33
+ * timestampMs: Date.now(),
34
+ * accuracyMeters: 10,
35
+ * provider: 'gps'
36
+ * };
37
+ *
38
+ * const currentBest: LocationQuality = {
39
+ * timestampMs: Date.now() - 60000, // 1 minute ago
40
+ * accuracyMeters: 50,
41
+ * provider: 'network'
42
+ * };
43
+ *
44
+ * isBetterLocation(newLoc, currentBest); // true (newer and more accurate)
45
+ * ```
46
+ */
47
+ export function isBetterLocation(
48
+ newLocation: LocationQuality,
49
+ currentBest: LocationQuality | null
50
+ ): boolean {
51
+ // If there's no current best location, the new location is always better
52
+ if (!currentBest) {
53
+ return true;
54
+ }
55
+
56
+ // Calculate time difference between locations
57
+ const timeDelta = newLocation.timestampMs - currentBest.timestampMs;
58
+ const isSignificantlyNewer = timeDelta > TWO_MINUTES_MS;
59
+ const isSignificantlyOlder = timeDelta < -TWO_MINUTES_MS;
60
+
61
+ // If the new location is significantly newer, it's better
62
+ if (isSignificantlyNewer) {
63
+ return true;
64
+ }
65
+
66
+ // If the new location is significantly older, it's not better
67
+ if (isSignificantlyOlder) {
68
+ return false;
69
+ }
70
+
71
+ // Calculate accuracy difference
72
+ const accuracyDelta = newLocation.accuracyMeters - currentBest.accuracyMeters;
73
+ const isMoreAccurate = accuracyDelta < 0;
74
+ const isLessAccurate = accuracyDelta > 0;
75
+ const isSignificantlyLessAccurate =
76
+ accuracyDelta > SIGNIFICANT_ACCURACY_DIFFERENCE_METERS;
77
+
78
+ // Determine if location is newer
79
+ const isNewer = timeDelta > 0;
80
+
81
+ // Check if from same provider
82
+ const isFromSameProvider = newLocation.provider === currentBest.provider;
83
+
84
+ // Evaluate location quality based on accuracy and recency
85
+ if (isMoreAccurate) {
86
+ return true;
87
+ }
88
+
89
+ if (isNewer && !isLessAccurate) {
90
+ return true;
91
+ }
92
+
93
+ if (isNewer && !isSignificantlyLessAccurate && isFromSameProvider) {
94
+ return true;
95
+ }
96
+
97
+ return false;
98
+ }
package/README.md DELETED
@@ -1,318 +0,0 @@
1
- # react-native-nitro-geolocation
2
-
3
- [![NPM](https://img.shields.io/npm/v/react-native-nitro-geolocation)](https://www.npmjs.com/package/react-native-nitro-geolocation)
4
-
5
- [`@react-native-community/geolocation`](https://github.com/michalchudziak/react-native-geolocation)
6
- for the **React Native New Architecture** — with 100% API compatibility.
7
-
8
- ![react-native-nitro-geolocation)(https://raw.githubusercontent.com/jingjing2222/react-native-nitro-geolocation/main/demo.gif)
9
-
10
- ---
11
-
12
- ## 📘 Documentation
13
-
14
- Full documentation available at:
15
- 👉 [https://react-native-nitro-geolocation.pages.dev](https://react-native-nitro-geolocation.pages.dev)
16
-
17
- ---
18
-
19
- ## 🧭 Introduction
20
-
21
- The `@react-native-community/geolocation` package has long been the standard way to access device location in React Native apps.
22
-
23
- With React Native moving toward **Nitro Modules**, **Fabric**, and **JSI**,
24
- this project — **React Native Nitro Geolocation** — brings the same familiar API to the new architecture.
25
-
26
- It provides the **same API surface** with:
27
-
28
- - 🚀 Faster performance via direct **JSI bindings**
29
- - 📱 Improved native consistency (Android + iOS)
30
- - 🔁 Seamless migration from `@react-native-community/geolocation`
31
- - 🧩 TypeScript-first developer experience
32
- - 🔄 100% API compatibility (drop-in replacement)
33
-
34
- Whether upgrading an existing app or building a new one,
35
- **React Native Nitro Geolocation** keeps the simplicity you know — with modern internals.
36
-
37
- ## 🏗 Architecture Comparison
38
-
39
- ### 🧩 Origin: Event-based Architecture (`@react-native-community/geolocation`)
40
-
41
- ~~~
42
- JavaScript
43
- ↓ EventEmitter.addListener('geolocationDidChange', callback)
44
- ↓ (Callback stored in JS)
45
- React Native Bridge (JSON serialization)
46
-
47
- Native Layer (Android/iOS)
48
- ↓ LocationListener receives updates
49
- ↓ emit('geolocationDidChange', data)
50
-
51
- EventEmitter dispatches to all listeners
52
-
53
- User callback executed
54
- ~~~
55
-
56
- **Key traits:**
57
- - Callbacks stored only in JS
58
- - Bridge serialization on every update
59
- - One shared event stream
60
-
61
- ---
62
-
63
- ### ⚡ Modern: Direct Callback Architecture (`react-native-nitro-geolocation`)
64
-
65
- ~~~
66
- JavaScript
67
- ↓ Geolocation.watchPosition(success, error)
68
- ↓ (Callbacks passed directly to native via JSI)
69
- JSI Layer (No Bridge!)
70
-
71
- Native Layer (Kotlin/Swift)
72
- ↓ callback.success(position) → JSI direct call
73
-
74
- User callback executed immediately
75
- ~~~
76
-
77
- **Key traits:**
78
- - Callbacks passed as native JSI references
79
- - No Bridge serialization
80
- - Independent callback per watcher
81
- - Native → JS communication in real time
82
-
83
- ---
84
-
85
- ## ⚡ Quick Start
86
-
87
- ### 1. Installation
88
-
89
- ~~~bash
90
- # Install Nitro core and Geolocation module
91
- yarn add react-native-nitro-modules react-native-nitro-geolocation
92
-
93
- # or using npm
94
- npm install react-native-nitro-modules react-native-nitro-geolocation
95
- ~~~
96
-
97
- After installation, rebuild your native app:
98
-
99
- ~~~bash
100
- cd ios && pod install
101
- ~~~
102
-
103
- ---
104
-
105
- ### 2. iOS Setup
106
-
107
- Add the following permissions to your **Info.plist**:
108
-
109
- ~~~xml
110
- <key>NSLocationWhenInUseUsageDescription</key>
111
- <string>This app requires access to your location while it’s in use.</string>
112
- <key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
113
- <string>This app requires access to your location at all times.</string>
114
- ~~~
115
-
116
- ---
117
-
118
- ### 3. Android Setup
119
-
120
- Add these permissions to your **AndroidManifest.xml**:
121
-
122
- ~~~xml
123
- <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
124
- <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
125
- ~~~
126
-
127
- Optional (for background access):
128
-
129
- ~~~xml
130
- <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
131
- ~~~
132
-
133
- ---
134
-
135
- ### 4. Usage Example
136
-
137
- ~~~tsx
138
- import Geolocation from 'react-native-nitro-geolocation';
139
-
140
- Geolocation.getCurrentPosition(
141
- (position) => {
142
- console.log('Latitude:', position.coords.latitude);
143
- console.log('Longitude:', position.coords.longitude);
144
- },
145
- (error) => {
146
- console.error('Location error:', error);
147
- },
148
- { enableHighAccuracy: true, timeout: 15000, maximumAge: 10000 }
149
- );
150
-
151
- // Subscribe to continuous updates
152
- const watchId = Geolocation.watchPosition(
153
- (position) => {
154
- console.log('Updated position:', position);
155
- },
156
- (error) => console.error(error),
157
- );
158
- ~~~
159
-
160
- ---
161
-
162
- ### Migrating from `@react-native-community/geolocation`
163
-
164
- Nitro Geolocation is **100% API-compatible** with the original package.
165
- You can migrate simply by replacing imports:
166
-
167
- ~~~diff
168
- - import Geolocation from '@react-native-community/geolocation';
169
- + import Geolocation from 'react-native-nitro-geolocation';
170
- ~~~
171
-
172
- **Benefits:**
173
- - Better performance via JSI
174
- - Reduced bridge overhead
175
- - Improved permission consistency
176
- - Built-in TypeScript definitions
177
-
178
- ---
179
-
180
- ## 🧠 API Methods
181
-
182
- ### Summary
183
- - `setRNConfiguration`
184
- - `requestAuthorization`
185
- - `getCurrentPosition`
186
- - `watchPosition`
187
- - `clearWatch`
188
- - `stopObserving`
189
-
190
- ---
191
-
192
- ### `setRNConfiguration()`
193
-
194
- Sets configuration options used for all location requests.
195
-
196
- ~~~tsx
197
- import Geolocation from 'react-native-nitro-geolocation';
198
-
199
- Geolocation.setRNConfiguration({
200
- skipPermissionRequests: false,
201
- authorizationLevel: 'auto',
202
- enableBackgroundLocationUpdates: true,
203
- locationProvider: 'auto',
204
- });
205
-
206
- // recommended
207
- import { setRNConfiguration } from 'react-native-nitro-geolocation';
208
-
209
- setRNConfiguration({
210
- skipPermissionRequests: false,
211
- authorizationLevel: 'auto',
212
- enableBackgroundLocationUpdates: true,
213
- locationProvider: 'auto',
214
- });
215
- ~~~
216
-
217
- **Options:**
218
- - `skipPermissionRequests` — default `false`
219
- - `authorizationLevel` — `'always' | 'whenInUse' | 'auto'` *(iOS only)*
220
- - `enableBackgroundLocationUpdates` — *(iOS only)*
221
- - `locationProvider` — `'playServices' | 'android' | 'auto'` *(Android only)*
222
-
223
- ---
224
-
225
- ### `requestAuthorization()`
226
-
227
- Requests location permission from the system.
228
-
229
- ~~~tsx
230
- import Geolocation from 'react-native-nitro-geolocation';
231
-
232
- Geolocation.requestAuthorization(
233
- () => console.log('Permission granted'),
234
- (error) => console.error('Permission error:', error),
235
- );
236
-
237
- // recommended
238
- import { requestAuthorization } from 'react-native-nitro-geolocation';
239
-
240
- requestAuthorization(
241
- () => console.log('Permission granted'),
242
- (error) => console.error('Permission error:', error),
243
- );
244
- ~~~
245
-
246
- ---
247
-
248
- ### `getCurrentPosition()`
249
-
250
- Retrieves the current device location once.
251
-
252
- ~~~tsx
253
- import Geolocation from 'react-native-nitro-geolocation';
254
-
255
- Geolocation.getCurrentPosition(
256
- (position) => console.log(position),
257
- (error) => console.error(error),
258
- { enableHighAccuracy: true, timeout: 15000, maximumAge: 10000 },
259
- );
260
-
261
- // recommended
262
- import { getCurrentPosition } from 'react-native-nitro-geolocation';
263
-
264
- getCurrentPosition(
265
- (position) => console.log(position),
266
- (error) => console.error(error),
267
- { enableHighAccuracy: true, timeout: 15000, maximumAge: 10000 },
268
- );
269
- ~~~
270
-
271
- ---
272
-
273
- ### `watchPosition()`
274
-
275
- Watches location changes and calls the success callback each time.
276
-
277
- ~~~tsx
278
- import Geolocation from 'react-native-nitro-geolocation';
279
-
280
- const id = Geolocation.watchPosition(
281
- (position) => console.log('Position:', position),
282
- (error) => console.error(error),
283
- { interval: 5000, distanceFilter: 10 },
284
- );
285
-
286
- // recommended
287
- import { watchPosition } from 'react-native-nitro-geolocation';
288
-
289
- const id = watchPosition(
290
- (position) => console.log('Position:', position),
291
- (error) => console.error(error),
292
- { interval: 5000, distanceFilter: 10 },
293
- );
294
-
295
- ~~~
296
-
297
- ---
298
-
299
- ### `clearWatch()`
300
-
301
- Stops watching location updates for a given watch ID.
302
-
303
- ~~~tsx
304
- import Geolocation from 'react-native-nitro-geolocation';
305
- Geolocation.clearWatch(id);
306
-
307
- // recommended
308
- import { clearWatch } from 'react-native-nitro-geolocation';
309
- clearWatch(id);
310
- ~~~
311
-
312
- ---
313
-
314
- ## 🧪 Summary
315
-
316
- **React Native Nitro Geolocation** transforms the geolocation API
317
- from a bridge-based, event-driven system into a **JSI-powered direct-callback model** —
318
- delivering native-level performance with **zero API changes** for developers.
package/src/clearWatch.ts DELETED
@@ -1,13 +0,0 @@
1
- import { NitroModules } from "react-native-nitro-modules";
2
- import type { NitroGeolocation } from "./NitroGeolocation.nitro";
3
-
4
- /**
5
- * Clears a specific watch session identified by watchId.
6
- *
7
- * @param watchId - The ID returned by watchPosition()
8
- */
9
- export function clearWatch(watchId: number): void {
10
- const nitroGeolocation =
11
- NitroModules.createHybridObject<NitroGeolocation>("NitroGeolocation");
12
- nitroGeolocation.clearWatch(watchId);
13
- }
@@ -1,9 +0,0 @@
1
- import { NitroGeolocationHybridObject } from "./NitroGeolocationModule";
2
- import type { GeolocationError } from "./types";
3
-
4
- export function requestAuthorization(
5
- success?: () => void,
6
- error?: (error: GeolocationError) => void
7
- ): void {
8
- NitroGeolocationHybridObject.requestAuthorization(success, error);
9
- }