Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions packages/jsActions/nanoflow-actions-native/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),

## [Unreleased]

- We've migrated from using @react-native-community/geolocation to react-native-permissions for handling location permissions.

## [6.1.1] Nanoflow Commons - 2025-10-7

### Fixed
Expand Down
1 change: 1 addition & 0 deletions packages/jsActions/nanoflow-actions-native/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
"@react-native-community/geolocation": "3.4.0",
"invariant": "^2.2.4",
"js-base64": "~3.7.2",
"react-native-permissions": "5.4.2",
"react-native-geocoder": "0.5.0"
},
"devDependencies": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,8 @@
// - the code between BEGIN USER CODE and END USER CODE
// - the code between BEGIN EXTRA CODE and END EXTRA CODE
// Other code you write will be lost the next time you deploy the project.
import Geolocation from "@react-native-community/geolocation";

import type { GeolocationServiceStatic, AuthorizationResult } from "../../typings/Geolocation";
import { check, request, PERMISSIONS, RESULTS, openSettings } from "react-native-permissions";
import { Platform, Alert, ToastAndroid } from "react-native";

// BEGIN EXTRA CODE
// END EXTRA CODE
Expand All @@ -19,137 +18,77 @@ import type { GeolocationServiceStatic, AuthorizationResult } from "../../typing
export async function RequestLocationPermission(): Promise<boolean> {
// BEGIN USER CODE

let reactNativeModule: typeof import("react-native") | undefined;
let geolocationModule: typeof import("@react-native-community/geolocation").default;

const hasPermissionIOS = async (): Promise<boolean> => {
const openSetting = (): void => {
reactNativeModule?.Linking.openSettings().catch(() => {
reactNativeModule?.Alert.alert("Unable to open settings.");
openSettings().catch(() => {
Alert.alert("Unable to open settings.");
});
};

return (geolocationModule as GeolocationServiceStatic)
.requestAuthorization("whenInUse")
.then((status: AuthorizationResult) => {
if (status === "granted") {
return true;
}
const status = await request(PERMISSIONS.IOS.LOCATION_WHEN_IN_USE);

if (status === "denied") {
reactNativeModule?.Alert.alert("Location permission denied.");
}
if (status === RESULTS.GRANTED) {
return true;
}

if (status === RESULTS.DENIED || status === RESULTS.BLOCKED) {
Alert.alert("Location permission denied.");
}

if (status === "disabled") {
reactNativeModule?.Alert.alert(
"Location Services must be enabled to determine your location.",
"",
[
{ text: "Go to Settings", onPress: openSetting },
{
text: "Don't Use Location"
}
]
);
if (status === RESULTS.UNAVAILABLE) {
Alert.alert("Location Services must be enabled to determine your location.", "", [
{ text: "Go to Settings", onPress: openSetting },
{
text: "Don't Use Location"
}
]);
}

return false;
});
return false;
};

const hasPermissionAndroid = async (): Promise<boolean | undefined> => {
if (typeof reactNativeModule?.Platform?.Version === "number" && reactNativeModule?.Platform?.Version < 23) {
if (typeof Platform.Version === "number" && Platform.Version < 23) {
return true;
}

const androidLocationPermission = reactNativeModule?.PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION;
const status = await check(PERMISSIONS.ANDROID.ACCESS_FINE_LOCATION);

if (!androidLocationPermission) {
return false;
if (status === RESULTS.GRANTED) {
return true;
}

return reactNativeModule?.PermissionsAndroid.check(androidLocationPermission).then(hasPermission =>
hasPermission
? true
: reactNativeModule?.PermissionsAndroid?.request(androidLocationPermission).then(status => {
if (status === reactNativeModule?.PermissionsAndroid.RESULTS.GRANTED) {
return true;
}

if (status === reactNativeModule?.PermissionsAndroid.RESULTS.DENIED) {
reactNativeModule.ToastAndroid.show(
"Location permission denied by user.",
reactNativeModule.ToastAndroid.LONG
);
} else if (status === reactNativeModule?.PermissionsAndroid.RESULTS.NEVER_ASK_AGAIN) {
reactNativeModule.ToastAndroid.show(
"Location permission revoked by user.",
reactNativeModule.ToastAndroid.LONG
);
}

return false;
})
);
const requestStatus = await request(PERMISSIONS.ANDROID.ACCESS_FINE_LOCATION);

if (requestStatus === RESULTS.GRANTED) {
return true;
}

if (requestStatus === RESULTS.DENIED) {
ToastAndroid.show("Location permission denied by user.", ToastAndroid.LONG);
} else if (requestStatus === RESULTS.BLOCKED) {
ToastAndroid.show("Location permission revoked by user.", ToastAndroid.LONG);
}

return false;
};

const hasLocationPermission = async (): Promise<boolean> => {
if (reactNativeModule?.Platform.OS === "ios") {
if (Platform.OS === "ios") {
const hasPermission = await hasPermissionIOS();
return hasPermission;
}

if (reactNativeModule?.Platform.OS === "android") {
if (Platform.OS === "android") {
const hasPermission = await hasPermissionAndroid();
return hasPermission ?? false;
}

return Promise.reject(new Error("Unsupported platform"));
};

const hasLocationPermissionForOldLibrary = async (): Promise<boolean | undefined> => {
if (reactNativeModule?.Platform.OS === "android") {
const locationPermission = reactNativeModule.PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION;

return reactNativeModule.PermissionsAndroid.check(locationPermission).then(hasPermission =>
hasPermission
? true
: reactNativeModule?.PermissionsAndroid.request(locationPermission).then(
status => status === reactNativeModule?.PermissionsAndroid.RESULTS.GRANTED
)
);
} else if (geolocationModule) {
return new Promise(resolve => {
geolocationModule.requestAuthorization(
() => {
resolve(true);
},
() => {
resolve(false);
}
);
});
}

return false;
};

if (navigator && navigator.product === "ReactNative") {
reactNativeModule = require("react-native");

if (!reactNativeModule) {
return Promise.reject(new Error("React Native module could not be found"));
}

if (reactNativeModule.NativeModules.RNFusedLocation) {
geolocationModule = (await import("@react-native-community/geolocation")).default;
return hasLocationPermission();
} else if (reactNativeModule.NativeModules.RNCGeolocation) {
geolocationModule = Geolocation;
return (await hasLocationPermissionForOldLibrary()) ?? false;
} else {
return Promise.reject(new Error("Geolocation module could not be found"));
}
return hasLocationPermission();
} else if (navigator && navigator.geolocation) {
return Promise.reject(new Error("No permission request for location is required for web/hybrid platform"));
} else {
Expand Down
Loading