From 6a2146f0539bf89290e89577c5b0cf539b5ae475 Mon Sep 17 00:00:00 2001 From: karahanharunn Date: Thu, 16 Oct 2025 09:46:08 +0200 Subject: [PATCH] feat: migrate to react-native-permissions for location handling --- .../nanoflow-actions-native/CHANGELOG.md | 2 + .../nanoflow-actions-native/package.json | 1 + .../geolocation/RequestLocationPermission.ts | 141 +++++------------- 3 files changed, 43 insertions(+), 101 deletions(-) diff --git a/packages/jsActions/nanoflow-actions-native/CHANGELOG.md b/packages/jsActions/nanoflow-actions-native/CHANGELOG.md index 69cc94518..c9c6071cb 100644 --- a/packages/jsActions/nanoflow-actions-native/CHANGELOG.md +++ b/packages/jsActions/nanoflow-actions-native/CHANGELOG.md @@ -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 diff --git a/packages/jsActions/nanoflow-actions-native/package.json b/packages/jsActions/nanoflow-actions-native/package.json index ae87bd594..6df397a08 100644 --- a/packages/jsActions/nanoflow-actions-native/package.json +++ b/packages/jsActions/nanoflow-actions-native/package.json @@ -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": { diff --git a/packages/jsActions/nanoflow-actions-native/src/geolocation/RequestLocationPermission.ts b/packages/jsActions/nanoflow-actions-native/src/geolocation/RequestLocationPermission.ts index 0bdf03337..b9a253b19 100644 --- a/packages/jsActions/nanoflow-actions-native/src/geolocation/RequestLocationPermission.ts +++ b/packages/jsActions/nanoflow-actions-native/src/geolocation/RequestLocationPermission.ts @@ -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 @@ -19,87 +18,68 @@ import type { GeolocationServiceStatic, AuthorizationResult } from "../../typing export async function RequestLocationPermission(): Promise { // BEGIN USER CODE - let reactNativeModule: typeof import("react-native") | undefined; - let geolocationModule: typeof import("@react-native-community/geolocation").default; - const hasPermissionIOS = async (): Promise => { 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 => { - 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 => { - 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; } @@ -107,49 +87,8 @@ export async function RequestLocationPermission(): Promise { return Promise.reject(new Error("Unsupported platform")); }; - const hasLocationPermissionForOldLibrary = async (): Promise => { - 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 {