diff options
author | George Rusu <george@tagg.id> | 2021-06-22 04:32:39 -0700 |
---|---|---|
committer | George Rusu <george@tagg.id> | 2021-06-22 04:32:39 -0700 |
commit | ae970faf6f560cc2fb55488acd49a04cfcb942c5 (patch) | |
tree | 1e1fd28fe58f68573cb40913dc72968a043ba396 /src | |
parent | 3065e921b858f68eb1c1746bba116c01cbfb01dd (diff) |
Add documentation and clean up code: improvements in code quality can be made, POC functionality ready
Diffstat (limited to 'src')
-rw-r--r-- | src/components/moments/Moment.tsx | 91 | ||||
-rw-r--r-- | src/services/MomentService.ts | 45 | ||||
-rw-r--r-- | src/types/types.ts | 4 |
3 files changed, 83 insertions, 57 deletions
diff --git a/src/components/moments/Moment.tsx b/src/components/moments/Moment.tsx index 11640b5b..d2f7be2e 100644 --- a/src/components/moments/Moment.tsx +++ b/src/components/moments/Moment.tsx @@ -1,25 +1,25 @@ +import AsyncStorage from '@react-native-community/async-storage'; import {useNavigation} from '@react-navigation/native'; import React from 'react'; import {Alert, StyleProp, StyleSheet, View, ViewStyle} from 'react-native'; -import AsyncStorage from '@react-native-community/async-storage'; 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'; -import PlusIcon from '../../assets/icons/plus-icon.svg'; 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'; import { handlePresignedURL, handleVideoUpload, } from '../../services/MomentService'; +import {MomentType, ScreenType} from '../../types'; +import {normalize, SCREEN_WIDTH} from '../../utils'; +import MomentTile from './MomentTile'; interface MomentProps { title: string; @@ -46,8 +46,14 @@ const Moment: React.FC<MomentProps> = ({ move, externalStyles, }) => { - // const navigation = useNavigation(); - + const navigation = useNavigation(); + /** + * This function opens the ImagePicker, only lets you select video files, + * formats the file extension, then makes a call to the server to get the presigned URL, + * after which it makes a POST request to the returned URL to upload the file directly to S3. + * params: none + * @returns: none + */ const navigateToVideoPicker = () => { ImagePicker.openPicker({ smartAlbums: [ @@ -61,7 +67,7 @@ const Moment: React.FC<MomentProps> = ({ height: 580, cropping: false, cropperToolbarTitle: 'select a video', - mediaType: 'any', + mediaType: 'video', }) .then(async (vid) => { if ('path' in vid) { @@ -82,36 +88,36 @@ const Moment: React.FC<MomentProps> = ({ }); }; - // const navigateToImagePicker = () => { - // ImagePicker.openPicker({ - // smartAlbums: [ - // 'Favorites', - // 'RecentlyAdded', - // 'SelfPortraits', - // 'Screenshots', - // 'UserLibrary', - // ], - // width: 580, - // height: 580, - // cropping: true, - // cropperToolbarTitle: 'Upload a moment', - // mediaType: 'photo', - // }) - // .then((picture) => { - // if ('path' in picture) { - // navigation.navigate('CaptionScreen', { - // screenType, - // title: title, - // image: picture, - // }); - // } - // }) - // .catch((err) => { - // if (err.code && err.code !== 'E_PICKER_CANCELLED') { - // Alert.alert(ERROR_UPLOAD); - // } - // }); - // }; + const navigateToImagePicker = () => { + ImagePicker.openPicker({ + smartAlbums: [ + 'Favorites', + 'RecentlyAdded', + 'SelfPortraits', + 'Screenshots', + 'UserLibrary', + ], + width: 580, + height: 580, + cropping: true, + cropperToolbarTitle: 'Upload a moment', + mediaType: 'photo', + }) + .then((picture) => { + if ('path' in picture) { + navigation.navigate('CaptionScreen', { + screenType, + title: title, + image: picture, + }); + } + }) + .catch((err) => { + if (err.code && err.code !== 'E_PICKER_CANCELLED') { + Alert.alert(ERROR_UPLOAD); + } + }); + }; return ( <View style={[styles.container, externalStyles?.container]}> @@ -150,6 +156,13 @@ const Moment: React.FC<MomentProps> = ({ width={23} height={23} onPress={() => navigateToVideoPicker()} + color={'black'} + style={styles.horizontalMargin} + /> + <PlusIcon + width={23} + height={23} + onPress={() => navigateToImagePicker()} color={TAGG_LIGHT_BLUE} style={styles.horizontalMargin} /> @@ -179,7 +192,7 @@ const Moment: React.FC<MomentProps> = ({ /> ))} {(images === undefined || images.length === 0) && !userXId && ( - <TouchableOpacity onPress={() => navigateToVideoPicker()}> + <TouchableOpacity onPress={() => navigateToImagePicker()}> <LinearGradient colors={['rgba(105, 141, 211, 1)', 'rgba(105, 141, 211, 0.3)']}> <View style={styles.defaultImage}> diff --git a/src/services/MomentService.ts b/src/services/MomentService.ts index 28191421..d7a27146 100644 --- a/src/services/MomentService.ts +++ b/src/services/MomentService.ts @@ -1,7 +1,6 @@ import AsyncStorage from '@react-native-community/async-storage'; import {Image, Video} from 'react-native-image-crop-picker'; import RNFetchBlob from 'rn-fetch-blob'; -import {ProfileBody} from '../components'; import { MOMENTS_ENDPOINT, MOMENTTAG_ENDPOINT, @@ -14,7 +13,7 @@ import { ERROR_SOMETHING_WENT_WRONG, ERROR_SOMETHING_WENT_WRONG_REFRESH, } from '../constants/strings'; -import {MomentPostType, MomentTagType, ResponseURL} from '../types'; +import {MomentPostType, MomentTagType, PresignedURLResponse} from '../types'; import {checkImageUploadStatus} from '../utils'; export const postMoment = async ( @@ -217,7 +216,13 @@ export const deleteMomentTag = async (moment_tag_id: string) => { return false; } }; - +/** + * This function makes a request to the server in order to provide the client with a presigned URL. + * This is called first, in order for the client to directly upload a file to S3 + * @param value: string | undefined + * @param filename: string | undefined + * @returns a PresignedURLResponse object + */ export const handlePresignedURL = async ( value: string | undefined, filename: string | undefined, @@ -231,7 +236,7 @@ export const handlePresignedURL = async ( }), }); const status = response.status; - let data: ResponseURL = await response.json(); + let data: PresignedURLResponse = await response.json(); if (status === 200) { console.log(data.response_msg); return data; @@ -250,16 +255,29 @@ export const handlePresignedURL = async ( console.log(ERROR_SOMETHING_WENT_WRONG); } }; +/** + * This util function takes in the file object and the PresignedURLResponse object, creates form data from the latter, + * and makes a post request to the presigned URL, sending the file object inside of the form data. + * @param file: Video, Image, Undefined + * @param urlObj PresignedURLResponse | undefined + * @returns responseURL or boolean + */ export const handleVideoUpload = async ( file: Video | Image | undefined, - urlObj: ResponseURL | undefined, + urlObj: PresignedURLResponse | undefined, ) => { try { - console.log('inside of second handler: \n' + JSON.stringify(urlObj)); - console.log(urlObj?.response_url.url); - let fileName = file?.filename || ''; // check if null - //build payload packet - console.log('LOG'); + let fileName = file?.filename; + if (fileName === null || '') { + console.log('Invalid filename'); + return false; + } + if (urlObj === null || urlObj === undefined) { + console.log('Invalid urlObj'); + return false; + } + //build formData for POST request + // Could not get a forEach to work and could not assign directly, will look into cleaning this series of appends up later. const form = new FormData(); form.append('key', urlObj.response_url.fields.key); form.append( @@ -276,14 +294,12 @@ export const handleVideoUpload = async ( 'x-amz-signature', urlObj.response_url.fields['x-amz-signature'], ); - console.log('date: \n' + urlObj.response_url.fields['x-amz-date']); form.append('file', { uri: file?.sourceURL, + // other types such as 'quicktime' 'image' etc exist, and we can programmatically type this, but for now sticking with simple 'video' type: 'video', name: fileName, }); - console.log('FORM: \n' + JSON.stringify(form)); - const response = await fetch(urlObj.response_url.url, { method: 'POST', headers: { @@ -291,9 +307,7 @@ export const handleVideoUpload = async ( }, body: form, }); - console.log('response' + JSON.stringify(response)); const status = response.status; - console.log('responmse text' + response.text()); let data = await response.json(); if (status === 200) { console.log(data.response_msg); @@ -304,7 +318,6 @@ export const handleVideoUpload = async ( `Please make sure that the email / username entered is registered with us. You may contact our customer support at ${TAGG_CUSTOMER_SUPPORT}`, ); } else { - console.log('bad'); console.log(ERROR_SOMETHING_WENT_WRONG_REFRESH); } console.log(response); diff --git a/src/types/types.ts b/src/types/types.ts index 4da226b6..f6f23fc8 100644 --- a/src/types/types.ts +++ b/src/types/types.ts @@ -365,8 +365,8 @@ export type ReactionType = { id: string; type: ReactionOptionsType; }; - -export type ResponseURL = { +// used to handle direct S3 uploads by packaging presigned_url info into one object +export type PresignedURLResponse = { response_msg: string; response_url: { url: string; |