diff options
Diffstat (limited to 'src/screens')
-rw-r--r-- | src/screens/moments/CameraScreen.tsx | 87 |
1 files changed, 68 insertions, 19 deletions
diff --git a/src/screens/moments/CameraScreen.tsx b/src/screens/moments/CameraScreen.tsx index 37b37264..75638c40 100644 --- a/src/screens/moments/CameraScreen.tsx +++ b/src/screens/moments/CameraScreen.tsx @@ -6,6 +6,7 @@ import {StackNavigationProp} from '@react-navigation/stack'; import React, {createRef, useCallback, useEffect, useState} from 'react'; import {StyleSheet, TouchableOpacity, View} from 'react-native'; import {CameraType, FlashMode, RNCamera} from 'react-native-camera'; +import {AnimatedCircularProgress} from 'react-native-circular-progress'; import CloseIcon from '../../assets/ionicons/close-outline.svg'; import { FlashButton, @@ -14,9 +15,10 @@ import { SaveButton, TaggSquareButton, } from '../../components'; +import {TAGG_PURPLE} from '../../constants'; import {MainStackParams} from '../../routes'; import {HeaderHeight, normalize, SCREEN_WIDTH} from '../../utils'; -import {showGIFFailureAlert, takePicture} from '../../utils/camera'; +import {showGIFFailureAlert, takePicture, takeVideo} from '../../utils/camera'; type CameraScreenRouteProps = RouteProp<MainStackParams, 'CameraScreen'>; export type CameraScreenNavigationProps = StackNavigationProp< @@ -33,9 +35,10 @@ const CameraScreen: React.FC<CameraScreenProps> = ({route, navigation}) => { const tabBarHeight = useBottomTabBarHeight(); const [cameraType, setCameraType] = useState<keyof CameraType>('front'); const [flashMode, setFlashMode] = useState<keyof FlashMode>('off'); - const [capturedImage, setCapturedImage] = useState<string>(''); + const [mediaFromGallery, setMediaFromGallery] = useState<string>(''); const [mostRecentPhoto, setMostRecentPhoto] = useState<string>(''); const [showSaveButton, setShowSaveButton] = useState<boolean>(false); + const [isRecording, setIsRecording] = useState<boolean>(false); useFocusEffect( useCallback(() => { @@ -64,7 +67,7 @@ const CameraScreen: React.FC<CameraScreenProps> = ({route, navigation}) => { .catch((_err) => console.log('Unable to fetch preview photo for gallery'), ); - }, [capturedImage]); + }, [mediaFromGallery]); const navigateToCropper = (uri: string) => { navigation.navigate('ZoomInCropper', { @@ -77,13 +80,13 @@ const CameraScreen: React.FC<CameraScreenProps> = ({route, navigation}) => { }); }; - const navigateToCaptionScreen = () => { + const navigateToCaptionScreen = (isVideo: boolean, uri: string) => { navigation.navigate('CaptionScreen', { screenType, title, media: { - uri: capturedImage, - isVideo: false, + uri, + isVideo, }, }); }; @@ -96,7 +99,7 @@ const CameraScreen: React.FC<CameraScreenProps> = ({route, navigation}) => { if (showSaveButton) { cameraRef.current?.resumePreview(); setShowSaveButton(false); - setCapturedImage(''); + setMediaFromGallery(''); } else { navigation.goBack(); } @@ -116,24 +119,53 @@ const CameraScreen: React.FC<CameraScreenProps> = ({route, navigation}) => { /> <View style={[styles.bottomContainer, {bottom: tabBarHeight}]}> {showSaveButton ? ( - <SaveButton capturedImageURI={capturedImage} /> + <SaveButton capturedImageURI={mediaFromGallery} /> ) : ( <FlipButton cameraType={cameraType} setCameraType={setCameraType} /> )} <TouchableOpacity - onPress={() => + activeOpacity={1} + onLongPress={() => { + takeVideo(cameraRef, (vid) => { + navigateToCaptionScreen(true, vid.uri); + }); + setIsRecording(true); + }} + onPressOut={async () => { + if (await cameraRef.current?.isRecording()) { + cameraRef.current?.stopRecording(); + setIsRecording(false); + } + }} + onPress={() => { takePicture(cameraRef, (pic) => { setShowSaveButton(true); - setCapturedImage(pic.uri); - }) - } - style={styles.captureButtonContainer}> + setMediaFromGallery(pic.uri); + }); + }} + style={ + isRecording + ? styles.captureButtonVideoContainer + : styles.captureButtonContainer + }> <View style={styles.captureButton} /> </TouchableOpacity> + {isRecording && ( + <AnimatedCircularProgress + size={95} + width={6} + fill={100} + rotation={0} + duration={60000 + 1000} // an extra second for UI to load + tintColor={TAGG_PURPLE} + style={styles.bottomContainer} + lineCap={'round'} + /> + )} <View style={styles.bottomRightContainer}> - {capturedImage ? ( + {mediaFromGallery ? ( <TaggSquareButton - onPress={navigateToCaptionScreen} + onPress={() => navigateToCaptionScreen(false, mediaFromGallery)} title={'Next'} buttonStyle={'large'} buttonColor={'blue'} @@ -144,15 +176,20 @@ const CameraScreen: React.FC<CameraScreenProps> = ({route, navigation}) => { ) : ( <GalleryIcon mostRecentPhotoUri={mostRecentPhoto} - callback={(pic) => { - const filename = pic.filename; + callback={(media) => { + const filename = media.filename; if ( filename && (filename.endsWith('gif') || filename.endsWith('GIF')) ) { - showGIFFailureAlert(() => navigateToCropper(pic.path)); + showGIFFailureAlert(() => navigateToCropper(media.path)); } else { - navigateToCropper(pic.path); + // is this a video? + if (media.duration !== null) { + navigateToCaptionScreen(true, media.path); + } else { + navigateToCropper(media.path); + } } }} /> @@ -173,6 +210,18 @@ const styles = StyleSheet.create({ flexDirection: 'column', backgroundColor: 'black', }, + captureButtonVideoContainer: { + alignSelf: 'center', + backgroundColor: 'transparent', + borderRadius: 100, + borderWidth: 15, + borderColor: 'rgba(255,255,255,0.3)', + width: 93, + height: 93, + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'center', + }, captureButtonContainer: { alignSelf: 'center', backgroundColor: 'transparent', |