aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGeorge Rusu <george@tagg.id>2021-06-22 04:32:39 -0700
committerGeorge Rusu <george@tagg.id>2021-06-22 04:32:39 -0700
commitae970faf6f560cc2fb55488acd49a04cfcb942c5 (patch)
tree1e1fd28fe58f68573cb40913dc72968a043ba396 /src
parent3065e921b858f68eb1c1746bba116c01cbfb01dd (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.tsx91
-rw-r--r--src/services/MomentService.ts45
-rw-r--r--src/types/types.ts4
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;