Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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