import React, { useState, useRef } from 'react'; import { Animated, StyleSheet, TouchableOpacity, View } from 'react-native'; import { Camera, CameraApi, CameraType, Orientation } from 'react-native-camera-kit'; import loc from '../loc'; import { Icon } from '@rneui/base'; import { OnOrientationChangeData, OnReadCodeData } from 'react-native-camera-kit/dist/CameraProps'; import { triggerSelectionHapticFeedback } from '../blue_modules/hapticFeedback'; interface CameraScreenProps { onCancelButtonPress: () => void; showImagePickerButton?: boolean; showFilePickerButton?: boolean; onImagePickerButtonPress?: () => void; onFilePickerButtonPress?: () => void; onReadCode?: (event: OnReadCodeData) => void; } const CameraScreen: React.FC = ({ onCancelButtonPress, showImagePickerButton, showFilePickerButton, onImagePickerButtonPress, onFilePickerButtonPress, onReadCode, }) => { const cameraRef = useRef(null); const [torchMode, setTorchMode] = useState(false); const [cameraType, setCameraType] = useState(CameraType.Back); const [zoom, setZoom] = useState(); const [orientationAnim] = useState(new Animated.Value(3)); const onSwitchCameraPressed = () => { const direction = cameraType === CameraType.Back ? CameraType.Front : CameraType.Back; setCameraType(direction); setZoom(1); // When changing camera type, reset to default zoom for that camera triggerSelectionHapticFeedback(); }; const onSetTorch = () => { setTorchMode(!torchMode); triggerSelectionHapticFeedback(); }; // Counter-rotate the icons to indicate the actual orientation of the captured photo. // For this example, it'll behave incorrectly since UI orientation is allowed (and already-counter rotates the entire screen) // For real phone apps, lock your UI orientation using a library like 'react-native-orientation-locker' const rotateUi = true; const uiRotation = orientationAnim.interpolate({ inputRange: [1, 4], outputRange: ['180deg', '-90deg'], }); const uiRotationStyle = rotateUi ? { transform: [{ rotate: uiRotation }] } : {}; function rotateUiTo(rotationValue: number) { Animated.timing(orientationAnim, { toValue: rotationValue, useNativeDriver: true, duration: 200, isInteraction: false, }).start(); } const handleZoom = (e: { nativeEvent: { zoom: number } }) => { console.debug('zoom', e.nativeEvent.zoom); setZoom(e.nativeEvent.zoom); }; const handleOrientationChange = (e: OnOrientationChangeData) => { switch (e.nativeEvent.orientation) { case Orientation.PORTRAIT_UPSIDE_DOWN: console.debug('orientationChange', 'PORTRAIT_UPSIDE_DOWN'); rotateUiTo(1); break; case Orientation.LANDSCAPE_LEFT: console.debug('orientationChange', 'LANDSCAPE_LEFT'); rotateUiTo(2); break; case Orientation.PORTRAIT: console.debug('orientationChange', 'PORTRAIT'); rotateUiTo(3); break; case Orientation.LANDSCAPE_RIGHT: console.debug('orientationChange', 'LANDSCAPE_RIGHT'); rotateUiTo(4); break; default: console.debug('orientationChange', e.nativeEvent); break; } }; const handleReadCode = (event: OnReadCodeData) => { onReadCode?.(event); }; return ( {showImagePickerButton && ( )} {showFilePickerButton && ( )} {loc._.cancel} ); }; export default CameraScreen; const styles = StyleSheet.create({ screen: { height: '100%', backgroundColor: '#000000', }, topButtons: { padding: 10, zIndex: 10, flexDirection: 'row', justifyContent: 'space-between', }, topButton: { backgroundColor: '#222', width: 44, height: 44, borderRadius: 22, justifyContent: 'center', alignItems: 'center', }, topButtonImg: { margin: 10, width: 24, height: 24, }, cameraContainer: { justifyContent: 'center', flex: 1, }, cameraPreview: { width: '100%', height: '100%', }, bottomButtons: { padding: 10, flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', }, backTextStyle: { padding: 10, color: 'white', fontSize: 20, }, rightButtonsContainer: { flexDirection: 'row', alignItems: 'center', }, bottomButton: { backgroundColor: '#222', width: 44, height: 44, borderRadius: 22, justifyContent: 'center', alignItems: 'center', marginLeft: 10, }, spacing: { marginLeft: 20, }, });