Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUG 🐛] app crashes when isActive is true #104

Open
DikshantDML401 opened this issue Oct 25, 2024 · 3 comments
Open

[BUG 🐛] app crashes when isActive is true #104

DikshantDML401 opened this issue Oct 25, 2024 · 3 comments
Labels
bug Something isn't working

Comments

@DikshantDML401
Copy link

import {
Animated,
Dimensions,
Image,
PermissionsAndroid,
Platform,
StyleSheet,
Text,
TouchableOpacity,
View,
} from 'react-native';
import {useEffect, useRef, useState} from 'react';
import {
Frame,
useCameraDevice,
Camera as VCamera,
} from 'react-native-vision-camera';
import {
Face,
Camera,
FaceDetectionOptions,
} from 'react-native-vision-camera-face-detector';
import CustomButton from '../components/Button';
import Container from '../components/Container';
import AppHeader from '../components/AppHeader';
import Icon from 'react-native-vector-icons/Feather';
import {appHeaderIcon, CameraIcon, warningLogo} from '../utils/storage/icon';
import {moderateScale} from '../theme/Responsive';
import {colors} from '../theme';
import ImagePickerComponent from '../components/ImagePickerComponent';
import {launchImageLibrary} from 'react-native-image-picker';
import {setSelectedImage} from '../redux/slice/imagePickerSlice';
import {useDispatch} from 'react-redux';
import Toast from 'react-native-toast-message';
import {useNavigation} from '@react-navigation/native';
import LinearGradient from 'react-native-linear-gradient';
import PreviewPictures from '../components/PreviewPictures';

const {width: SCREEN_WIDTH, height: SCREEN_HEIGHT} = Dimensions.get('window');
const GUIDE_BOX_WIDTH = SCREEN_WIDTH * 0.7;
const GUIDE_BOX_HEIGHT = GUIDE_BOX_WIDTH * 1.3;
const GUIDE_BOX_TOP = (SCREEN_HEIGHT - GUIDE_BOX_HEIGHT) / 2;
const GUIDE_BOX_LEFT = (SCREEN_WIDTH - GUIDE_BOX_WIDTH) / 2;

const FaceOverlay = ({face, isFaceInPosition}: any) => {
if (!face) return null;

const {bounds} = face;

// Calculate the center point of the guide box
const guideBoxCenterX = GUIDE_BOX_LEFT + GUIDE_BOX_WIDTH / 2;
const guideBoxCenterY = GUIDE_BOX_TOP + GUIDE_BOX_HEIGHT / 2;

// Calculate the size of the circle based on the guide box dimensions
const circleSize = Math.min(GUIDE_BOX_WIDTH * 0.8, GUIDE_BOX_HEIGHT * 0.8);

// Calculate the position to center the circle
const circleLeft = guideBoxCenterX - circleSize / 1;
const circleTop = guideBoxCenterY - circleSize / 2;

// Scale factor for face bounds
const scaleFactor = Platform.OS === 'ios' ? 0.8 : 1;

return (
<Animated.View
style={[
styles.faceOverlay,
{
left: Platform.OS === 'ios' ? circleLeft : bounds.x * scaleFactor,
top: Platform.OS === 'ios' ? circleTop : bounds.y * scaleFactor,
width:
Platform.OS === 'ios' ? circleSize : bounds.width * scaleFactor,
height:
Platform.OS === 'ios' ? circleSize : bounds.height * scaleFactor,
borderColor: isFaceInPosition ? 'green' : 'yellow',
},
]}
/>
);
};

export default function Home() {
const dispatch = useDispatch();
const navigation = useNavigation();
const [hasPermission, setHasPermission] = useState<boolean | null>(null);
const [isCameraOpen, setIsCameraOpen] = useState(false);
const cameraRef = useRef(null);
const [capturedPhoto, setCapturedPhoto] = useState(null);
const [photoTaken, setPhotoTaken] = useState(false);
const [currentFace, setCurrentFace] = useState(null);
const [isCapturing, setIsCapturing] = useState(false);
const [isFaceInPosition, setIsFaceInPosition] = useState(false);
// const [tempImageData, setTempImageData] = useState<{
// uri: string;
// type: string;
// name: string;
// } | null>(null);
const device = useCameraDevice('front');
// const {faces, error, status} = useFacesInPhoto(tempImageData?.uri || '');
const faceDetectionOptions = useRef({
performanceMode: 'fast',
contourMode: 'all',
trackingEnabled: true,
}).current;

useEffect(() => {
(async () => {
const isPermission = await VCamera.requestCameraPermission();
if (isPermission === 'granted') {
console.log('granted');
await requestGalleryPermission();
}
setHasPermission(isPermission === 'granted');
})();
}, []);
const showToastError = (error: any) => {
console.log('Toast error triggered with:', error);
Toast.show({
type: 'error',
text1: 'Error',
text2:
typeof error === 'string'
? error
: 'Face should cover at least 50% of the photo, try again!',
});
};
function handleFacesDetection(faces: Face[], frame: Frame) {
if (faces.length >= 1) {
const face = faces[0];
const {bounds} = face;

  const isFaceCentered =
    bounds.x >= GUIDE_BOX_LEFT &&
    bounds.y >= GUIDE_BOX_TOP &&
    bounds.x + bounds.width < GUIDE_BOX_LEFT + GUIDE_BOX_WIDTH &&
    bounds.y + bounds.height < GUIDE_BOX_TOP + GUIDE_BOX_HEIGHT;

  const isFaceLargeEnough =
    bounds.width > GUIDE_BOX_WIDTH * 0.7 &&
    bounds.height > GUIDE_BOX_HEIGHT * 0.6;

  const faceInPosition = isFaceCentered && isFaceLargeEnough;
  setCurrentFace(face);
  setIsFaceInPosition(faceInPosition);

  if (faceInPosition) {
    console.log('Face is in position. Auto-capturing the image...');
    takePicture();
  }
} else {
  setCurrentFace(null);
  setIsFaceInPosition(false);
}

}
const openCamera = () => {
setIsCameraOpen(true);
setPhotoTaken(false);
setIsCapturing(false);
};

const closeCamera = () => {
setIsCameraOpen(false);
setIsCapturing(false);
};

const takePicture = async () => {
if (cameraRef.current && !photoTaken && !isCapturing) {
setIsCapturing(true);
try {
console.log('Attempting to take picture...');
const photo = await cameraRef.current.takePhoto({
qualityPrioritization: 'speed',
});
console.log('Photo taken:', photo.path);

    const imageData = {
      uri: `file://${photo.path}`,
      type: 'image/jpeg',
      name: 'photo.jpg',
    };
    console.log('Image data:', imageData.uri);
    setCapturedPhoto(imageData);
    setPhotoTaken(true);
  } catch (error) {
    console.error('Error taking picture:', error);
  } finally {
    setIsCapturing(false);
  }
}

};
const requestGalleryPermission = async () => {
if (Platform.OS === 'android') {
try {
const granted = await PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.READ_MEDIA_IMAGES,
{
title: 'Gallery Permission',
message: 'App needs access to your gallery to select images',
buttonNeutral: 'Ask Me Later',
buttonNegative: 'Cancel',
buttonPositive: 'OK',
},
);
return granted === PermissionsAndroid.RESULTS.GRANTED;
} catch (err) {
console.error('Permission error:', err);
return false;
}
}
return true; // iOS handles permissions differently
};
const pickImage = async () => {
try {
// Check for permissions first
const hasGalleryPermission = await requestGalleryPermission();
if (!hasGalleryPermission) {
console.log('Gallery permission denied');
Toast.show({
type: 'error',
text1: 'Permission Denied',
text2: 'Please enable gallery access in your device settings',
});
return;
}

  const options = {
    mediaType: 'photo',
    includeBase64: false,
    maxHeight: 2000,
    maxWidth: 2000,
    quality: 1 as const,
    selectionLimit: 1,
    presentationStyle: 'pageSheet' as const,
  };

  const result = await launchImageLibrary(options);

  if (!result.didCancel && result.assets && result.assets.length > 0) {
    const asset = result.assets[0];
    const imageData = {
      uri: asset.uri,
      type: asset.type || 'image/jpeg',
      name: asset.fileName || 'image.jpg',
    };
    // setTempImageData(imageData);
    dispatch(setSelectedImage(imageData));
    console.log(imageData, 'imageData');
    navigation.navigate('AnalyzePhoto', {imageUri: imageData.uri});
  }
} catch (error) {
  console.error('Error picking image:', error);
}

};

const confirmPhoto = () => {
if (capturedPhoto) {
dispatch(setSelectedImage(capturedPhoto));
navigation.navigate('AnalyzePhoto', {imageUri: capturedPhoto.uri});
closeCamera();
}
};

const retakePhoto = () => {
setCapturedPhoto(null);
setPhotoTaken(false);
};

const flipCamera = () => {
// Implementation for camera flip if needed
};
console.log(hasPermission, 'hasPermission');
if (hasPermission === null) {
return ;
}
if (hasPermission === false) {
return No access to camera;
}
const gradientColors = ['#7A4BFF66', '#D241DA66'];

return (
<>
{isCameraOpen ? (

{!!device && (

)}
{!photoTaken && (
<>
<View
style={[
styles.guideBox,
isFaceInPosition
? styles.guideBoxActive
: styles.guideBoxInactive,
]}
/>




{currentFace && (
<>

{/* Only show capture button when face is detected /}
<View style={{justifyContent: 'flex-end'}}>
<TouchableOpacity
style={[
styles.captureButton,
isCapturing && styles.capturingButton,
]}
onPress={takePicture}
disabled={photoTaken || isCapturing}>



</>
)}




</>
)}
{photoTaken && (








)}

) : (
<Container renderHeader={}>

Upload your Photo
To get accurate results





Image should be front facing


{/
<View style={{ justifyContent: "flex-end" }}>
<TouchableOpacity
style={[
styles.captureButton,
isCapturing && styles.capturingButton,
]}
onPress={takePicture}
disabled={photoTaken || isCapturing}
>


*/}



Face should cover at least 50% of the photo






<LinearGradient
colors={gradientColors}
start={{x: 0, y: 0}}
end={{x: 1, y: 0}}
style={styles.dividerStyle}
/>
Or
<LinearGradient
colors={gradientColors}
start={{x: 0, y: 0}}
end={{x: 1, y: 0}}
style={styles.dividerStyle}
/>



)}
</>
);
}

const styles = StyleSheet.create({
titleStyle: {
fontSize: moderateScale(24),
fontWeight: '600',
color: colors.light,
paddingBottom: moderateScale(16),
fontFamily: 'Poppins-SemiBold',
},
titleWrapper: {
alignItems: 'center',
justifyContent: 'center',
marginTop: moderateScale(20),
},
warningWrapper: {
flexDirection: 'row',
justifyContent: 'space-between',
paddingTop: moderateScale(12),
paddingBottom: moderateScale(30),
gap: 10,
},
subTitleStyle: {
fontSize: moderateScale(12),
fontWeight: '400',
color: colors.light,
fontFamily: 'Poppins-Regular',
},
warningWrapperStyle: {
flexDirection: 'row',
alignItems: 'center',
maxWidth: moderateScale(150),
backgroundColor: '#FFFFFF1A',
borderRadius: moderateScale(40),
height: moderateScale(44),
paddingHorizontal: moderateScale(8),
},
warningWrapperStylee: {
flexDirection: 'row',
alignItems: 'center',
maxWidth: moderateScale(180),
backgroundColor: '#FFFFFF1A',
borderRadius: moderateScale(40),
height: moderateScale(44),
paddingHorizontal: moderateScale(8),
},
warningLogoStyle: {
width: moderateScale(25),
height: moderateScale(25),
marginRight: moderateScale(8),
},
warningTextLeft: {
fontSize: moderateScale(11),
fontWeight: '400',
color: colors.light,
maxWidth: moderateScale(100),
paddingRight: moderateScale(10),
fontFamily: 'Poppins-Regular',
},
warningText: {
fontSize: moderateScale(11),
fontWeight: '400',
color: colors.light,
maxWidth: moderateScale(140),
paddingRight: moderateScale(8),
fontFamily: 'Poppins-Regular',
},
btnContainerStyle: {
marginVertical: moderateScale(30),
},
btnTitleStyle: {
fontSize: moderateScale(18),
fontWeight: '600',
},
dividerWrapper: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'center',
},
dividerStyle: {
height: 0.5,
width: moderateScale(150),
},
dividerText: {
fontSize: moderateScale(14),
color: colors.light,
marginHorizontal: moderateScale(10),
fontFamily: 'Poppins-Regular',
},
cameraContainer: {
flex: 1,
width: SCREEN_WIDTH,
height: SCREEN_HEIGHT,
justifyContent: 'center',
alignItems: 'center',
},
guideBox: {
position: 'absolute',
width: GUIDE_BOX_WIDTH,
height: GUIDE_BOX_HEIGHT,
borderWidth: 2,
borderRadius: 10,
},
guideBoxInactive: {
borderColor: 'white',
},
guideBoxActive: {
borderColor: 'green',
},
confirmationContainer: {
position: 'absolute',
bottom: 30,
flexDirection: 'row',
justifyContent: 'space-around',
width: '100%',
},
confirmationButton: {
backgroundColor: 'rgba(0, 0, 0, 0.5)',
padding: 15,
borderRadius: 30,
},
faceOverlay: {
position: 'absolute',
borderWidth: 2,
borderRadius: 999,
backgroundColor: 'transparent',
},
idealFaceCircle: {
position: 'absolute',
width: GUIDE_BOX_WIDTH,
height: GUIDE_BOX_HEIGHT,
borderRadius: GUIDE_BOX_WIDTH / 2,
borderWidth: 1,
borderColor: 'rgba(255, 255, 255, 0.3)',
borderStyle: 'dashed',
top: GUIDE_BOX_TOP,
left: GUIDE_BOX_LEFT,
},
camera: {
flex: 1,
},
buttonContainer: {
flex: 1,
backgroundColor: 'transparent',
flexDirection: 'row',
justifyContent: 'space-around',
margin: 20,
},
button: {
alignSelf: 'flex-end',
alignItems: 'center',
padding: 10,
},
text: {
fontSize: 16,
color: 'white',
},
captureButton: {
width: 70,
height: 70,
borderRadius: 35,
backgroundColor: 'white',
justifyContent: 'center',
alignItems: 'center',
},
innerCaptureButton: {
width: 60,
height: 60,
borderRadius: 30,
backgroundColor: 'white',
borderWidth: 2,
borderColor: '#000',
},
capturingButton: {
opacity: 0.5,
},
});

@DikshantDML401 DikshantDML401 added the bug Something isn't working label Oct 25, 2024
@chinawangyatao
Copy link

Hey, friend, did you solve your problem? I've encountered the same issue as well.

@luicfrr
Copy link
Owner

luicfrr commented Nov 1, 2024

@DikshantDML401 There's really a lot of code, styles, etc.. (also it's bad formated) in your issue. Please edit it and provide only a minimal reproducible example

@shubh197
Copy link

shubh197 commented Nov 20, 2024

facing same issue @DikshantDML401 @chinawangyatao , did you guys get any solution?

import {Platform, StyleSheet, Text, View} from 'react-native';
import {useEffect, useState, useRef} from 'react';
import {Frame, useCameraDevice} from 'react-native-vision-camera';
import {
Face,
Camera,
FaceDetectionOptions,
} from 'react-native-vision-camera-face-detector';
import {PERMISSIONS, request, RESULTS} from 'react-native-permissions';

export default function App() {
const faceDetectionOptions = useRef({
// detection options
}).current;

useEffect(() => {
requestCameraPermission();
}, []);

const device = useCameraDevice('front');

useEffect(() => {
(async () => {
const status = await Camera.requestCameraPermission();
console.log({status});
})();
}, [device]);

function handleFacesDetection(faces: Face[], frame: Frame) {
console.log('faces', faces.length, 'frame', frame.toString());
}

const requestCameraPermission = async () => {
const result = await request(
Platform.OS === 'ios'
? PERMISSIONS.IOS.CAMERA
: PERMISSIONS.ANDROID.CAMERA,
);

if (result === RESULTS.GRANTED) {
  console.log('Camera permission granted');
} else {
  console.log('Camera permission denied');
}

};

return (
<View style={{flex: 1}}>
{!!device ? (

) : (
No Device
)}

);
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

4 participants