react-native-nitro-geolocation 0.1.2 → 0.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.
- package/android/src/main/java/com/margelo/nitro/nitrogeolocation/GetCurrentPosition.kt +4 -4
- package/android/src/main/java/com/margelo/nitro/nitrogeolocation/NitroGeolocation.kt +642 -50
- package/android/src/main/java/com/margelo/nitro/nitrogeolocation/NitroGeolocationCompat.kt +81 -0
- package/android/src/main/java/com/margelo/nitro/nitrogeolocation/WatchPosition.kt +4 -4
- package/ios/LocationManager.swift +4 -4
- package/ios/NitroGeolocation.swift +543 -68
- package/ios/NitroGeolocationCompat.swift +109 -0
- package/nitrogen/generated/android/c++/JAuthorizationLevel.hpp +61 -0
- package/nitrogen/generated/android/c++/JAuthorizationLevelInternal.hpp +3 -4
- package/nitrogen/generated/android/c++/JFunc_void.hpp +2 -1
- package/nitrogen/generated/android/c++/JFunc_void_GeolocationError.hpp +2 -1
- package/nitrogen/generated/android/c++/JFunc_void_GeolocationResponse.hpp +6 -1
- package/nitrogen/generated/android/c++/JFunc_void_LocationError.hpp +78 -0
- package/nitrogen/generated/android/c++/JGeolocationCoordinates.hpp +25 -17
- package/nitrogen/generated/android/c++/JGeolocationError.hpp +5 -1
- package/nitrogen/generated/android/c++/JGeolocationOptions.hpp +5 -1
- package/nitrogen/generated/android/c++/JGeolocationResponse.hpp +9 -1
- package/nitrogen/generated/android/c++/JHybridNitroGeolocationCompatSpec.cpp +109 -0
- package/nitrogen/generated/android/c++/JHybridNitroGeolocationCompatSpec.hpp +70 -0
- package/nitrogen/generated/android/c++/JHybridNitroGeolocationSpec.cpp +98 -42
- package/nitrogen/generated/android/c++/JHybridNitroGeolocationSpec.hpp +7 -5
- package/nitrogen/generated/android/c++/JLocationError.hpp +61 -0
- package/nitrogen/generated/android/c++/JLocationProvider.hpp +61 -0
- package/nitrogen/generated/android/c++/JLocationProviderInternal.hpp +3 -4
- package/nitrogen/generated/android/c++/JLocationRequestOptions.hpp +81 -0
- package/nitrogen/generated/android/c++/JModernGeolocationConfiguration.hpp +73 -0
- package/nitrogen/generated/android/c++/JNullableDouble.cpp +26 -0
- package/nitrogen/generated/android/c++/JNullableDouble.hpp +69 -0
- package/nitrogen/generated/android/c++/JPermissionStatus.hpp +64 -0
- package/nitrogen/generated/android/c++/JRNConfigurationInternal.hpp +5 -1
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/AuthorizationLevel.kt +24 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/AuthorizationLevelInternal.kt +2 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/Func_void.kt +0 -1
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/Func_void_GeolocationError.kt +0 -1
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/Func_void_GeolocationResponse.kt +0 -1
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/Func_void_LocationError.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/GeolocationCoordinates.kt +34 -25
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/GeolocationError.kt +27 -18
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/GeolocationOptions.kt +33 -24
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/GeolocationResponse.kt +18 -9
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/HybridNitroGeolocationCompatSpec.kt +92 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/HybridNitroGeolocationSpec.kt +17 -17
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/LocationError.kt +41 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/LocationProvider.kt +24 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/LocationProviderInternal.kt +2 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/LocationRequestOptions.kt +56 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/ModernGeolocationConfiguration.kt +47 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/NullableDouble.kt +59 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/PermissionStatus.kt +25 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/RNConfigurationInternal.kt +24 -15
- package/nitrogen/generated/android/nitrogeolocation+autolinking.cmake +3 -0
- package/nitrogen/generated/android/nitrogeolocationOnLoad.cpp +14 -2
- package/nitrogen/generated/ios/NitroGeolocation+autolinking.rb +1 -1
- package/nitrogen/generated/ios/NitroGeolocation-Swift-Cxx-Bridge.cpp +55 -13
- package/nitrogen/generated/ios/NitroGeolocation-Swift-Cxx-Bridge.hpp +325 -68
- package/nitrogen/generated/ios/NitroGeolocation-Swift-Cxx-Umbrella.hpp +26 -0
- package/nitrogen/generated/ios/NitroGeolocationAutolinking.mm +8 -0
- package/nitrogen/generated/ios/NitroGeolocationAutolinking.swift +15 -0
- package/nitrogen/generated/ios/c++/HybridNitroGeolocationCompatSpecSwift.cpp +11 -0
- package/nitrogen/generated/ios/c++/HybridNitroGeolocationCompatSpecSwift.hpp +130 -0
- package/nitrogen/generated/ios/c++/HybridNitroGeolocationSpecSwift.hpp +47 -26
- package/nitrogen/generated/ios/swift/AuthorizationLevel.swift +44 -0
- package/nitrogen/generated/ios/swift/Func_void.swift +1 -1
- package/nitrogen/generated/ios/swift/Func_void_GeolocationError.swift +1 -1
- package/nitrogen/generated/ios/swift/Func_void_GeolocationResponse.swift +1 -1
- package/nitrogen/generated/ios/swift/Func_void_LocationError.swift +47 -0
- package/nitrogen/generated/ios/swift/Func_void_PermissionStatus.swift +47 -0
- package/nitrogen/generated/ios/swift/Func_void_std__exception_ptr.swift +47 -0
- package/nitrogen/generated/ios/swift/GeolocationCoordinates.swift +132 -93
- package/nitrogen/generated/ios/swift/GeolocationError.swift +11 -40
- package/nitrogen/generated/ios/swift/GeolocationOptions.swift +29 -98
- package/nitrogen/generated/ios/swift/GeolocationResponse.swift +5 -16
- package/nitrogen/generated/ios/swift/HybridNitroGeolocationCompatSpec.swift +61 -0
- package/nitrogen/generated/ios/swift/HybridNitroGeolocationCompatSpec_cxx.swift +244 -0
- package/nitrogen/generated/ios/swift/HybridNitroGeolocationSpec.swift +13 -5
- package/nitrogen/generated/ios/swift/HybridNitroGeolocationSpec_cxx.swift +66 -64
- package/nitrogen/generated/ios/swift/LocationError.swift +35 -0
- package/nitrogen/generated/ios/swift/LocationProvider.swift +44 -0
- package/nitrogen/generated/ios/swift/LocationRequestOptions.swift +116 -0
- package/nitrogen/generated/ios/swift/ModernGeolocationConfiguration.swift +83 -0
- package/nitrogen/generated/ios/swift/NullableDouble.swift +18 -0
- package/nitrogen/generated/ios/swift/PermissionStatus.swift +48 -0
- package/nitrogen/generated/ios/swift/RNConfigurationInternal.swift +16 -50
- package/nitrogen/generated/shared/c++/AuthorizationLevel.hpp +80 -0
- package/nitrogen/generated/shared/c++/GeolocationCoordinates.hpp +45 -27
- package/nitrogen/generated/shared/c++/GeolocationError.hpp +32 -16
- package/nitrogen/generated/shared/c++/GeolocationOptions.hpp +38 -22
- package/nitrogen/generated/shared/c++/GeolocationResponse.hpp +23 -7
- package/nitrogen/generated/shared/c++/HybridNitroGeolocationCompatSpec.cpp +26 -0
- package/nitrogen/generated/shared/c++/HybridNitroGeolocationCompatSpec.hpp +79 -0
- package/nitrogen/generated/shared/c++/HybridNitroGeolocationSpec.cpp +4 -3
- package/nitrogen/generated/shared/c++/HybridNitroGeolocationSpec.hpp +22 -16
- package/nitrogen/generated/shared/c++/LocationError.hpp +87 -0
- package/nitrogen/generated/shared/c++/LocationProvider.hpp +80 -0
- package/nitrogen/generated/shared/c++/LocationRequestOptions.hpp +107 -0
- package/nitrogen/generated/shared/c++/ModernGeolocationConfiguration.hpp +100 -0
- package/nitrogen/generated/shared/c++/PermissionStatus.hpp +84 -0
- package/nitrogen/generated/shared/c++/RNConfigurationInternal.hpp +29 -13
- package/package.json +16 -7
- package/src/GeolocationClient.ts +116 -0
- package/src/NitroGeolocation.nitro.ts +177 -30
- package/src/NitroGeolocationCompat.nitro.ts +41 -0
- package/src/NitroGeolocationModule.ts +6 -0
- package/src/compat/clearWatch.ts +9 -0
- package/src/{getCurrentPosition.ts → compat/getCurrentPosition.ts} +7 -3
- package/src/compat/index.tsx +34 -0
- package/src/compat/requestAuthorization.ts +9 -0
- package/src/{setRNConfiguration.ts → compat/setRNConfiguration.ts} +6 -4
- package/src/{stopObserving.ts → compat/stopObserving.ts} +4 -2
- package/src/{watchPosition.ts → compat/watchPosition.ts} +7 -6
- package/src/components/GeolocationProvider.tsx +91 -0
- package/src/components/index.ts +13 -0
- package/src/hooks/index.ts +9 -0
- package/src/hooks/useCheckPermission.ts +46 -0
- package/src/hooks/useGetCurrentPosition.ts +140 -0
- package/src/hooks/useRequestPermission.ts +98 -0
- package/src/hooks/useWatchPosition.ts +130 -0
- package/src/index.tsx +72 -27
- package/src/types.ts +32 -4
- package/src/utils/cache.ts +25 -0
- package/src/utils/config.ts +93 -0
- package/src/utils/errors.ts +82 -0
- package/src/utils/index.ts +27 -0
- package/src/utils/provider.ts +61 -0
- package/src/utils/quality.ts +98 -0
- package/src/clearWatch.ts +0 -13
- package/src/requestAuthorization.ts +0 -9
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { NitroGeolocationHybridCompatObject } from "../NitroGeolocationModule";
|
|
2
|
+
import type { GeolocationError } from "../types";
|
|
3
|
+
|
|
4
|
+
export function requestAuthorization(
|
|
5
|
+
success?: () => void,
|
|
6
|
+
error?: (error: GeolocationError) => void
|
|
7
|
+
): void {
|
|
8
|
+
NitroGeolocationHybridCompatObject.requestAuthorization(success, error);
|
|
9
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { RNConfigurationInternal } from "
|
|
2
|
-
import {
|
|
3
|
-
import type { GeolocationConfiguration } from "
|
|
1
|
+
import type { RNConfigurationInternal } from "../NitroGeolocationCompat.nitro";
|
|
2
|
+
import { NitroGeolocationHybridCompatObject } from "../NitroGeolocationModule";
|
|
3
|
+
import type { GeolocationConfiguration } from "../types";
|
|
4
4
|
|
|
5
5
|
// Mapping layer: convert "android" to "android_platform" for C++
|
|
6
6
|
function mapConfigToInternal(
|
|
@@ -18,5 +18,7 @@ function mapConfigToInternal(
|
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
export function setRNConfiguration(config: GeolocationConfiguration): void {
|
|
21
|
-
|
|
21
|
+
NitroGeolocationHybridCompatObject.setRNConfiguration(
|
|
22
|
+
mapConfigToInternal(config)
|
|
23
|
+
);
|
|
22
24
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { NitroModules } from "react-native-nitro-modules";
|
|
2
|
-
import type {
|
|
2
|
+
import type { NitroGeolocationCompat } from "../NitroGeolocationCompat.nitro";
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Stops observing all location updates.
|
|
@@ -7,6 +7,8 @@ import type { NitroGeolocation } from "./NitroGeolocation.nitro";
|
|
|
7
7
|
*/
|
|
8
8
|
export function stopObserving(): void {
|
|
9
9
|
const nitroGeolocation =
|
|
10
|
-
NitroModules.createHybridObject<
|
|
10
|
+
NitroModules.createHybridObject<NitroGeolocationCompat>(
|
|
11
|
+
"NitroGeolocationCompat"
|
|
12
|
+
);
|
|
11
13
|
nitroGeolocation.stopObserving();
|
|
12
14
|
}
|
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import type { NitroGeolocation } from "./NitroGeolocation.nitro";
|
|
1
|
+
import { NitroGeolocationHybridCompatObject } from "../NitroGeolocationModule";
|
|
3
2
|
import type {
|
|
4
3
|
GeolocationError,
|
|
5
4
|
GeolocationOptions,
|
|
6
5
|
GeolocationResponse
|
|
7
|
-
} from "
|
|
6
|
+
} from "../types";
|
|
8
7
|
|
|
9
8
|
/**
|
|
10
9
|
* Invokes the success callback whenever the location changes.
|
|
@@ -20,7 +19,9 @@ export function watchPosition(
|
|
|
20
19
|
error?: (error: GeolocationError) => void,
|
|
21
20
|
options?: GeolocationOptions
|
|
22
21
|
): number {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
22
|
+
return NitroGeolocationHybridCompatObject.watchPosition(
|
|
23
|
+
success,
|
|
24
|
+
error,
|
|
25
|
+
options
|
|
26
|
+
);
|
|
26
27
|
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import React, { createContext, useContext } from "react";
|
|
2
|
+
import type { GeolocationClient } from "../GeolocationClient";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Geolocation context value.
|
|
6
|
+
*/
|
|
7
|
+
export interface GeolocationContextValue {
|
|
8
|
+
client: GeolocationClient;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Geolocation context.
|
|
13
|
+
*/
|
|
14
|
+
const GeolocationContext = createContext<GeolocationContextValue | null>(null);
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Hook to access GeolocationClient from context.
|
|
18
|
+
* Throws error if used outside GeolocationClientProvider.
|
|
19
|
+
*/
|
|
20
|
+
export function useGeolocationClient(): GeolocationClient {
|
|
21
|
+
const context = useContext(GeolocationContext);
|
|
22
|
+
|
|
23
|
+
if (!context) {
|
|
24
|
+
throw new Error(
|
|
25
|
+
"useGeolocationClient must be used within GeolocationClientProvider. " +
|
|
26
|
+
"Wrap your component with <GeolocationClientProvider client={...}> at the root level."
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return context.client;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Props for GeolocationProvider component.
|
|
35
|
+
*/
|
|
36
|
+
export interface GeolocationProviderProps {
|
|
37
|
+
/**
|
|
38
|
+
* GeolocationClient instance (required).
|
|
39
|
+
* Create with: new GeolocationClient({...config})
|
|
40
|
+
*/
|
|
41
|
+
client: GeolocationClient;
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Child components that can use geolocation hooks.
|
|
45
|
+
*/
|
|
46
|
+
children: React.ReactNode;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Provider component for GeolocationClient.
|
|
51
|
+
*
|
|
52
|
+
* This component should wrap your app at the root level.
|
|
53
|
+
* It provides a GeolocationClient instance to all child components via context.
|
|
54
|
+
*
|
|
55
|
+
* @example
|
|
56
|
+
* ```tsx
|
|
57
|
+
* // Create client instance
|
|
58
|
+
* const geolocationClient = new GeolocationClient({
|
|
59
|
+
* authorizationLevel: 'whenInUse',
|
|
60
|
+
* enableBackgroundLocationUpdates: false,
|
|
61
|
+
* locationProvider: 'auto'
|
|
62
|
+
* });
|
|
63
|
+
*
|
|
64
|
+
* function App() {
|
|
65
|
+
* return (
|
|
66
|
+
* <GeolocationClientProvider client={geolocationClient}>
|
|
67
|
+
* <NavigationContainer>
|
|
68
|
+
* <YourApp />
|
|
69
|
+
* </NavigationContainer>
|
|
70
|
+
* </GeolocationClientProvider>
|
|
71
|
+
* );
|
|
72
|
+
* }
|
|
73
|
+
* ```
|
|
74
|
+
*/
|
|
75
|
+
export function GeolocationProvider({
|
|
76
|
+
client,
|
|
77
|
+
children
|
|
78
|
+
}: GeolocationProviderProps) {
|
|
79
|
+
const value: GeolocationContextValue = {
|
|
80
|
+
client
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
return (
|
|
84
|
+
<GeolocationContext.Provider value={value}>
|
|
85
|
+
{children}
|
|
86
|
+
</GeolocationContext.Provider>
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Modern alias (preferred)
|
|
91
|
+
export const GeolocationClientProvider = GeolocationProvider;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* React components for geolocation.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
export {
|
|
6
|
+
GeolocationProvider,
|
|
7
|
+
GeolocationClientProvider,
|
|
8
|
+
useGeolocationClient
|
|
9
|
+
} from "./GeolocationProvider";
|
|
10
|
+
export type {
|
|
11
|
+
GeolocationProviderProps,
|
|
12
|
+
GeolocationContextValue
|
|
13
|
+
} from "./GeolocationProvider";
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Modern React hooks for geolocation.
|
|
3
|
+
* These hooks provide a declarative, React-friendly API for location services.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export * from "./useCheckPermission";
|
|
7
|
+
export * from "./useRequestPermission";
|
|
8
|
+
export * from "./useGetCurrentPosition";
|
|
9
|
+
export * from "./useWatchPosition";
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { PermissionStatus } from "../NitroGeolocation.nitro";
|
|
2
|
+
import { useGeolocationClient } from "../components/GeolocationProvider";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Hook that returns a function to check current location permission status.
|
|
6
|
+
* Does NOT request permission, only checks current state.
|
|
7
|
+
*
|
|
8
|
+
* Must be used within GeolocationClientProvider.
|
|
9
|
+
*
|
|
10
|
+
* @returns Object containing checkPermission function
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```tsx
|
|
14
|
+
* const geolocationClient = new GeolocationClient({...config});
|
|
15
|
+
*
|
|
16
|
+
* function App() {
|
|
17
|
+
* return (
|
|
18
|
+
* <GeolocationClientProvider client={geolocationClient}>
|
|
19
|
+
* <MyComponent />
|
|
20
|
+
* </GeolocationClientProvider>
|
|
21
|
+
* );
|
|
22
|
+
* }
|
|
23
|
+
*
|
|
24
|
+
* function MyComponent() {
|
|
25
|
+
* const { checkPermission } = useCheckPermission();
|
|
26
|
+
*
|
|
27
|
+
* const handleCheck = async () => {
|
|
28
|
+
* const status = await checkPermission();
|
|
29
|
+
* if (status === 'granted') {
|
|
30
|
+
* // Can use location
|
|
31
|
+
* }
|
|
32
|
+
* };
|
|
33
|
+
*
|
|
34
|
+
* return <Button onPress={handleCheck} />;
|
|
35
|
+
* }
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
export function useCheckPermission() {
|
|
39
|
+
const client = useGeolocationClient();
|
|
40
|
+
|
|
41
|
+
return {
|
|
42
|
+
checkPermission: (): Promise<PermissionStatus> => {
|
|
43
|
+
return client.checkPermission();
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import { useCallback, useEffect, useRef, useState } from "react";
|
|
2
|
+
import type {
|
|
3
|
+
LocationError,
|
|
4
|
+
LocationRequestOptions
|
|
5
|
+
} from "../NitroGeolocation.nitro";
|
|
6
|
+
import { useGeolocationClient } from "../components/GeolocationProvider";
|
|
7
|
+
import type { GeolocationResponse } from "../types";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Options for useGetCurrentPosition hook (Query style).
|
|
11
|
+
*/
|
|
12
|
+
export interface UseGetCurrentPositionOptions extends LocationRequestOptions {
|
|
13
|
+
/**
|
|
14
|
+
* Whether to automatically fetch the current position.
|
|
15
|
+
* When false, only manual refetch() will trigger the request.
|
|
16
|
+
* @default true
|
|
17
|
+
*/
|
|
18
|
+
enabled?: boolean;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Hook for getting current location (one-time request) in Query style.
|
|
23
|
+
* Provides loading, error states, and data similar to TanStack Query.
|
|
24
|
+
*
|
|
25
|
+
* @param options - Location request options and enabled flag
|
|
26
|
+
* @returns Object containing position, loading/error states, and refetch function
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* ```tsx
|
|
30
|
+
* // Auto-fetch on mount
|
|
31
|
+
* function MyComponent() {
|
|
32
|
+
* const {
|
|
33
|
+
* position,
|
|
34
|
+
* isLoading,
|
|
35
|
+
* isError,
|
|
36
|
+
* error,
|
|
37
|
+
* refetch
|
|
38
|
+
* } = useGetCurrentPosition({
|
|
39
|
+
* enabled: true,
|
|
40
|
+
* enableHighAccuracy: true,
|
|
41
|
+
* });
|
|
42
|
+
*
|
|
43
|
+
* if (isLoading) return <Text>Loading...</Text>;
|
|
44
|
+
* if (isError) return <Text>Error: {error?.message}</Text>;
|
|
45
|
+
* if (!position) return null;
|
|
46
|
+
*
|
|
47
|
+
* return (
|
|
48
|
+
* <View>
|
|
49
|
+
* <Text>Lat: {position.coords.latitude}</Text>
|
|
50
|
+
* <Text>Lng: {position.coords.longitude}</Text>
|
|
51
|
+
* <Button title="Refresh" onPress={() => refetch()} />
|
|
52
|
+
* </View>
|
|
53
|
+
* );
|
|
54
|
+
* }
|
|
55
|
+
*
|
|
56
|
+
* // Manual trigger only
|
|
57
|
+
* function ManualComponent() {
|
|
58
|
+
* const { position, isLoading, refetch } = useGetCurrentPosition({
|
|
59
|
+
* enabled: false
|
|
60
|
+
* });
|
|
61
|
+
*
|
|
62
|
+
* return (
|
|
63
|
+
* <View>
|
|
64
|
+
* <Button
|
|
65
|
+
* title="Get Location"
|
|
66
|
+
* onPress={() => refetch()}
|
|
67
|
+
* disabled={isLoading}
|
|
68
|
+
* />
|
|
69
|
+
* {position && <Text>Lat: {position.coords.latitude}</Text>}
|
|
70
|
+
* </View>
|
|
71
|
+
* );
|
|
72
|
+
* }
|
|
73
|
+
* ```
|
|
74
|
+
*/
|
|
75
|
+
export function useGetCurrentPosition(options?: UseGetCurrentPositionOptions) {
|
|
76
|
+
const client = useGeolocationClient();
|
|
77
|
+
|
|
78
|
+
const [position, setPosition] = useState<GeolocationResponse | null>(null);
|
|
79
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
80
|
+
const [isError, setIsError] = useState(false);
|
|
81
|
+
const [error, setError] = useState<LocationError | null>(null);
|
|
82
|
+
|
|
83
|
+
const isMountedRef = useRef(true);
|
|
84
|
+
const optionsRef = useRef(options);
|
|
85
|
+
|
|
86
|
+
// Update options ref when they change
|
|
87
|
+
useEffect(() => {
|
|
88
|
+
optionsRef.current = options;
|
|
89
|
+
}, [options]);
|
|
90
|
+
|
|
91
|
+
const fetchPosition = useCallback(async () => {
|
|
92
|
+
if (!isMountedRef.current) return;
|
|
93
|
+
|
|
94
|
+
setIsLoading(true);
|
|
95
|
+
setIsError(false);
|
|
96
|
+
setError(null);
|
|
97
|
+
|
|
98
|
+
try {
|
|
99
|
+
const result = await client.getCurrentPosition(optionsRef.current);
|
|
100
|
+
if (!isMountedRef.current) return;
|
|
101
|
+
|
|
102
|
+
setPosition(result);
|
|
103
|
+
setIsLoading(false);
|
|
104
|
+
} catch (err) {
|
|
105
|
+
if (!isMountedRef.current) return;
|
|
106
|
+
|
|
107
|
+
setIsError(true);
|
|
108
|
+
setError(err as LocationError);
|
|
109
|
+
setIsLoading(false);
|
|
110
|
+
}
|
|
111
|
+
}, [client]);
|
|
112
|
+
|
|
113
|
+
// Extract enabled flag for reactive dependency
|
|
114
|
+
const enabled = options?.enabled ?? true;
|
|
115
|
+
|
|
116
|
+
// Auto-fetch on mount if enabled
|
|
117
|
+
useEffect(() => {
|
|
118
|
+
if (enabled) {
|
|
119
|
+
fetchPosition();
|
|
120
|
+
}
|
|
121
|
+
// Only run when enabled changes, not when fetchPosition changes
|
|
122
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
123
|
+
}, [enabled]);
|
|
124
|
+
|
|
125
|
+
// Track mount status
|
|
126
|
+
useEffect(() => {
|
|
127
|
+
isMountedRef.current = true;
|
|
128
|
+
return () => {
|
|
129
|
+
isMountedRef.current = false;
|
|
130
|
+
};
|
|
131
|
+
}, []);
|
|
132
|
+
|
|
133
|
+
return {
|
|
134
|
+
position,
|
|
135
|
+
isLoading,
|
|
136
|
+
isError,
|
|
137
|
+
error,
|
|
138
|
+
refetch: fetchPosition
|
|
139
|
+
};
|
|
140
|
+
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { useCallback, useEffect, useRef, useState } from "react";
|
|
2
|
+
import type {
|
|
3
|
+
LocationError,
|
|
4
|
+
PermissionStatus
|
|
5
|
+
} from "../NitroGeolocation.nitro";
|
|
6
|
+
import { useGeolocationClient } from "../components/GeolocationProvider";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Hook for requesting location permission in Mutation style.
|
|
10
|
+
* Provides pending, error states, and status similar to TanStack Query mutations.
|
|
11
|
+
*
|
|
12
|
+
* @returns Object containing requestPermission function, status, and state flags
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```tsx
|
|
16
|
+
* function MyComponent() {
|
|
17
|
+
* const {
|
|
18
|
+
* requestPermission,
|
|
19
|
+
* status,
|
|
20
|
+
* isPending,
|
|
21
|
+
* isError,
|
|
22
|
+
* error
|
|
23
|
+
* } = useRequestPermission();
|
|
24
|
+
*
|
|
25
|
+
* const handleRequest = async () => {
|
|
26
|
+
* const result = await requestPermission();
|
|
27
|
+
* if (result === 'granted') {
|
|
28
|
+
* console.log('Permission granted!');
|
|
29
|
+
* }
|
|
30
|
+
* };
|
|
31
|
+
*
|
|
32
|
+
* return (
|
|
33
|
+
* <View>
|
|
34
|
+
* <Button
|
|
35
|
+
* onPress={handleRequest}
|
|
36
|
+
* disabled={isPending}
|
|
37
|
+
* >
|
|
38
|
+
* {isPending ? 'Requesting...' : 'Request Permission'}
|
|
39
|
+
* </Button>
|
|
40
|
+
* {isError && <Text>Error: {error?.message}</Text>}
|
|
41
|
+
* {status && <Text>Status: {status}</Text>}
|
|
42
|
+
* </View>
|
|
43
|
+
* );
|
|
44
|
+
* }
|
|
45
|
+
* ```
|
|
46
|
+
*/
|
|
47
|
+
export function useRequestPermission() {
|
|
48
|
+
const client = useGeolocationClient();
|
|
49
|
+
|
|
50
|
+
const [status, setStatus] = useState<PermissionStatus | null>(null);
|
|
51
|
+
const [isPending, setIsPending] = useState(false);
|
|
52
|
+
const [isError, setIsError] = useState(false);
|
|
53
|
+
const [error, setError] = useState<LocationError | null>(null);
|
|
54
|
+
|
|
55
|
+
const isMountedRef = useRef(true);
|
|
56
|
+
|
|
57
|
+
const requestPermission = useCallback(async (): Promise<PermissionStatus> => {
|
|
58
|
+
if (!isMountedRef.current) {
|
|
59
|
+
throw new Error("Component unmounted");
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
setIsPending(true);
|
|
63
|
+
setIsError(false);
|
|
64
|
+
setError(null);
|
|
65
|
+
|
|
66
|
+
try {
|
|
67
|
+
const result = await client.requestPermission();
|
|
68
|
+
if (!isMountedRef.current) return result;
|
|
69
|
+
|
|
70
|
+
setStatus(result);
|
|
71
|
+
setIsPending(false);
|
|
72
|
+
return result;
|
|
73
|
+
} catch (err) {
|
|
74
|
+
if (!isMountedRef.current) throw err;
|
|
75
|
+
|
|
76
|
+
setIsError(true);
|
|
77
|
+
setError(err as LocationError);
|
|
78
|
+
setIsPending(false);
|
|
79
|
+
throw err;
|
|
80
|
+
}
|
|
81
|
+
}, [client]);
|
|
82
|
+
|
|
83
|
+
// Track mount status
|
|
84
|
+
useEffect(() => {
|
|
85
|
+
isMountedRef.current = true;
|
|
86
|
+
return () => {
|
|
87
|
+
isMountedRef.current = false;
|
|
88
|
+
};
|
|
89
|
+
}, []);
|
|
90
|
+
|
|
91
|
+
return {
|
|
92
|
+
requestPermission,
|
|
93
|
+
status,
|
|
94
|
+
isPending,
|
|
95
|
+
isError,
|
|
96
|
+
error
|
|
97
|
+
};
|
|
98
|
+
}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { useEffect, useRef, useState } from "react";
|
|
2
|
+
import type {
|
|
3
|
+
LocationError,
|
|
4
|
+
LocationRequestOptions
|
|
5
|
+
} from "../NitroGeolocation.nitro";
|
|
6
|
+
import { useGeolocationClient } from "../components/GeolocationProvider";
|
|
7
|
+
import type { GeolocationResponse } from "../types";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Options for useWatchPosition hook.
|
|
11
|
+
*/
|
|
12
|
+
export interface UseWatchPositionOptions extends LocationRequestOptions {
|
|
13
|
+
/**
|
|
14
|
+
* Whether to actively watch for location updates.
|
|
15
|
+
* When false, watching is paused and cleanup is performed.
|
|
16
|
+
* @default false
|
|
17
|
+
*/
|
|
18
|
+
enabled?: boolean;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Hook for continuous location tracking.
|
|
23
|
+
* Automatically subscribes/unsubscribes based on component lifecycle.
|
|
24
|
+
*
|
|
25
|
+
* The subscription token is completely hidden from the user.
|
|
26
|
+
* Cleanup is automatic via useEffect.
|
|
27
|
+
*
|
|
28
|
+
* @param options - Location request options
|
|
29
|
+
* @returns Object containing current position, error, and watching status
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* ```tsx
|
|
33
|
+
* function LiveTracking() {
|
|
34
|
+
* const { position, error, isWatching } = useWatchPosition({
|
|
35
|
+
* enabled: true,
|
|
36
|
+
* enableHighAccuracy: true,
|
|
37
|
+
* distanceFilter: 10 // Update every 10 meters
|
|
38
|
+
* });
|
|
39
|
+
*
|
|
40
|
+
* if (!isWatching) return <Text>Not watching</Text>;
|
|
41
|
+
* if (error) return <Text>Error: {error.message}</Text>;
|
|
42
|
+
* if (!position) return <Text>Waiting for location...</Text>;
|
|
43
|
+
*
|
|
44
|
+
* return (
|
|
45
|
+
* <Text>
|
|
46
|
+
* Current: {position.coords.latitude}, {position.coords.longitude}
|
|
47
|
+
* Accuracy: {position.coords.accuracy}m
|
|
48
|
+
* </Text>
|
|
49
|
+
* );
|
|
50
|
+
* }
|
|
51
|
+
* ```
|
|
52
|
+
*/
|
|
53
|
+
export function useWatchPosition(options?: UseWatchPositionOptions) {
|
|
54
|
+
const client = useGeolocationClient();
|
|
55
|
+
|
|
56
|
+
const [position, setPosition] = useState<GeolocationResponse | null>(null);
|
|
57
|
+
const [isWatching, setIsWatching] = useState(false);
|
|
58
|
+
const [error, setError] = useState<LocationError | null>(null);
|
|
59
|
+
|
|
60
|
+
// Store subscription token (hidden from user!)
|
|
61
|
+
const tokenRef = useRef<string | null>(null);
|
|
62
|
+
|
|
63
|
+
// Track if component is mounted to prevent state updates after unmount
|
|
64
|
+
const isMountedRef = useRef(true);
|
|
65
|
+
|
|
66
|
+
// Store latest options in ref to avoid unnecessary re-subscriptions
|
|
67
|
+
const optionsRef = useRef(options);
|
|
68
|
+
|
|
69
|
+
// Update options ref whenever options change
|
|
70
|
+
useEffect(() => {
|
|
71
|
+
optionsRef.current = options;
|
|
72
|
+
}, [options]);
|
|
73
|
+
|
|
74
|
+
// Extract enabled flag for reactive dependency
|
|
75
|
+
const enabled = options?.enabled ?? false;
|
|
76
|
+
|
|
77
|
+
useEffect(() => {
|
|
78
|
+
if (!enabled) {
|
|
79
|
+
// Not enabled, ensure cleanup
|
|
80
|
+
if (tokenRef.current) {
|
|
81
|
+
client.unwatch(tokenRef.current);
|
|
82
|
+
tokenRef.current = null;
|
|
83
|
+
}
|
|
84
|
+
setIsWatching(false);
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Start watching with latest options
|
|
89
|
+
setIsWatching(true);
|
|
90
|
+
setError(null);
|
|
91
|
+
|
|
92
|
+
const token = client.watchPosition(
|
|
93
|
+
(result: GeolocationResponse) => {
|
|
94
|
+
// Success callback
|
|
95
|
+
if (!isMountedRef.current) return;
|
|
96
|
+
setPosition(result);
|
|
97
|
+
setError(null);
|
|
98
|
+
},
|
|
99
|
+
(err: LocationError) => {
|
|
100
|
+
// Error callback
|
|
101
|
+
if (!isMountedRef.current) return;
|
|
102
|
+
setError(err);
|
|
103
|
+
},
|
|
104
|
+
optionsRef.current
|
|
105
|
+
);
|
|
106
|
+
|
|
107
|
+
tokenRef.current = token;
|
|
108
|
+
|
|
109
|
+
// Cleanup function
|
|
110
|
+
return () => {
|
|
111
|
+
if (token) {
|
|
112
|
+
client.unwatch(token);
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
}, [enabled, client]); // Only re-subscribe when enabled/client changes
|
|
116
|
+
|
|
117
|
+
// Track mount status
|
|
118
|
+
useEffect(() => {
|
|
119
|
+
isMountedRef.current = true;
|
|
120
|
+
return () => {
|
|
121
|
+
isMountedRef.current = false;
|
|
122
|
+
};
|
|
123
|
+
}, []);
|
|
124
|
+
|
|
125
|
+
return {
|
|
126
|
+
position,
|
|
127
|
+
error,
|
|
128
|
+
isWatching
|
|
129
|
+
};
|
|
130
|
+
}
|