-
Notifications
You must be signed in to change notification settings - Fork 23
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
Comments
Hey, friend, did you solve your problem? I've encountered the same issue as well. |
@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 |
facing same issue @DikshantDML401 @chinawangyatao , did you guys get any solution? import {Platform, StyleSheet, Text, View} from 'react-native'; export default function App() { useEffect(() => { const device = useCameraDevice('front'); useEffect(() => { function handleFacesDetection(faces: Face[], frame: Frame) { const requestCameraPermission = async () => {
}; return ( |
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 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 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 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,
},
});
The text was updated successfully, but these errors were encountered: