From 49dfe6a52e09bdb218e2b1ceb5a8df9ed46873f1 Mon Sep 17 00:00:00 2001 From: Ivan Chen Date: Tue, 22 Jun 2021 18:37:12 -0400 Subject: Squashed commit of the following: commit b1c2002caa349dc96f81d3cc3e00ea545f4e654e Author: Ivan Chen Date: Tue Jun 22 15:28:18 2021 -0400 Add video for camerea --- ios/Frontend/Info.plist | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'ios/Frontend') diff --git a/ios/Frontend/Info.plist b/ios/Frontend/Info.plist index 0d75ca35..fa67d073 100644 --- a/ios/Frontend/Info.plist +++ b/ios/Frontend/Info.plist @@ -66,6 +66,8 @@ UILaunchStoryboardName LaunchScreen + NSMicrophoneUsageDescription + This lets you share video audio from your camera for a Moment post on your profile! UIRequiredDeviceCapabilities armv7 @@ -74,6 +76,8 @@ UIInterfaceOrientationPortrait + NSCameraUsageDescription + This lets you share photos/videos from your camera for a Moment post on your profile! UIViewControllerBasedStatusBarAppearance -- cgit v1.2.3-70-g09d2 From 2f3244dfa11cc23b804930ad448222bbff4f022a Mon Sep 17 00:00:00 2001 From: Ivan Chen Date: Wed, 30 Jun 2021 13:55:28 -0400 Subject: Squashed commit of the following: commit 66c974161b59f1e3570e2a4a42334fabc16c2129 Merge: 53bdc94c d4b21051 Author: Ivan Chen Date: Tue Jun 29 17:06:19 2021 -0400 Merge pull request #476 from shravyaramesh/tma937-tagg-camera [TMA-937] Tagg Camera commit d4b210518eaffd3bf1320ca7ce7fa4a6d611528f Author: Ivan Chen Date: Tue Jun 29 17:04:10 2021 -0400 Cleanup code, Update camera options commit 3f826ec0741d3f0d0c85a17e5d0a09eef402dbf2 Author: Ivan Chen Date: Tue Jun 29 16:45:45 2021 -0400 Set to only allow photos commit 9d30c0c211e6b0b1b87e5de93a043e6e9f06beb3 Author: Ivan Chen Date: Tue Jun 29 16:44:41 2021 -0400 Cleanup code, Fix gallery icon bug commit f6fdd5d913c29855644f226d09d6cba60faf6e21 Author: Ivan Chen Date: Tue Jun 29 16:32:19 2021 -0400 Add error handling commit 5fcffd40746b2074d523f53dc82c824d147444e5 Author: Ivan Chen Date: Tue Jun 29 16:29:06 2021 -0400 Refactor buttons commit f273a7aa1c2e27692c2a03ae1e2fc9b81360558d Author: Shravya Ramesh Date: Fri Jun 25 17:18:47 2021 -0700 Fix lint errors commit 448e91ed0b6c7519c02bbe1ac32a9d51989679db Author: Shravya Ramesh Date: Fri Jun 25 16:58:05 2021 -0700 Fix lint errors commit 6f94f0bb6dbe12e23f4222a0d0e3ffb09af965d7 Author: Shravya Ramesh Date: Fri Jun 25 16:50:13 2021 -0700 Add missing description for permissions commit 727c6384a2a07c42cd132d02da8c7dbb5757ea4f Author: Shravya Ramesh Date: Fri Jun 25 16:50:00 2021 -0700 Refactor code, Fix orientation bug commit f596a0246a9b9453df3a93c8c3fc5c9137bb50fc Author: Shravya Ramesh Date: Fri Jun 25 03:26:00 2021 -0700 Create camera screen, Add to Navigator commit 0646d38547319200f7f725cdd76b1ed9b531a188 Author: Shravya Ramesh Date: Fri Jun 25 03:24:54 2021 -0700 Navigate to camera screen, Move image picker funct commit f0762b7a3171f99833eb3c3f5e723c472dbc4879 Author: Shravya Ramesh Date: Fri Jun 25 03:23:56 2021 -0700 Add assets for camera screen commit 3c4676b7646fbddc43bf5d9796b7cbac185b6664 Author: Shravya Ramesh Date: Fri Jun 25 03:23:33 2021 -0700 Add package, install for camera lib --- ios/Frontend/Info.plist | 6 + ios/Podfile.lock | 12 ++ package.json | 1 + src/assets/icons/camera/flash-off.svg | 1 + src/assets/icons/camera/flash-on.svg | 1 + src/assets/icons/camera/flip.svg | 1 + src/assets/icons/camera/save.svg | 1 + src/components/camera/FlashButton.tsx | 42 +++++++ src/components/camera/FlipButton.tsx | 29 +++++ src/components/camera/GalleryIcon.tsx | 43 +++++++ src/components/camera/SaveButton.tsx | 26 ++++ src/components/camera/index.ts | 4 + src/components/camera/styles.tsx | 53 ++++++++ src/components/index.ts | 9 +- src/components/moments/Moment.tsx | 13 +- src/routes/main/MainStackNavigator.tsx | 4 + src/routes/main/MainStackScreen.tsx | 8 ++ src/screens/moments/CameraScreen.tsx | 215 +++++++++++++++++++++++++++++++++ src/screens/moments/index.ts | 1 + src/utils/camera.ts | 65 ++++++++++ yarn.lock | 7 ++ 21 files changed, 533 insertions(+), 9 deletions(-) create mode 100644 src/assets/icons/camera/flash-off.svg create mode 100644 src/assets/icons/camera/flash-on.svg create mode 100644 src/assets/icons/camera/flip.svg create mode 100644 src/assets/icons/camera/save.svg create mode 100644 src/components/camera/FlashButton.tsx create mode 100644 src/components/camera/FlipButton.tsx create mode 100644 src/components/camera/GalleryIcon.tsx create mode 100644 src/components/camera/SaveButton.tsx create mode 100644 src/components/camera/index.ts create mode 100644 src/components/camera/styles.tsx create mode 100644 src/screens/moments/CameraScreen.tsx create mode 100644 src/utils/camera.ts (limited to 'ios/Frontend') diff --git a/ios/Frontend/Info.plist b/ios/Frontend/Info.plist index fa67d073..94734c40 100644 --- a/ios/Frontend/Info.plist +++ b/ios/Frontend/Info.plist @@ -56,6 +56,12 @@ LaunchScreen NSPhotoLibraryUsageDescription This lets you share photos from your library and select profile displays + NSPhotoLibraryAddUsageDescription + This lets you save photos captured on Tagg, to your library + NSCameraUsageDescription + Enable camera access to capture and share moment with your friends + NSMicrophoneUsageDescription + Enable microphone access to record and listen to videos UIAppFonts Feather.ttf diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 15ec026f..8eed7569 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -329,6 +329,14 @@ PODS: - React-jsinspector (0.63.3) - react-native-blur (0.8.0): - React + - react-native-camera (3.44.1): + - React-Core + - react-native-camera/RCT (= 3.44.1) + - react-native-camera/RN (= 3.44.1) + - react-native-camera/RCT (3.44.1): + - React-Core + - react-native-camera/RN (3.44.1): + - React-Core - react-native-cameraroll (4.0.4): - React-Core - react-native-contacts (6.0.5): @@ -534,6 +542,7 @@ DEPENDENCIES: - React-jsiexecutor (from `../node_modules/react-native/ReactCommon/jsiexecutor`) - React-jsinspector (from `../node_modules/react-native/ReactCommon/jsinspector`) - "react-native-blur (from `../node_modules/@react-native-community/blur`)" + - react-native-camera (from `../node_modules/react-native-camera`) - "react-native-cameraroll (from `../node_modules/@react-native-community/cameraroll`)" - react-native-contacts (from `../node_modules/react-native-contacts`) - react-native-date-picker (from `../node_modules/react-native-date-picker`) @@ -638,6 +647,8 @@ EXTERNAL SOURCES: :path: "../node_modules/react-native/ReactCommon/jsinspector" react-native-blur: :path: "../node_modules/@react-native-community/blur" + react-native-camera: + :path: "../node_modules/react-native-camera" react-native-cameraroll: :path: "../node_modules/@react-native-community/cameraroll" react-native-contacts: @@ -758,6 +769,7 @@ SPEC CHECKSUMS: React-jsiexecutor: b56c03e61c0dd5f5801255f2160a815f4a53d451 React-jsinspector: 8e68ffbfe23880d3ee9bafa8be2777f60b25cbe2 react-native-blur: cad4d93b364f91e7b7931b3fa935455487e5c33c + react-native-camera: 7bf59f2728ffb019fa25e60a225d2c57e1a8f0f6 react-native-cameraroll: 88f4e62d9ecd0e1f253abe4f685474f2ea14bfa2 react-native-contacts: 931baebf460125c5a7bbce1c4521a96c69795123 react-native-date-picker: 96a07ca27a6225da8a3935324d85046028456b0f diff --git a/package.json b/package.json index 09ed6fc5..63203775 100644 --- a/package.json +++ b/package.json @@ -34,6 +34,7 @@ "react-moment": "^1.0.0", "react-native": "0.63.3", "react-native-animatable": "^1.3.3", + "react-native-camera": "^3.44.1", "react-native-confirmation-code-field": "^6.5.0", "react-native-contacts": "^6.0.4", "react-native-controlled-mentions": "^2.2.5", diff --git a/src/assets/icons/camera/flash-off.svg b/src/assets/icons/camera/flash-off.svg new file mode 100644 index 00000000..fb04efd2 --- /dev/null +++ b/src/assets/icons/camera/flash-off.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/camera/flash-on.svg b/src/assets/icons/camera/flash-on.svg new file mode 100644 index 00000000..b4608b75 --- /dev/null +++ b/src/assets/icons/camera/flash-on.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/camera/flip.svg b/src/assets/icons/camera/flip.svg new file mode 100644 index 00000000..e2ef1a0c --- /dev/null +++ b/src/assets/icons/camera/flip.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/camera/save.svg b/src/assets/icons/camera/save.svg new file mode 100644 index 00000000..6a28fb55 --- /dev/null +++ b/src/assets/icons/camera/save.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/components/camera/FlashButton.tsx b/src/components/camera/FlashButton.tsx new file mode 100644 index 00000000..06a4e44e --- /dev/null +++ b/src/components/camera/FlashButton.tsx @@ -0,0 +1,42 @@ +import React, {Dispatch, SetStateAction} from 'react'; +import {Text, TouchableOpacity} from 'react-native'; +import {FlashMode} from 'react-native-camera'; +import FlashOffIcon from '../../assets/icons/camera/flash-off.svg'; +import FlashOnIcon from '../../assets/icons/camera/flash-on.svg'; +import {styles} from './styles'; + +interface FlashButtonProps { + flashMode: keyof FlashMode; + setFlashMode: Dispatch>; +} + +/* + * Toggles between flash on/off modes + */ +export const FlashButton: React.FC = ({ + flashMode, + setFlashMode, +}) => ( + setFlashMode(flashMode === 'on' ? 'off' : 'on')} + style={styles.flashButtonContainer}> + {flashMode === 'on' ? ( + + ) : ( + + )} + Flash + +); + +export default FlashButton; diff --git a/src/components/camera/FlipButton.tsx b/src/components/camera/FlipButton.tsx new file mode 100644 index 00000000..c6f710a9 --- /dev/null +++ b/src/components/camera/FlipButton.tsx @@ -0,0 +1,29 @@ +import React, {Dispatch, SetStateAction} from 'react'; +import {Text, TouchableOpacity} from 'react-native'; +import {CameraType} from 'react-native-camera'; +import FlipIcon from '../../assets/icons/camera/flip.svg'; +import {styles} from './styles'; + +interface FlipButtonProps { + setCameraType: Dispatch>; + cameraType: keyof CameraType; +} + +/* + * Toggles between back camera and front camera + * Appears only when user has not taken a picture yet + * Once user takes a picture, this button disappears to reveal the save button + */ +export const FlipButton: React.FC = ({ + setCameraType, + cameraType, +}) => ( + setCameraType(cameraType === 'front' ? 'back' : 'front')} + style={styles.saveButton}> + + Flip + +); + +export default FlipButton; diff --git a/src/components/camera/GalleryIcon.tsx b/src/components/camera/GalleryIcon.tsx new file mode 100644 index 00000000..c49ace7d --- /dev/null +++ b/src/components/camera/GalleryIcon.tsx @@ -0,0 +1,43 @@ +import {useNavigation} from '@react-navigation/native'; +import React from 'react'; +import {Image, Text, TouchableOpacity, View} from 'react-native'; +import {ScreenType} from '../../types'; +import {navigateToImagePicker} from '../../utils/camera'; +import {styles} from './styles'; + +interface GalleryIconProps { + screenType: ScreenType; + title: string; + mostRecentPhotoUri: string; +} + +/* + * Displays the most recent photo in the user's gallery + * On click, navigates to the image picker + */ +export const GalleryIcon: React.FC = ({ + screenType, + title, + mostRecentPhotoUri, +}) => { + const navigation = useNavigation(); + return ( + navigateToImagePicker(navigation, screenType, title)} + style={styles.saveButton}> + {mostRecentPhotoUri !== '' ? ( + + ) : ( + + )} + Gallery + + ); +}; + +export default GalleryIcon; diff --git a/src/components/camera/SaveButton.tsx b/src/components/camera/SaveButton.tsx new file mode 100644 index 00000000..840cc804 --- /dev/null +++ b/src/components/camera/SaveButton.tsx @@ -0,0 +1,26 @@ +import React from 'react'; +import {Text, TouchableOpacity} from 'react-native'; +import SaveIcon from '../../assets/icons/camera/save.svg'; +import {downloadImage} from '../../utils/camera'; +import {styles} from './styles'; + +interface SaveButtonProps { + capturedImageURI: string; +} + +/* + * Appears when a picture has been taken, + * On click, saves the captured image to "Recents" album on device gallery + */ +export const SaveButton: React.FC = ({capturedImageURI}) => ( + { + downloadImage(capturedImageURI); + }} + style={styles.saveButton}> + + Save + +); + +export default SaveButton; diff --git a/src/components/camera/index.ts b/src/components/camera/index.ts new file mode 100644 index 00000000..d33d1e4a --- /dev/null +++ b/src/components/camera/index.ts @@ -0,0 +1,4 @@ +export {default as GalleryIcon} from './GalleryIcon'; +export {default as FlashButton} from './FlashButton'; +export {default as FlipButton} from './FlipButton'; +export {default as SaveButton} from './SaveButton'; diff --git a/src/components/camera/styles.tsx b/src/components/camera/styles.tsx new file mode 100644 index 00000000..33b47cc4 --- /dev/null +++ b/src/components/camera/styles.tsx @@ -0,0 +1,53 @@ +import {StyleSheet} from 'react-native'; +import {normalize, SCREEN_WIDTH} from '../../utils/layouts'; + +export const styles = StyleSheet.create({ + saveButton: { + zIndex: 1, + flexDirection: 'column', + justifyContent: 'center', + alignItems: 'center', + width: (SCREEN_WIDTH - 100) / 2, + }, + saveButtonLabel: { + color: 'white', + fontWeight: '700', + fontSize: normalize(12), + lineHeight: normalize(14.32), + marginTop: 5, + zIndex: 999, + }, + flashButtonContainer: { + position: 'absolute', + backgroundColor: '#808080', + opacity: 0.25, + zIndex: 1, + top: normalize(50), + right: 0, + marginRight: normalize(18), + height: 86, + width: 49, + flexDirection: 'column', + justifyContent: 'center', + alignItems: 'center', + borderRadius: 30, + }, + galleryIcon: { + borderWidth: 2, + borderColor: 'white', + borderRadius: 5, + width: 40, + height: 40, + }, + galleryIconEmpty: { + borderWidth: 2, + borderColor: 'white', + borderRadius: 5, + width: 40, + height: 40, + backgroundColor: 'grey', + }, + flashIcon: { + zIndex: 2, + }, +}); diff --git a/src/components/index.ts b/src/components/index.ts index 47dc583b..c2f50118 100644 --- a/src/components/index.ts +++ b/src/components/index.ts @@ -1,9 +1,10 @@ +export * from './camera'; +export * from './comments'; export * from './common'; +export * from './messages'; +export * from './moments'; export * from './onboarding'; export * from './profile'; export * from './search'; -export * from './taggs'; -export * from './comments'; -export * from './moments'; export * from './suggestedPeople'; -export * from './messages'; +export * from './taggs'; diff --git a/src/components/moments/Moment.tsx b/src/components/moments/Moment.tsx index a43a2830..b080ca4a 100644 --- a/src/components/moments/Moment.tsx +++ b/src/components/moments/Moment.tsx @@ -1,9 +1,8 @@ import {useNavigation} from '@react-navigation/native'; import React from 'react'; -import {Alert, StyleProp, StyleSheet, View, ViewStyle} from 'react-native'; +import {StyleProp, StyleSheet, View, ViewStyle} from 'react-native'; import {Text} from 'react-native-animatable'; import {ScrollView, TouchableOpacity} from 'react-native-gesture-handler'; -import ImagePicker from 'react-native-image-crop-picker'; import LinearGradient from 'react-native-linear-gradient'; import DeleteIcon from '../../assets/icons/delete-logo.svg'; import DownIcon from '../../assets/icons/down_icon.svg'; @@ -11,7 +10,6 @@ import BigPlusIcon from '../../assets/icons/plus-icon-white.svg'; import PlusIcon from '../../assets/icons/plus-icon.svg'; import UpIcon from '../../assets/icons/up_icon.svg'; import {TAGG_LIGHT_BLUE} from '../../constants'; -import {ERROR_UPLOAD} from '../../constants/strings'; import {MomentType, ScreenType} from '../../types'; import {normalize, SCREEN_WIDTH} from '../../utils'; import MomentTile from './MomentTile'; @@ -108,6 +106,11 @@ const Moment: React.FC = ({ Alert.alert(ERROR_UPLOAD); } }); + const navigateToCameraScreen = () => { + navigation.navigate('CameraScreen', { + title, + screenType, + }); }; return ( @@ -174,7 +177,7 @@ const Moment: React.FC = ({ navigateToImagePicker()} + onPress={() => navigateToCameraScreen()} color={TAGG_LIGHT_BLUE} style={styles.horizontalMargin} /> @@ -204,7 +207,7 @@ const Moment: React.FC = ({ /> ))} {(images === undefined || images.length === 0) && !userXId && ( - navigateToImagePicker()}> + navigateToCameraScreen()}> diff --git a/src/routes/main/MainStackNavigator.tsx b/src/routes/main/MainStackNavigator.tsx index c518d75e..21430d7a 100644 --- a/src/routes/main/MainStackNavigator.tsx +++ b/src/routes/main/MainStackNavigator.tsx @@ -115,6 +115,10 @@ export type MainStackParams = { screenType: ScreenType; title: string; }; + CameraScreen: { + title: string; + screenType: ScreenType; + }; }; export const MainStack = createStackNavigator(); diff --git a/src/routes/main/MainStackScreen.tsx b/src/routes/main/MainStackScreen.tsx index 9e3747f9..f6adeab1 100644 --- a/src/routes/main/MainStackScreen.tsx +++ b/src/routes/main/MainStackScreen.tsx @@ -34,6 +34,7 @@ import { SuggestedPeopleWelcomeScreen, TagSelectionScreen, TagFriendsScreen, + CameraScreen, } from '../../screens'; import MutualBadgeHolders from '../../screens/suggestedPeople/MutualBadgeHolders'; import {ScreenType} from '../../types'; @@ -334,6 +335,13 @@ const MainStackScreen: React.FC = ({route}) => { gestureEnabled: false, }} /> + ); }; diff --git a/src/screens/moments/CameraScreen.tsx b/src/screens/moments/CameraScreen.tsx new file mode 100644 index 00000000..c6ed1116 --- /dev/null +++ b/src/screens/moments/CameraScreen.tsx @@ -0,0 +1,215 @@ +import CameraRoll from '@react-native-community/cameraroll'; +import {useBottomTabBarHeight} from '@react-navigation/bottom-tabs'; +import {RouteProp, useFocusEffect} from '@react-navigation/core'; +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 CloseIcon from '../../assets/ionicons/close-outline.svg'; +import { + FlashButton, + FlipButton, + GalleryIcon, + SaveButton, + TaggSquareButton, +} from '../../components'; +import {MainStackParams} from '../../routes'; +import {HeaderHeight, normalize, SCREEN_WIDTH} from '../../utils'; +import {takePicture} from '../../utils/camera'; + +type CameraScreenRouteProps = RouteProp; +export type CameraScreenNavigationProps = StackNavigationProp< + MainStackParams, + 'CameraScreen' +>; +interface CameraScreenProps { + route: CameraScreenRouteProps; + navigation: CameraScreenNavigationProps; +} +const CameraScreen: React.FC = ({route, navigation}) => { + const {title, screenType} = route.params; + const cameraRef = createRef(); + const tabBarHeight = useBottomTabBarHeight(); + const [cameraType, setCameraType] = useState('front'); + const [flashMode, setFlashMode] = useState('off'); + const [capturedImage, setCapturedImage] = useState(''); + const [mostRecentPhoto, setMostRecentPhoto] = useState(''); + const [showSaveButton, setShowSaveButton] = useState(false); + + /* + * Removes bottom navigation bar on current screen and add it back when navigating away + */ + useFocusEffect( + useCallback(() => { + navigation.dangerouslyGetParent()?.setOptions({ + tabBarVisible: false, + }); + return () => { + navigation.dangerouslyGetParent()?.setOptions({ + tabBarVisible: true, + }); + }; + }, [navigation]), + ); + + /* + * Chooses the last picture from gallery to display as the gallery button icon + */ + useEffect(() => { + CameraRoll.getPhotos({first: 1}) + .then((lastPhoto) => { + if (lastPhoto.edges.length > 0) { + const image = lastPhoto.edges[0].node.image; + setMostRecentPhoto(image.uri); + } + }) + .catch((_err) => + console.log('Unable to fetch preview photo for gallery'), + ); + }, [capturedImage]); + + /* + * Appears once a picture has been captured to navigate to the caption screen + */ + const handleNext = () => { + navigation.navigate('CaptionScreen', { + screenType, + title, + image: { + filename: capturedImage, + path: capturedImage, + }, + }); + }; + + /* + * If picture is not taken yet, exists from camera screen to profile view + * If picture is taken, exists from captured image's preview to camera + * */ + const handleClose = () => { + if (showSaveButton) { + cameraRef.current?.resumePreview(); + setShowSaveButton(false); + setCapturedImage(''); + } else { + navigation.goBack(); + } + }; + + return ( + + + + + + + + {showSaveButton ? ( + + ) : ( + + )} + + takePicture(cameraRef, setShowSaveButton, setCapturedImage) + } + style={styles.captureButtonContainer}> + + + + {capturedImage ? ( + + ) : ( + + )} + + + + ); +}; + +const styles = StyleSheet.create({ + camera: { + flex: 1, + justifyContent: 'space-between', + }, + container: { + flex: 1, + flexDirection: 'column', + backgroundColor: 'black', + }, + preview: { + flex: 1, + justifyContent: 'flex-end', + alignItems: 'center', + }, + captureButtonContainer: { + alignSelf: 'center', + backgroundColor: 'transparent', + borderRadius: 100, + borderWidth: 4, + borderColor: '#fff', + width: 93, + height: 93, + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'center', + }, + captureButton: { + backgroundColor: '#fff', + width: 68, + height: 68, + borderRadius: 74, + }, + closeButton: { + position: 'absolute', + top: 0, + paddingTop: HeaderHeight, + zIndex: 1, + marginLeft: '5%', + }, + bottomContainer: { + position: 'absolute', + width: SCREEN_WIDTH, + flexDirection: 'row', + justifyContent: 'center', + }, + bottomRightContainer: { + flexDirection: 'column', + justifyContent: 'center', + alignItems: 'center', + width: (SCREEN_WIDTH - 100) / 2, + }, + nextButton: { + zIndex: 1, + width: normalize(100), + height: normalize(37), + borderRadius: 10, + }, + nextButtonLabel: { + fontWeight: '700', + fontSize: normalize(15), + lineHeight: normalize(17.8), + letterSpacing: normalize(1.3), + textAlign: 'center', + }, +}); + +export default CameraScreen; diff --git a/src/screens/moments/index.ts b/src/screens/moments/index.ts index aac2ddeb..07d55192 100644 --- a/src/screens/moments/index.ts +++ b/src/screens/moments/index.ts @@ -1,2 +1,3 @@ export {default as TagSelectionScreen} from './TagSelectionScreen'; export {default as TagFriendsScreen} from './TagFriendsScreen'; +export {default as CameraScreen} from './CameraScreen'; diff --git a/src/utils/camera.ts b/src/utils/camera.ts new file mode 100644 index 00000000..73461ad7 --- /dev/null +++ b/src/utils/camera.ts @@ -0,0 +1,65 @@ +import CameraRoll from '@react-native-community/cameraroll'; +import {Dispatch, RefObject, SetStateAction} from 'react'; +import {Alert} from 'react-native'; +import {RNCamera} from 'react-native-camera'; +import ImagePicker from 'react-native-image-crop-picker'; +import {ScreenType} from 'src/types'; +import {ERROR_UPLOAD} from '../constants/strings'; + +/* + * Captures a photo and pauses to shoe the preview of the picture taken + */ +export const takePicture = ( + cameraRef: RefObject, + setShowSaveButton: Dispatch>, + setCapturedImage: Dispatch>, +) => { + if (cameraRef !== null) { + cameraRef.current?.pausePreview(); + const options = { + forceUpOrientation: true, + writeExif: false, + }; + cameraRef.current?.takePictureAsync(options).then((response) => { + setShowSaveButton(true); + setCapturedImage(response.uri); + }); + } +}; + +export const downloadImage = (capturedImageURI: string) => { + CameraRoll.save(capturedImageURI, {album: 'Recents', type: 'photo'}) + .then((_res) => Alert.alert('Saved to device!')) + .catch((_err) => Alert.alert('Failed to save to device!')); +}; + +export const navigateToImagePicker = ( + navigation: any, + screenType: ScreenType, + title: string, +) => { + ImagePicker.openPicker({ + smartAlbums: [ + 'Favorites', + 'RecentlyAdded', + 'SelfPortraits', + 'Screenshots', + 'UserLibrary', + ], + mediaType: 'photo', + }) + .then((picture) => { + if ('path' in picture) { + navigation.navigate('ZoomInCropper', { + screenType, + title, + image: picture, + }); + } + }) + .catch((err) => { + if (err.code && err.code !== 'E_PICKER_CANCELLED') { + Alert.alert(ERROR_UPLOAD); + } + }); +}; diff --git a/yarn.lock b/yarn.lock index 9b425078..716b345a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6427,6 +6427,13 @@ react-native-animatable@^1.3.3: dependencies: prop-types "^15.7.2" +react-native-camera@^3.44.1: + version "3.44.1" + resolved "https://registry.yarnpkg.com/react-native-camera/-/react-native-camera-3.44.1.tgz#60e7d60fe778c1fc59d0579b64c63c3c1a59865a" + integrity sha512-B95RL3laK2v8R7L/37v28MYcEcwsM/mS94h6EZuRMLH5HFolkAwh7zJo+UAn7FG9eFtAdBwIM6s9OqYudTVO4Q== + dependencies: + prop-types "^15.6.2" + react-native-confirmation-code-field@^6.5.0: version "6.7.0" resolved "https://registry.yarnpkg.com/react-native-confirmation-code-field/-/react-native-confirmation-code-field-6.7.0.tgz#81f5e646898addb3243cf89d41d884b0762ae962" -- cgit v1.2.3-70-g09d2 From 4b90c999d3ee45368108851eeb1cdc634e5ec499 Mon Sep 17 00:00:00 2001 From: Ivan Chen Date: Wed, 30 Jun 2021 14:32:55 -0400 Subject: Organize plist key values --- ios/Frontend/Info.plist | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) (limited to 'ios/Frontend') diff --git a/ios/Frontend/Info.plist b/ios/Frontend/Info.plist index 94734c40..0b1f27bf 100644 --- a/ios/Frontend/Info.plist +++ b/ios/Frontend/Info.plist @@ -54,14 +54,6 @@ NSMainNibFile LaunchScreen - NSPhotoLibraryUsageDescription - This lets you share photos from your library and select profile displays - NSPhotoLibraryAddUsageDescription - This lets you save photos captured on Tagg, to your library - NSCameraUsageDescription - Enable camera access to capture and share moment with your friends - NSMicrophoneUsageDescription - Enable microphone access to record and listen to videos UIAppFonts Feather.ttf @@ -82,6 +74,10 @@ UIInterfaceOrientationPortrait + NSPhotoLibraryUsageDescription + This lets you share photos from your library and select profile displays + NSPhotoLibraryAddUsageDescription + This lets you save photos captured on Tagg, to your library NSCameraUsageDescription This lets you share photos/videos from your camera for a Moment post on your profile! UIViewControllerBasedStatusBarAppearance -- cgit v1.2.3-70-g09d2