feat(import, geolocation): fix import and geoLocation issue

This commit is contained in:
uttam 2026-07-03 18:03:10 +05:30
parent 44f6050e60
commit 47f6b6aacf
18 changed files with 168 additions and 80 deletions

View File

@ -6,6 +6,20 @@ buildscript {
targetSdkVersion = 36 targetSdkVersion = 36
ndkVersion = "27.1.12297006" ndkVersion = "27.1.12297006"
kotlinVersion = "2.1.20" kotlinVersion = "2.1.20"
// ---------------------------------------------------------------
// Pin Google Play Services versions so all libraries use the same
// artifact. react-native-geolocation-service defaults to 18.0.0
// but react-native-maps requires 21.x where FusedLocationProvider-
// Client is an interface, not a class. Using two different versions
// causes IncompatibleClassChangeError and a hard app crash.
// ---------------------------------------------------------------
googlePlayServicesVersion = "21.3.0" // used by geolocation-service
playServicesVersion = "21.3.0" // fallback alias
playServicesLocationVersion = "21.3.0" // used by geolocation-service
googlePlayServicesLocationVersion = "21.3.0" // used by react-native-maps
googlePlayServicesMapsVersion = "19.1.0"
googlePlayServicesBaseVersion = "18.5.0"
} }
repositories { repositories {
google() google()
@ -19,3 +33,13 @@ buildscript {
} }
apply plugin: "com.facebook.react.rootproject" apply plugin: "com.facebook.react.rootproject"
// Force a single version of play-services-location across ALL modules
// to prevent IncompatibleClassChangeError at runtime.
subprojects {
configurations.all {
resolutionStrategy {
force "com.google.android.gms:play-services-location:21.3.0"
}
}
}

View File

@ -1,7 +1,7 @@
import React, { useState } from 'react'; import React, { useState } from 'react';
import { View, Text, TextInput, TouchableOpacity } from 'react-native'; import { View, Text, TextInput, TouchableOpacity } from 'react-native';
import { CustomInputProps } from './CustomInput.props'; import { CustomInputProps } from './customInput.props';
import { getStyles } from './CustomInput.styles'; import { getStyles } from './customInput.styles';
import { useAppTheme } from '@theme'; import { useAppTheme } from '@theme';
export const CustomInput: React.FC<CustomInputProps> = ({ export const CustomInput: React.FC<CustomInputProps> = ({

View File

@ -1,2 +1,2 @@
export * from './CustomInput'; export * from './customInput';
export * from './CustomInput.props'; export * from './customInput.props';

View File

@ -1,7 +1,7 @@
import React from 'react'; import React from 'react';
import { TouchableOpacity, Text, ActivityIndicator } from 'react-native'; import { TouchableOpacity, Text, ActivityIndicator } from 'react-native';
import { PrimaryButtonProps } from './PrimaryButton.props'; import { PrimaryButtonProps } from './PrimaryButton.props';
import { styles } from './PrimaryButton.styles'; import { styles } from './primaryButton.styles';
import { colors } from '@theme'; import { colors } from '@theme';
export const PrimaryButton: React.FC<PrimaryButtonProps> = ({ export const PrimaryButton: React.FC<PrimaryButtonProps> = ({

View File

@ -1,2 +1,2 @@
export * from './PrimaryButton'; export * from './primaryButton';
export * from './PrimaryButton.props'; export * from './primaryButton.props';

View File

@ -1,7 +1,7 @@
import React from 'react'; import React from 'react';
import { TouchableOpacity, Text } from 'react-native'; import { TouchableOpacity, Text } from 'react-native';
import { SocialButtonProps } from './socialButton.props'; import { SocialButtonProps } from './socialButton.props';
import { getStyles } from './SocialButton.styles'; import { getStyles } from './socialButton.styles';
import { useAppTheme } from '@theme'; import { useAppTheme } from '@theme';
import Svg, { Path } from 'react-native-svg'; import Svg, { Path } from 'react-native-svg';

View File

@ -1,2 +1,2 @@
export * from './SocialButton'; export * from './socialButton';
export * from './SocialButton.props'; export * from './socialButton.props';

View File

@ -1,6 +1,6 @@
export * from './CustomInput'; export * from './customInput';
export * from './PrimaryButton'; export * from './primaryButton';
export * from './SocialButton'; export * from './socialButton';
export * from './header'; export * from './header';
export * from './searchBar'; export * from './searchBar';
export * from './providerCard'; export * from './providerCard';

View File

@ -9,7 +9,7 @@ import { StackNavigationProp } from '@react-navigation/stack';
import { getStyles } from './accountScreen.styles'; import { getStyles } from './accountScreen.styles';
import { Header, PrimaryButton } from '@components'; import { Header, PrimaryButton } from '@components';
import { useAppTheme } from '@theme'; import { useAppTheme } from '@theme';
import { useAppDispatch, useAppSelector } from '../../../hooks/useAppDispatch'; import { useAppDispatch, useAppSelector } from '../../../store';
import { logout } from '../../../store/commonreducers/auth'; import { logout } from '../../../store/commonreducers/auth';
import { AppStackParamList } from '../../../navigation/appStack'; import { AppStackParamList } from '../../../navigation/appStack';
import { MainTabParamList } from '../../../navigation/mainTabNavigator'; import { MainTabParamList } from '../../../navigation/mainTabNavigator';

View File

@ -11,7 +11,7 @@ import { StackNavigationProp } from '@react-navigation/stack';
import { getStyles } from './cartScreen.styles'; import { getStyles } from './cartScreen.styles';
import { Header, QuantitySelector, PrimaryButton } from '@components'; import { Header, QuantitySelector, PrimaryButton } from '@components';
import { useAppTheme } from '@theme'; import { useAppTheme } from '@theme';
import { useAppDispatch, useAppSelector } from '../../../hooks/useAppDispatch'; import { useAppDispatch, useAppSelector } from '../../../store';
import { import {
removeItem, removeItem,
applyCoupon, applyCoupon,

View File

@ -12,7 +12,7 @@ import { StackNavigationProp } from '@react-navigation/stack';
import { getStyles } from './completeProfileScreen.styles'; import { getStyles } from './completeProfileScreen.styles';
import { CustomInput, PrimaryButton } from '@components'; import { CustomInput, PrimaryButton } from '@components';
import { useAppTheme } from '@theme'; import { useAppTheme } from '@theme';
import { useAppDispatch } from '../../../hooks/useAppDispatch'; import { useAppDispatch } from '../../../store';
import { completeProfile } from '../../../store/commonreducers/auth'; import { completeProfile } from '../../../store/commonreducers/auth';
import { AuthStackParamList } from '../../../navigation/authStack'; import { AuthStackParamList } from '../../../navigation/authStack';

View File

@ -1,4 +1,4 @@
export * from './LoginScreen'; export * from './loginScreen';
export * from './otpScreen'; export * from './otpScreen';
export * from './setLocationScreen'; export * from './setLocationScreen';
export * from './completeProfileScreen'; export * from './completeProfileScreen';

View File

@ -3,7 +3,7 @@ import { View, Text } from 'react-native';
import { getStyles } from './onboardingCompleteScreen.styles'; import { getStyles } from './onboardingCompleteScreen.styles';
import { PrimaryButton } from '@components'; import { PrimaryButton } from '@components';
import { useAppTheme } from '@theme'; import { useAppTheme } from '@theme';
import { useAppDispatch } from '../../../hooks/useAppDispatch'; import { useAppDispatch } from '../../../store';
import { completeOnboarding } from '../../../store/commonreducers/auth'; import { completeOnboarding } from '../../../store/commonreducers/auth';
export const OnboardingCompleteScreen: React.FC = () => { export const OnboardingCompleteScreen: React.FC = () => {

View File

@ -11,7 +11,7 @@ import { StackNavigationProp } from '@react-navigation/stack';
import { getStyles } from './otpScreen.styles'; import { getStyles } from './otpScreen.styles';
import { PrimaryButton } from '@components'; import { PrimaryButton } from '@components';
import { useAppTheme } from '@theme'; import { useAppTheme } from '@theme';
import { useAppDispatch } from '../../../hooks/useAppDispatch'; import { useAppDispatch } from '../../../store';
import { verifyOtp } from '../../../store/commonreducers/auth'; import { verifyOtp } from '../../../store/commonreducers/auth';
import { AuthStackParamList } from '../../../navigation/authStack'; import { AuthStackParamList } from '../../../navigation/authStack';

View File

@ -12,7 +12,7 @@ import { StackNavigationProp } from '@react-navigation/stack';
import { getStyles } from './providerDetailsScreen.styles'; import { getStyles } from './providerDetailsScreen.styles';
import { CatalogItemRow } from '@components'; import { CatalogItemRow } from '@components';
import { useAppTheme } from '@theme'; import { useAppTheme } from '@theme';
import { useAppDispatch, useAppSelector } from '../../../hooks/useAppDispatch'; import { useAppDispatch, useAppSelector } from '../../../store';
import { addItem } from '../../../store/commonreducers/cart'; import { addItem } from '../../../store/commonreducers/cart';
import { getProviderCatalogApi, getProvidersApi } from '../../../api/deliveryApi'; import { getProviderCatalogApi, getProvidersApi } from '../../../api/deliveryApi';
import { CatalogItem, Provider } from '../../../interfaces'; import { CatalogItem, Provider } from '../../../interfaces';

View File

@ -3,8 +3,8 @@ import {
View, View,
Text, Text,
TouchableOpacity, TouchableOpacity,
Platform,
ActivityIndicator, ActivityIndicator,
InteractionManager,
} from 'react-native'; } from 'react-native';
import MapView, { Marker, Region } from 'react-native-maps'; import MapView, { Marker, Region } from 'react-native-maps';
import { useNavigation } from '@react-navigation/native'; import { useNavigation } from '@react-navigation/native';
@ -17,6 +17,7 @@ import {
DEFAULT_LOCATION, DEFAULT_LOCATION,
getCurrentLocationWithAddress, getCurrentLocationWithAddress,
reverseGeocode, reverseGeocode,
showPermissionDeniedAlert,
LatLng, LatLng,
} from '../../../services/locationServices'; } from '../../../services/locationServices';
@ -29,6 +30,8 @@ export const SetLocationScreen: React.FC = () => {
const styles = getStyles(colors); const styles = getStyles(colors);
const navigation = useNavigation<NavProp>(); const navigation = useNavigation<NavProp>();
const mapRef = useRef<MapView>(null); const mapRef = useRef<MapView>(null);
// Guard: never call setState after the component has unmounted
const isMounted = useRef(true);
const [coords, setCoords] = useState<LatLng>(DEFAULT_LOCATION); const [coords, setCoords] = useState<LatLng>(DEFAULT_LOCATION);
const [address, setAddress] = useState('Fetching your location…'); const [address, setAddress] = useState('Fetching your location…');
@ -38,27 +41,43 @@ export const SetLocationScreen: React.FC = () => {
// Fetch current location on mount // Fetch current location on mount
// ------------------------------------------------------------------ // ------------------------------------------------------------------
const fetchCurrentLocation = useCallback(async () => { const fetchCurrentLocation = useCallback(async () => {
if (!isMounted.current) return;
setLoading(true); setLoading(true);
try { try {
console.log('--------------'); console.log('--------------');
const result = await getCurrentLocationWithAddress(); const result = await getCurrentLocationWithAddress();
console.log('result', result); console.log('result', result);
if (!isMounted.current) return;
setCoords(result.coords); setCoords(result.coords);
setAddress(result.address); setAddress(result.address);
// Animate the map to the user's location // Animate the map to the user's location
mapRef.current?.animateToRegion({ ...result.coords, ...DELTA }, 600); mapRef.current?.animateToRegion({ ...result.coords, ...DELTA }, 600);
} catch { } catch (err: unknown) {
// Permission denied or GPS unavailable — keep the default location const message = err instanceof Error ? err.message : '';
console.log('--------error------'); if (message === 'Location permission denied') {
// Show the alert here — safe, outside the Promise chain
showPermissionDeniedAlert();
}
console.log('--------error------', err);
if (!isMounted.current) return;
setAddress('Could not determine location'); setAddress('Could not determine location');
} finally { } finally {
setLoading(false); if (isMounted.current) setLoading(false);
} }
}, []); }, []);
useEffect(() => { useEffect(() => {
// Wait for the screen-transition animation to fully finish before
// calling PermissionsAndroid.request(). Calling it while the Activity
// is still transitioning causes a native crash on Android.
const task = InteractionManager.runAfterInteractions(() => {
fetchCurrentLocation(); fetchCurrentLocation();
});
return () => {
task.cancel();
isMounted.current = false;
};
}, [fetchCurrentLocation]); }, [fetchCurrentLocation]);
// ------------------------------------------------------------------ // ------------------------------------------------------------------
@ -83,8 +102,6 @@ export const SetLocationScreen: React.FC = () => {
ref={mapRef} ref={mapRef}
style={styles.map} style={styles.map}
initialRegion={{ ...DEFAULT_LOCATION, ...DELTA }} initialRegion={{ ...DEFAULT_LOCATION, ...DELTA }}
showsUserLocation
showsMyLocationButton={true}
onRegionChangeComplete={handleRegionChangeComplete} onRegionChangeComplete={handleRegionChangeComplete}
> >
<Marker <Marker

View File

@ -46,13 +46,21 @@ export const requestLocationPermission = async (): Promise<boolean> => {
} }
} }
// Android // Android — check first to avoid showing the dialog when already granted
try { try {
const alreadyGranted = await PermissionsAndroid.check(
PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
);
if (alreadyGranted) {
return true;
}
const granted = await PermissionsAndroid.request( const granted = await PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION, PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
{ {
title: 'Location Permission', title: 'Location Permission',
message: 'This app needs access to your location to set it on the map.', message:
'This app needs access to your location to set it on the map.',
buttonNeutral: 'Ask Me Later', buttonNeutral: 'Ask Me Later',
buttonNegative: 'Cancel', buttonNegative: 'Cancel',
buttonPositive: 'OK', buttonPositive: 'OK',
@ -88,13 +96,12 @@ export const showPermissionDeniedAlert = (): void => {
* Get the device's current GPS position. * Get the device's current GPS position.
* Wraps the callback-based Geolocation API in a Promise. * Wraps the callback-based Geolocation API in a Promise.
*/ */
export const getCurrentPosition = async (): Promise<LatLng> => { /**
try { * Wraps Geolocation.getCurrentPosition in a Promise.
console.log('get current position'); * Tries high-accuracy first; falls back to low-accuracy on failure.
console.log('Geolocation:', Geolocation); */
console.log('getCurrentPosition:', Geolocation?.getCurrentPosition); const getPositionOnce = (highAccuracy: boolean): Promise<LatLng> =>
new Promise<LatLng>((resolve, reject) => {
const location = await new Promise<LatLng>((resolve, reject) => {
Geolocation.getCurrentPosition( Geolocation.getCurrentPosition(
(position: GeoPosition) => { (position: GeoPosition) => {
resolve({ resolve({
@ -103,23 +110,33 @@ export const getCurrentPosition = async (): Promise<LatLng> => {
}); });
}, },
(error: GeoError) => { (error: GeoError) => {
console.log('Geolocation Error:', error); console.log('Geolocation error (highAccuracy=' + highAccuracy + '):', error);
reject(error); reject(error);
}, },
{ {
enableHighAccuracy: true, enableHighAccuracy: highAccuracy,
timeout: 15000, timeout: highAccuracy ? 5000 : 10000,
maximumAge: 10000, maximumAge: 10000,
forceRequestLocation: true, forceRequestLocation: false, // avoid native dialog that can crash
showLocationDialog: true, showLocationDialog: true,
}, },
); );
}); });
return location; export const getCurrentPosition = async (): Promise<LatLng> => {
} catch (error) { console.log('getCurrentPosition called');
console.error('Failed to get current position:', error); try {
throw error; // First attempt: high accuracy (GPS)
return await getPositionOnce(true);
} catch (highAccuracyError) {
console.warn('High-accuracy location failed, retrying with low accuracy…', highAccuracyError);
try {
// Fallback: network / cell-tower accuracy
return await getPositionOnce(false);
} catch (lowAccuracyError) {
console.error('Failed to get current position:', lowAccuracyError);
throw lowAccuracyError;
}
} }
}; };
@ -146,9 +163,38 @@ export const reverseGeocode = async (coords: LatLng): Promise<string> => {
return data.results[0].formatted_address; return data.results[0].formatted_address;
} }
console.warn('Google Maps Geocoding failed:', data.status, data.error_message || '');
// Fallback to OpenStreetMap Nominatim
const osmUrl = `https://nominatim.openstreetmap.org/reverse?format=jsonv2&lat=${coords.latitude}&lon=${coords.longitude}`;
const osmResponse = await fetch(osmUrl, {
headers: {
'User-Agent': 'SGDeliveryCustomerApp/1.0',
},
});
const osmData = await osmResponse.json();
if (osmData && osmData.display_name) {
return osmData.display_name;
}
return 'Address not found'; return 'Address not found';
} catch (error) { } catch (error) {
console.log('reverseGeocode error', error); console.log('reverseGeocode error', error);
try {
// Fallback to OpenStreetMap Nominatim on catch
const osmUrl = `https://nominatim.openstreetmap.org/reverse?format=jsonv2&lat=${coords.latitude}&lon=${coords.longitude}`;
const osmResponse = await fetch(osmUrl, {
headers: {
'User-Agent': 'SGDeliveryCustomerApp/1.0',
},
});
const osmData = await osmResponse.json();
if (osmData && osmData.display_name) {
return osmData.display_name;
}
} catch (osmError) {
console.log('OSM fallback error', osmError);
}
return 'Unable to fetch address'; return 'Unable to fetch address';
} }
}; };
@ -166,9 +212,10 @@ export const reverseGeocode = async (coords: LatLng): Promise<string> => {
export const getCurrentLocationWithAddress = export const getCurrentLocationWithAddress =
async (): Promise<LocationResult> => { async (): Promise<LocationResult> => {
const hasPermission = await requestLocationPermission(); const hasPermission = await requestLocationPermission();
console.log('hasPermission', hasPermission);
if (!hasPermission) { if (!hasPermission) {
showPermissionDeniedAlert(); // Alert shown by the caller so it doesn't fire inside a Promise chain
// on mount (which can cause a crash on some Android versions).
throw new Error('Location permission denied'); throw new Error('Location permission denied');
} }

View File

@ -1730,9 +1730,9 @@
nullthrows "^1.1.1" nullthrows "^1.1.1"
"@react-navigation/bottom-tabs@^7.18.3": "@react-navigation/bottom-tabs@^7.18.3":
version "7.18.4" version "7.18.5"
resolved "https://registry.yarnpkg.com/@react-navigation/bottom-tabs/-/bottom-tabs-7.18.4.tgz#a0157c4d449bec8e5440967934c07ef27dca81fc" resolved "https://registry.yarnpkg.com/@react-navigation/bottom-tabs/-/bottom-tabs-7.18.5.tgz#b374eb01c564da7ed15cccd98205a044e16be904"
integrity sha512-L7D1tlPnIsXlp45iZCpAIRRKlZSuqM9WyUNFbooRTlcaaLDSlOr0X6cKbGmJmCvSOoqT6bAsQjCKfb5WRqhtQA== integrity sha512-BiXkpEprKwE++p64qjfUOhsK+e0VW8r5FsLbDOp8Mcr/vhoT9aqX3a4pHCVQ8ug5YQW+QrgF4/XIXI99CZxMnQ==
dependencies: dependencies:
"@react-navigation/elements" "^2.9.27" "@react-navigation/elements" "^2.9.27"
color "^4.2.3" color "^4.2.3"
@ -2459,9 +2459,9 @@ base64-js@^1.3.1, base64-js@^1.5.1:
integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==
baseline-browser-mapping@^2.10.38: baseline-browser-mapping@^2.10.38:
version "2.10.40" version "2.10.41"
resolved "https://registry.yarnpkg.com/baseline-browser-mapping/-/baseline-browser-mapping-2.10.40.tgz#f372c8eb36ff4ad0b5e7ae467014abef124554ba" resolved "https://registry.yarnpkg.com/baseline-browser-mapping/-/baseline-browser-mapping-2.10.41.tgz#86738e4aafb4392a32672642ddd092c0c2f80161"
integrity sha512-BSSLZ9/Cjjv7Gtj5B68ZzXcXUg8iOf3fme+FCuh8rC/Go+Kmh8cox7M3A8dolou16s64QjLPOSdngh7GxXvkSw== integrity sha512-WwS7MHhqGHHlaVsqRZnhvCEMS0owDX+SxRlve7JkuH7My1Ara3ZriTmCQupPfYjxMZ8I/tgxtJYr2t7taHaH4A==
bl@^4.1.0: bl@^4.1.0:
version "4.1.0" version "4.1.0"
@ -3065,9 +3065,9 @@ ee-first@1.1.1:
integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==
electron-to-chromium@^1.5.376: electron-to-chromium@^1.5.376:
version "1.5.383" version "1.5.385"
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.383.tgz#5bd22306497d454103b289b0fef97260c56d0855" resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.385.tgz#fbb900d4ddde6fab4651f37de6c1659a070bc68d"
integrity sha512-I2484/KkAvl8lm9VyjH2JnbOIV0d/UCqT7gbzs6l+o6Vmn9wgB66uVcKX+Vk6HrXtY6fbWTOEXuv8waDTuFNCw== integrity sha512-78sa/M08MNAYHQfjoWMvOlKQqZ0ElhSm/L5HNUc96VZ3b+KvDVnngFm8sYQy0XrhTRgAhggHr5abA7yTvRdo4Q==
emittery@^0.13.1: emittery@^0.13.1:
version "0.13.1" version "0.13.1"
@ -3555,9 +3555,9 @@ fast-levenshtein@^2.0.6:
integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==
fast-xml-parser@^4.4.1: fast-xml-parser@^4.4.1:
version "4.5.6" version "4.5.7"
resolved "https://registry.yarnpkg.com/fast-xml-parser/-/fast-xml-parser-4.5.6.tgz#4ff57d4aca13a2d11aa42ad460495cf00f32b655" resolved "https://registry.yarnpkg.com/fast-xml-parser/-/fast-xml-parser-4.5.7.tgz#ba3479a1eca8abf2cc3e54af254fae6f1f115021"
integrity sha512-Yd4vkROfJf8AuJrDIVMVmYfULKmIJszVsMv7Vo71aocsKgFxpdlpSHXSaInvyYfgw2PRuObQSW2GFpVMUjxu9A== integrity sha512-a6Qh1RMCNbSrU1+sAyAAZH3rTe+OaWJbNZIq0S+ifZciUUOQtlVxBJwoTUE2bYhysmG/RYyI5WJFIKdBahJdrQ==
dependencies: dependencies:
strnum "^1.0.5" strnum "^1.0.5"
@ -5638,9 +5638,9 @@ picomatch@^2.0.4, picomatch@^2.2.3, picomatch@^2.3.1:
integrity sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA== integrity sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==
picomatch@^4.0.4: picomatch@^4.0.4:
version "4.0.4" version "4.0.5"
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-4.0.4.tgz#fd6f5e00a143086e074dffe4c924b8fb293b0589" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-4.0.5.tgz#51ea57a17d86f605f81039595fbc40ed06a55fab"
integrity sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A== integrity sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==
pirates@^4.0.4: pirates@^4.0.4:
version "4.0.7" version "4.0.7"
@ -5825,9 +5825,9 @@ react-native-maps@^1.29.0:
"@types/geojson" "^7946.0.13" "@types/geojson" "^7946.0.13"
react-native-reanimated@^4.5.0: react-native-reanimated@^4.5.0:
version "4.5.0" version "4.5.1"
resolved "https://registry.yarnpkg.com/react-native-reanimated/-/react-native-reanimated-4.5.0.tgz#7029849859625a6247c7cf11161d5bef2cb99b12" resolved "https://registry.yarnpkg.com/react-native-reanimated/-/react-native-reanimated-4.5.1.tgz#be81ed3a96bf70baeeccdc24d3350883099b7dd3"
integrity sha512-+iPfvK34PKKYP/p/4TaBliFkbfvjGDIvXuiiaxvISP5ip7sWegvlacwU/uAV6zNDSSmX0tDyER7PurPMKGDipA== integrity sha512-RnMvtDuR+68ig864gAvZCOdZehqhC5rFmMo0kn+ARfgVSTvFeF6IFLBVgMPUu0KwihaapEyW24WRi6nEyy1kSA==
dependencies: dependencies:
react-native-is-edge-to-edge "^1.3.1" react-native-is-edge-to-edge "^1.3.1"
semver "^7.7.3" semver "^7.7.3"