import React, { useState, useEffect, useRef, useCallback } from 'react'; import { View, Text, TouchableOpacity, ActivityIndicator, InteractionManager, } from 'react-native'; import MapView, { Marker, Region } from 'react-native-maps'; import { useNavigation } from '@react-navigation/native'; import { StackNavigationProp } from '@react-navigation/stack'; import { getStyles } from './setLocationScreen.styles'; import { PrimaryButton } from '@components'; import { useAppTheme } from '@theme'; import { AuthStackParamList } from '../../../navigation/authStack'; import { DEFAULT_LOCATION, getCurrentLocationWithAddress, reverseGeocode, showPermissionDeniedAlert, LatLng, } from '../../../services/locationServices'; type NavProp = StackNavigationProp; const DELTA = { latitudeDelta: 0.006, longitudeDelta: 0.006 }; export const SetLocationScreen: React.FC = () => { const { colors } = useAppTheme(); const styles = getStyles(colors); const navigation = useNavigation(); const mapRef = useRef(null); // Guard: never call setState after the component has unmounted const isMounted = useRef(true); const [coords, setCoords] = useState(DEFAULT_LOCATION); const [address, setAddress] = useState('Fetching your location…'); const [loading, setLoading] = useState(true); // ------------------------------------------------------------------ // 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 (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 { if (isMounted.current) setLoading(false); } }, []); 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(); }); return () => { task.cancel(); isMounted.current = false; }; }, [fetchCurrentLocation]); // ------------------------------------------------------------------ // When user drags the map, update the marker + address // ------------------------------------------------------------------ const handleRegionChangeComplete = useCallback(async (region: Region) => { const newCoords: LatLng = { latitude: region.latitude, longitude: region.longitude, }; setCoords(newCoords); setAddress('Fetching address…'); const newAddress = await reverseGeocode(newCoords); setAddress(newAddress); }, []); return ( {/* ---------- Map ---------- */} {/* ---------- "Locate me" floating button ---------- */} 📍 {/* ---------- Bottom sheet ---------- */} 📍 My Location {loading ? ( ) : ( {address} )} Change navigation.navigate('CompleteProfileScreen')} style={styles.confirmButton} /> navigation.navigate('CompleteProfileScreen')} activeOpacity={0.7} > Enter address manually ); };