import React, { useState, useRef, useEffect } from 'react'; import { View, Text, StyleSheet, TouchableOpacity, Image, Alert, Animated, Dimensions, ActivityIndicator, Linking, Platform, TextInput, KeyboardAvoidingView, ScrollView, } from 'react-native'; import { CameraView, useCameraPermissions } from 'expo-camera'; import * as Location from 'expo-location'; import { LinearGradient } from 'expo-linear-gradient'; import { useNavigation } from '@react-navigation/native'; import { Ionicons } from '@expo/vector-icons'; import { Button } from '../../components/ui/Button'; import { Card } from '../../components/ui/Card'; import { colors, spacing, borderRadius, typography } from '../../theme'; import { LocationData } from '../../types'; import { isLocationAccurate, checkLocationServicesEnabled, watchLocationWithGpsCheck, } from '../../services/locationService'; const { width, height } = Dimensions.get('window'); type CaptureScreenState = 'gps_check' | 'camera' | 'preview' | 'submitting'; export function CaptureScreen() { const navigation = useNavigation(); const cameraRef = useRef(null); const [permission, requestPermission] = useCameraPermissions(); const [locationPermission, setLocationPermission] = useState(false); const [screenState, setScreenState] = useState('gps_check'); const [capturedImage, setCapturedImage] = useState(null); const [location, setLocation] = useState(null); const [gpsAccuracy, setGpsAccuracy] = useState(null); const [isGpsEnabled, setIsGpsEnabled] = useState(null); const [isGpsReady, setIsGpsReady] = useState(false); const [description, setDescription] = useState(''); const pulseAnim = useRef(new Animated.Value(1)).current; const shutterAnim = useRef(new Animated.Value(1)).current; const cleanupRef = useRef<(() => void) | null>(null); useEffect(() => { initializeLocation(); return () => { if (cleanupRef.current) { cleanupRef.current(); } }; }, []); const initializeLocation = async () => { const gpsEnabled = await checkLocationServicesEnabled(); setIsGpsEnabled(gpsEnabled); if (!gpsEnabled) { setScreenState('gps_check'); return; } const { status } = await Location.requestForegroundPermissionsAsync(); setLocationPermission(status === 'granted'); if (status === 'granted') { startLocationTracking(); setScreenState('camera'); } }; const startLocationTracking = async () => { cleanupRef.current = await watchLocationWithGpsCheck( (newLocation) => { setGpsAccuracy(newLocation.accuracy); if (isLocationAccurate(newLocation.accuracy, 15)) { setIsGpsReady(true); setLocation(newLocation); } else { setIsGpsReady(false); } }, (enabled) => { setIsGpsEnabled(enabled); if (!enabled) { setScreenState('gps_check'); setIsGpsReady(false); } }, 15 ); }; useEffect(() => { if (screenState === 'camera' && !isGpsReady) { Animated.loop( Animated.sequence([ Animated.timing(pulseAnim, { toValue: 1.2, duration: 1000, useNativeDriver: true, }), Animated.timing(pulseAnim, { toValue: 1, duration: 1000, useNativeDriver: true, }), ]) ).start(); } else { pulseAnim.stopAnimation(); } }, [isGpsReady, screenState]); const handleOpenSettings = () => { if (Platform.OS === 'ios') { Linking.openURL('app-settings:'); } else { Linking.openSettings(); } }; const handleRetryGps = async () => { const enabled = await checkLocationServicesEnabled(); setIsGpsEnabled(enabled); if (enabled) { const { status } = await Location.requestForegroundPermissionsAsync(); if (status === 'granted') { startLocationTracking(); setScreenState('camera'); } } }; const handleCapture = async () => { if (!cameraRef.current || !isGpsReady || !location) { Alert.alert( 'GPS Not Ready', 'Please wait for GPS to lock (accuracy < 15m) before capturing. This is required to ensure accurate issue reporting.', [{ text: 'OK' }] ); return; } Animated.sequence([ Animated.timing(shutterAnim, { toValue: 0.8, duration: 50, useNativeDriver: true, }), Animated.timing(shutterAnim, { toValue: 1, duration: 50, useNativeDriver: true, }), ]).start(); try { const photo = await cameraRef.current.takePictureAsync({ quality: 0.8, base64: false, }); if (photo) { setCapturedImage(photo.uri); setScreenState('preview'); } } catch (error) { console.error('Camera capture error:', error); Alert.alert('Error', 'Failed to capture image'); } }; const handleRetake = () => { setCapturedImage(null); setDescription(''); setScreenState('camera'); }; const handleSubmit = () => { if (!capturedImage || !location) return; navigation.navigate('Processing', { imageUri: capturedImage, location: location, description: description.trim() || undefined, }); }; if (screenState === 'gps_check' || isGpsEnabled === false) { return ( GPS Required Location services must be enabled to report issues. This ensures accurate location data and prevents fraudulent reports. Precise location tracking Anti-fraud protection Accurate issue mapping