From 5d0279d7bcbf681890e8bfec582c1e7700749597 Mon Sep 17 00:00:00 2001 From: DylanDylann Date: Mon, 6 Jul 2026 16:55:30 +0700 Subject: [PATCH 1/3] Only read foreground location permissions without requesting them --- src/components/MapView/GPSMapView.tsx | 7 ++++--- src/components/MapView/MapView.tsx | 21 +++++++++++++++++---- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/src/components/MapView/GPSMapView.tsx b/src/components/MapView/GPSMapView.tsx index 7910e3d9b759..950bf3932161 100644 --- a/src/components/MapView/GPSMapView.tsx +++ b/src/components/MapView/GPSMapView.tsx @@ -16,7 +16,7 @@ import type {MapState} from '@rnmapbox/maps'; import {useFocusEffect} from '@react-navigation/native'; import Mapbox, {MarkerView} from '@rnmapbox/maps'; -import {getForegroundPermissionsAsync, requestForegroundPermissionsAsync} from 'expo-location'; +import {getForegroundPermissionsAsync} from 'expo-location'; import {useEffect, useRef, useState} from 'react'; import {View} from 'react-native'; import {useSharedValue} from 'react-native-reanimated'; @@ -55,14 +55,15 @@ function GPSMapView({accessToken, style, mapPadding, styleURL, pitchEnabled, way const [foregroundLocationPermissionsGranted, setForegroundLocationPermissionsGranted] = useState(null); - // Request foreground location permissions if not granted yet to determine if we can use followUserLocation prop on the map camera + // Check (never request) foreground location permissions to determine if we can use the followUserLocation prop on the map camera. + // Requesting here would trigger an OS prompt on open without a prior explicit user action, so we only read the current status. useFocusEffect(() => { if (isOffline) { return; } let ignore = false; - requestForegroundPermissionsAsync().then(({granted}) => { + getForegroundPermissionsAsync().then(({granted}) => { if (ignore) { return; } diff --git a/src/components/MapView/MapView.tsx b/src/components/MapView/MapView.tsx index 1d4531771ba3..bd018b96ca65 100644 --- a/src/components/MapView/MapView.tsx +++ b/src/components/MapView/MapView.tsx @@ -22,6 +22,7 @@ import type {MapState} from '@rnmapbox/maps'; import {useFocusEffect, useNavigation} from '@react-navigation/native'; import Mapbox, {MarkerView} from '@rnmapbox/maps'; +import {getForegroundPermissionsAsync} from 'expo-location'; import {memo, useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState} from 'react'; import {View} from 'react-native'; import {useSharedValue} from 'react-native-reanimated'; @@ -114,10 +115,22 @@ function MapView({ return; } - getCurrentPosition((params) => { - const currentCoords = {longitude: params.coords.longitude, latitude: params.coords.latitude}; - setUserLocation(currentCoords); - }, setCurrentPositionToInitialState); + // Only read the device location when permission is ALREADY granted. We never request it here, + // so opening the map cannot trigger an OS permission prompt without a prior explicit user action. + getForegroundPermissionsAsync().then(({granted}) => { + if (!granted) { + setCurrentPositionToInitialState(); + return; + } + + getCurrentPosition((params) => { + const currentCoords = { + longitude: params.coords.longitude, + latitude: params.coords.latitude, + }; + setUserLocation(currentCoords); + }, setCurrentPositionToInitialState); + }); }, [isOffline, shouldPanMapToCurrentPosition, setCurrentPositionToInitialState]), ); From 52fa828178c05db62757baff1f8ea7f74d930983 Mon Sep 17 00:00:00 2001 From: DylanDylann Date: Mon, 6 Jul 2026 17:07:15 +0700 Subject: [PATCH 2/3] Implement cleanup for location permission handling in MapView component --- src/components/MapView/MapView.tsx | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/components/MapView/MapView.tsx b/src/components/MapView/MapView.tsx index bd018b96ca65..64e5a9a05973 100644 --- a/src/components/MapView/MapView.tsx +++ b/src/components/MapView/MapView.tsx @@ -117,13 +117,20 @@ function MapView({ // Only read the device location when permission is ALREADY granted. We never request it here, // so opening the map cannot trigger an OS permission prompt without a prior explicit user action. + let ignore = false; getForegroundPermissionsAsync().then(({granted}) => { + if (ignore) { + return; + } if (!granted) { setCurrentPositionToInitialState(); return; } getCurrentPosition((params) => { + if (ignore) { + return; + } const currentCoords = { longitude: params.coords.longitude, latitude: params.coords.latitude, @@ -131,6 +138,10 @@ function MapView({ setUserLocation(currentCoords); }, setCurrentPositionToInitialState); }); + + return () => { + ignore = true; + }; }, [isOffline, shouldPanMapToCurrentPosition, setCurrentPositionToInitialState]), ); From a5cb887dd096e52ee8b617c16256db70db719b46 Mon Sep 17 00:00:00 2001 From: DylanDylann Date: Mon, 6 Jul 2026 17:26:18 +0700 Subject: [PATCH 3/3] passing error details to clear stale cached locations when access is denied. --- src/components/MapView/MapView.tsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/components/MapView/MapView.tsx b/src/components/MapView/MapView.tsx index 64e5a9a05973..acba06272d65 100644 --- a/src/components/MapView/MapView.tsx +++ b/src/components/MapView/MapView.tsx @@ -123,7 +123,11 @@ function MapView({ return; } if (!granted) { - setCurrentPositionToInitialState(); + // Pass the permission-denied error so any stale cached location is cleared and the map falls back to initialState. + setCurrentPositionToInitialState({ + code: GeolocationErrorCode.PERMISSION_DENIED, + message: 'User denied access to location.', + }); return; }