feat(import, geolocation): fix import and geoLocation issue
This commit is contained in:
parent
44f6050e60
commit
47f6b6aacf
@ -6,6 +6,20 @@ buildscript {
|
||||
targetSdkVersion = 36
|
||||
ndkVersion = "27.1.12297006"
|
||||
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 {
|
||||
google()
|
||||
@ -19,3 +33,13 @@ buildscript {
|
||||
}
|
||||
|
||||
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"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import React, { useState } from 'react';
|
||||
import { View, Text, TextInput, TouchableOpacity } from 'react-native';
|
||||
import { CustomInputProps } from './CustomInput.props';
|
||||
import { getStyles } from './CustomInput.styles';
|
||||
import { CustomInputProps } from './customInput.props';
|
||||
import { getStyles } from './customInput.styles';
|
||||
import { useAppTheme } from '@theme';
|
||||
|
||||
export const CustomInput: React.FC<CustomInputProps> = ({
|
||||
|
||||
@ -1,2 +1,2 @@
|
||||
export * from './CustomInput';
|
||||
export * from './CustomInput.props';
|
||||
export * from './customInput';
|
||||
export * from './customInput.props';
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import React from 'react';
|
||||
import { TouchableOpacity, Text, ActivityIndicator } from 'react-native';
|
||||
import { PrimaryButtonProps } from './PrimaryButton.props';
|
||||
import { styles } from './PrimaryButton.styles';
|
||||
import { styles } from './primaryButton.styles';
|
||||
import { colors } from '@theme';
|
||||
|
||||
export const PrimaryButton: React.FC<PrimaryButtonProps> = ({
|
||||
|
||||
@ -1,2 +1,2 @@
|
||||
export * from './PrimaryButton';
|
||||
export * from './PrimaryButton.props';
|
||||
export * from './primaryButton';
|
||||
export * from './primaryButton.props';
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import React from 'react';
|
||||
import { TouchableOpacity, Text } from 'react-native';
|
||||
import { SocialButtonProps } from './socialButton.props';
|
||||
import { getStyles } from './SocialButton.styles';
|
||||
import { getStyles } from './socialButton.styles';
|
||||
import { useAppTheme } from '@theme';
|
||||
import Svg, { Path } from 'react-native-svg';
|
||||
|
||||
|
||||
@ -1,2 +1,2 @@
|
||||
export * from './SocialButton';
|
||||
export * from './SocialButton.props';
|
||||
export * from './socialButton';
|
||||
export * from './socialButton.props';
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
export * from './CustomInput';
|
||||
export * from './PrimaryButton';
|
||||
export * from './SocialButton';
|
||||
export * from './customInput';
|
||||
export * from './primaryButton';
|
||||
export * from './socialButton';
|
||||
export * from './header';
|
||||
export * from './searchBar';
|
||||
export * from './providerCard';
|
||||
|
||||
@ -9,7 +9,7 @@ import { StackNavigationProp } from '@react-navigation/stack';
|
||||
import { getStyles } from './accountScreen.styles';
|
||||
import { Header, PrimaryButton } from '@components';
|
||||
import { useAppTheme } from '@theme';
|
||||
import { useAppDispatch, useAppSelector } from '../../../hooks/useAppDispatch';
|
||||
import { useAppDispatch, useAppSelector } from '../../../store';
|
||||
import { logout } from '../../../store/commonreducers/auth';
|
||||
import { AppStackParamList } from '../../../navigation/appStack';
|
||||
import { MainTabParamList } from '../../../navigation/mainTabNavigator';
|
||||
|
||||
@ -11,7 +11,7 @@ import { StackNavigationProp } from '@react-navigation/stack';
|
||||
import { getStyles } from './cartScreen.styles';
|
||||
import { Header, QuantitySelector, PrimaryButton } from '@components';
|
||||
import { useAppTheme } from '@theme';
|
||||
import { useAppDispatch, useAppSelector } from '../../../hooks/useAppDispatch';
|
||||
import { useAppDispatch, useAppSelector } from '../../../store';
|
||||
import {
|
||||
removeItem,
|
||||
applyCoupon,
|
||||
|
||||
@ -12,7 +12,7 @@ import { StackNavigationProp } from '@react-navigation/stack';
|
||||
import { getStyles } from './completeProfileScreen.styles';
|
||||
import { CustomInput, PrimaryButton } from '@components';
|
||||
import { useAppTheme } from '@theme';
|
||||
import { useAppDispatch } from '../../../hooks/useAppDispatch';
|
||||
import { useAppDispatch } from '../../../store';
|
||||
import { completeProfile } from '../../../store/commonreducers/auth';
|
||||
import { AuthStackParamList } from '../../../navigation/authStack';
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
export * from './LoginScreen';
|
||||
export * from './loginScreen';
|
||||
export * from './otpScreen';
|
||||
export * from './setLocationScreen';
|
||||
export * from './completeProfileScreen';
|
||||
|
||||
@ -3,7 +3,7 @@ import { View, Text } from 'react-native';
|
||||
import { getStyles } from './onboardingCompleteScreen.styles';
|
||||
import { PrimaryButton } from '@components';
|
||||
import { useAppTheme } from '@theme';
|
||||
import { useAppDispatch } from '../../../hooks/useAppDispatch';
|
||||
import { useAppDispatch } from '../../../store';
|
||||
import { completeOnboarding } from '../../../store/commonreducers/auth';
|
||||
|
||||
export const OnboardingCompleteScreen: React.FC = () => {
|
||||
|
||||
@ -11,7 +11,7 @@ import { StackNavigationProp } from '@react-navigation/stack';
|
||||
import { getStyles } from './otpScreen.styles';
|
||||
import { PrimaryButton } from '@components';
|
||||
import { useAppTheme } from '@theme';
|
||||
import { useAppDispatch } from '../../../hooks/useAppDispatch';
|
||||
import { useAppDispatch } from '../../../store';
|
||||
import { verifyOtp } from '../../../store/commonreducers/auth';
|
||||
import { AuthStackParamList } from '../../../navigation/authStack';
|
||||
|
||||
|
||||
@ -12,7 +12,7 @@ import { StackNavigationProp } from '@react-navigation/stack';
|
||||
import { getStyles } from './providerDetailsScreen.styles';
|
||||
import { CatalogItemRow } from '@components';
|
||||
import { useAppTheme } from '@theme';
|
||||
import { useAppDispatch, useAppSelector } from '../../../hooks/useAppDispatch';
|
||||
import { useAppDispatch, useAppSelector } from '../../../store';
|
||||
import { addItem } from '../../../store/commonreducers/cart';
|
||||
import { getProviderCatalogApi, getProvidersApi } from '../../../api/deliveryApi';
|
||||
import { CatalogItem, Provider } from '../../../interfaces';
|
||||
|
||||
@ -3,8 +3,8 @@ import {
|
||||
View,
|
||||
Text,
|
||||
TouchableOpacity,
|
||||
Platform,
|
||||
ActivityIndicator,
|
||||
InteractionManager,
|
||||
} from 'react-native';
|
||||
import MapView, { Marker, Region } from 'react-native-maps';
|
||||
import { useNavigation } from '@react-navigation/native';
|
||||
@ -17,6 +17,7 @@ import {
|
||||
DEFAULT_LOCATION,
|
||||
getCurrentLocationWithAddress,
|
||||
reverseGeocode,
|
||||
showPermissionDeniedAlert,
|
||||
LatLng,
|
||||
} from '../../../services/locationServices';
|
||||
|
||||
@ -29,6 +30,8 @@ export const SetLocationScreen: React.FC = () => {
|
||||
const styles = getStyles(colors);
|
||||
const navigation = useNavigation<NavProp>();
|
||||
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 [address, setAddress] = useState('Fetching your location…');
|
||||
@ -38,27 +41,43 @@ export const SetLocationScreen: React.FC = () => {
|
||||
// Fetch current location on mount
|
||||
// ------------------------------------------------------------------
|
||||
const fetchCurrentLocation = useCallback(async () => {
|
||||
if (!isMounted.current) return;
|
||||
setLoading(true);
|
||||
try {
|
||||
console.log('--------------');
|
||||
const result = await getCurrentLocationWithAddress();
|
||||
console.log('result', result);
|
||||
if (!isMounted.current) return;
|
||||
setCoords(result.coords);
|
||||
setAddress(result.address);
|
||||
|
||||
// Animate the map to the user's location
|
||||
mapRef.current?.animateToRegion({ ...result.coords, ...DELTA }, 600);
|
||||
} catch {
|
||||
// Permission denied or GPS unavailable — keep the default location
|
||||
console.log('--------error------');
|
||||
} catch (err: unknown) {
|
||||
const message = err instanceof Error ? err.message : '';
|
||||
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');
|
||||
} finally {
|
||||
setLoading(false);
|
||||
if (isMounted.current) setLoading(false);
|
||||
}
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
fetchCurrentLocation();
|
||||
// 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();
|
||||
});
|
||||
return () => {
|
||||
task.cancel();
|
||||
isMounted.current = false;
|
||||
};
|
||||
}, [fetchCurrentLocation]);
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
@ -83,8 +102,6 @@ export const SetLocationScreen: React.FC = () => {
|
||||
ref={mapRef}
|
||||
style={styles.map}
|
||||
initialRegion={{ ...DEFAULT_LOCATION, ...DELTA }}
|
||||
showsUserLocation
|
||||
showsMyLocationButton={true}
|
||||
onRegionChangeComplete={handleRegionChangeComplete}
|
||||
>
|
||||
<Marker
|
||||
|
||||
@ -46,13 +46,21 @@ export const requestLocationPermission = async (): Promise<boolean> => {
|
||||
}
|
||||
}
|
||||
|
||||
// Android
|
||||
// Android — check first to avoid showing the dialog when already granted
|
||||
try {
|
||||
const alreadyGranted = await PermissionsAndroid.check(
|
||||
PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
|
||||
);
|
||||
if (alreadyGranted) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const granted = await PermissionsAndroid.request(
|
||||
PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
|
||||
{
|
||||
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',
|
||||
buttonNegative: 'Cancel',
|
||||
buttonPositive: 'OK',
|
||||
@ -88,38 +96,47 @@ export const showPermissionDeniedAlert = (): void => {
|
||||
* Get the device's current GPS position.
|
||||
* Wraps the callback-based Geolocation API in a Promise.
|
||||
*/
|
||||
/**
|
||||
* Wraps Geolocation.getCurrentPosition in a Promise.
|
||||
* Tries high-accuracy first; falls back to low-accuracy on failure.
|
||||
*/
|
||||
const getPositionOnce = (highAccuracy: boolean): Promise<LatLng> =>
|
||||
new Promise<LatLng>((resolve, reject) => {
|
||||
Geolocation.getCurrentPosition(
|
||||
(position: GeoPosition) => {
|
||||
resolve({
|
||||
latitude: position.coords.latitude,
|
||||
longitude: position.coords.longitude,
|
||||
});
|
||||
},
|
||||
(error: GeoError) => {
|
||||
console.log('Geolocation error (highAccuracy=' + highAccuracy + '):', error);
|
||||
reject(error);
|
||||
},
|
||||
{
|
||||
enableHighAccuracy: highAccuracy,
|
||||
timeout: highAccuracy ? 5000 : 10000,
|
||||
maximumAge: 10000,
|
||||
forceRequestLocation: false, // avoid native dialog that can crash
|
||||
showLocationDialog: true,
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
export const getCurrentPosition = async (): Promise<LatLng> => {
|
||||
console.log('getCurrentPosition called');
|
||||
try {
|
||||
console.log('get current position');
|
||||
console.log('Geolocation:', Geolocation);
|
||||
console.log('getCurrentPosition:', Geolocation?.getCurrentPosition);
|
||||
|
||||
const location = await new Promise<LatLng>((resolve, reject) => {
|
||||
Geolocation.getCurrentPosition(
|
||||
(position: GeoPosition) => {
|
||||
resolve({
|
||||
latitude: position.coords.latitude,
|
||||
longitude: position.coords.longitude,
|
||||
});
|
||||
},
|
||||
(error: GeoError) => {
|
||||
console.log('Geolocation Error:', error);
|
||||
reject(error);
|
||||
},
|
||||
{
|
||||
enableHighAccuracy: true,
|
||||
timeout: 15000,
|
||||
maximumAge: 10000,
|
||||
forceRequestLocation: true,
|
||||
showLocationDialog: true,
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
return location;
|
||||
} catch (error) {
|
||||
console.error('Failed to get current position:', error);
|
||||
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;
|
||||
}
|
||||
|
||||
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';
|
||||
} catch (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';
|
||||
}
|
||||
};
|
||||
@ -166,9 +212,10 @@ export const reverseGeocode = async (coords: LatLng): Promise<string> => {
|
||||
export const getCurrentLocationWithAddress =
|
||||
async (): Promise<LocationResult> => {
|
||||
const hasPermission = await requestLocationPermission();
|
||||
|
||||
console.log('hasPermission', 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');
|
||||
}
|
||||
|
||||
|
||||
36
yarn.lock
36
yarn.lock
@ -1730,9 +1730,9 @@
|
||||
nullthrows "^1.1.1"
|
||||
|
||||
"@react-navigation/bottom-tabs@^7.18.3":
|
||||
version "7.18.4"
|
||||
resolved "https://registry.yarnpkg.com/@react-navigation/bottom-tabs/-/bottom-tabs-7.18.4.tgz#a0157c4d449bec8e5440967934c07ef27dca81fc"
|
||||
integrity sha512-L7D1tlPnIsXlp45iZCpAIRRKlZSuqM9WyUNFbooRTlcaaLDSlOr0X6cKbGmJmCvSOoqT6bAsQjCKfb5WRqhtQA==
|
||||
version "7.18.5"
|
||||
resolved "https://registry.yarnpkg.com/@react-navigation/bottom-tabs/-/bottom-tabs-7.18.5.tgz#b374eb01c564da7ed15cccd98205a044e16be904"
|
||||
integrity sha512-BiXkpEprKwE++p64qjfUOhsK+e0VW8r5FsLbDOp8Mcr/vhoT9aqX3a4pHCVQ8ug5YQW+QrgF4/XIXI99CZxMnQ==
|
||||
dependencies:
|
||||
"@react-navigation/elements" "^2.9.27"
|
||||
color "^4.2.3"
|
||||
@ -2459,9 +2459,9 @@ base64-js@^1.3.1, base64-js@^1.5.1:
|
||||
integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==
|
||||
|
||||
baseline-browser-mapping@^2.10.38:
|
||||
version "2.10.40"
|
||||
resolved "https://registry.yarnpkg.com/baseline-browser-mapping/-/baseline-browser-mapping-2.10.40.tgz#f372c8eb36ff4ad0b5e7ae467014abef124554ba"
|
||||
integrity sha512-BSSLZ9/Cjjv7Gtj5B68ZzXcXUg8iOf3fme+FCuh8rC/Go+Kmh8cox7M3A8dolou16s64QjLPOSdngh7GxXvkSw==
|
||||
version "2.10.41"
|
||||
resolved "https://registry.yarnpkg.com/baseline-browser-mapping/-/baseline-browser-mapping-2.10.41.tgz#86738e4aafb4392a32672642ddd092c0c2f80161"
|
||||
integrity sha512-WwS7MHhqGHHlaVsqRZnhvCEMS0owDX+SxRlve7JkuH7My1Ara3ZriTmCQupPfYjxMZ8I/tgxtJYr2t7taHaH4A==
|
||||
|
||||
bl@^4.1.0:
|
||||
version "4.1.0"
|
||||
@ -3065,9 +3065,9 @@ ee-first@1.1.1:
|
||||
integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==
|
||||
|
||||
electron-to-chromium@^1.5.376:
|
||||
version "1.5.383"
|
||||
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.383.tgz#5bd22306497d454103b289b0fef97260c56d0855"
|
||||
integrity sha512-I2484/KkAvl8lm9VyjH2JnbOIV0d/UCqT7gbzs6l+o6Vmn9wgB66uVcKX+Vk6HrXtY6fbWTOEXuv8waDTuFNCw==
|
||||
version "1.5.385"
|
||||
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.385.tgz#fbb900d4ddde6fab4651f37de6c1659a070bc68d"
|
||||
integrity sha512-78sa/M08MNAYHQfjoWMvOlKQqZ0ElhSm/L5HNUc96VZ3b+KvDVnngFm8sYQy0XrhTRgAhggHr5abA7yTvRdo4Q==
|
||||
|
||||
emittery@^0.13.1:
|
||||
version "0.13.1"
|
||||
@ -3555,9 +3555,9 @@ fast-levenshtein@^2.0.6:
|
||||
integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==
|
||||
|
||||
fast-xml-parser@^4.4.1:
|
||||
version "4.5.6"
|
||||
resolved "https://registry.yarnpkg.com/fast-xml-parser/-/fast-xml-parser-4.5.6.tgz#4ff57d4aca13a2d11aa42ad460495cf00f32b655"
|
||||
integrity sha512-Yd4vkROfJf8AuJrDIVMVmYfULKmIJszVsMv7Vo71aocsKgFxpdlpSHXSaInvyYfgw2PRuObQSW2GFpVMUjxu9A==
|
||||
version "4.5.7"
|
||||
resolved "https://registry.yarnpkg.com/fast-xml-parser/-/fast-xml-parser-4.5.7.tgz#ba3479a1eca8abf2cc3e54af254fae6f1f115021"
|
||||
integrity sha512-a6Qh1RMCNbSrU1+sAyAAZH3rTe+OaWJbNZIq0S+ifZciUUOQtlVxBJwoTUE2bYhysmG/RYyI5WJFIKdBahJdrQ==
|
||||
dependencies:
|
||||
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==
|
||||
|
||||
picomatch@^4.0.4:
|
||||
version "4.0.4"
|
||||
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-4.0.4.tgz#fd6f5e00a143086e074dffe4c924b8fb293b0589"
|
||||
integrity sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==
|
||||
version "4.0.5"
|
||||
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-4.0.5.tgz#51ea57a17d86f605f81039595fbc40ed06a55fab"
|
||||
integrity sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==
|
||||
|
||||
pirates@^4.0.4:
|
||||
version "4.0.7"
|
||||
@ -5825,9 +5825,9 @@ react-native-maps@^1.29.0:
|
||||
"@types/geojson" "^7946.0.13"
|
||||
|
||||
react-native-reanimated@^4.5.0:
|
||||
version "4.5.0"
|
||||
resolved "https://registry.yarnpkg.com/react-native-reanimated/-/react-native-reanimated-4.5.0.tgz#7029849859625a6247c7cf11161d5bef2cb99b12"
|
||||
integrity sha512-+iPfvK34PKKYP/p/4TaBliFkbfvjGDIvXuiiaxvISP5ip7sWegvlacwU/uAV6zNDSSmX0tDyER7PurPMKGDipA==
|
||||
version "4.5.1"
|
||||
resolved "https://registry.yarnpkg.com/react-native-reanimated/-/react-native-reanimated-4.5.1.tgz#be81ed3a96bf70baeeccdc24d3350883099b7dd3"
|
||||
integrity sha512-RnMvtDuR+68ig864gAvZCOdZehqhC5rFmMo0kn+ARfgVSTvFeF6IFLBVgMPUu0KwihaapEyW24WRi6nEyy1kSA==
|
||||
dependencies:
|
||||
react-native-is-edge-to-edge "^1.3.1"
|
||||
semver "^7.7.3"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user