aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorIvan Chen <ivan@tagg.id>2021-06-23 17:08:20 -0400
committerIvan Chen <ivan@tagg.id>2021-06-23 17:08:20 -0400
commit345a20590da5fd1cabc85c4e7b0b72c05e1f0665 (patch)
treefec050399a051c3d3cc5b3bed44d450ea20f258f /src
parent66dcf88ab09fbd73e234e209e270e2b31c867247 (diff)
Squashed commit of the following:
commit 8c2b915678b852f597c38ab00d18c22bf62d2051 Merge: cd586326 16f6341d Author: Ivan Chen <ivan@tagg.id> Date: Wed Jun 23 16:26:12 2021 -0400 Merge pull request #473 from IvanIFChen/tma938-video-from-camera-video-streaming [TMA-938] Video From Camera & Video Streaming commit 16f6341daff56f827fbb6c6ade9cf1238e8e5f3e Author: Ivan Chen <ivan@tagg.id> Date: Wed Jun 23 14:22:29 2021 -0400 Lint commit 7e7a3ea6b6462d295717db052c37d87e1f58a091 Author: Ivan Chen <ivan@tagg.id> Date: Wed Jun 23 14:20:00 2021 -0400 Change to use image crop pickers instead commit 25d1a6514c9df784df27d22da648340ae018c1f8 Author: Ivan Chen <ivan@tagg.id> Date: Wed Jun 23 13:37:39 2021 -0400 Minor logic cleanup commit 4ecc4525738dc8a56c9f37a05d0870e54cfa5be9 Author: Ivan Chen <ivan@tagg.id> Date: Tue Jun 22 19:21:26 2021 -0400 Lint commit c3066187b9d253767e32880cc35ddd1abc6db6b3 Author: Ivan Chen <ivan@tagg.id> Date: Tue Jun 22 19:16:04 2021 -0400 Remove test code commit ab13c937f1de947e68df03b443cf9fccb0cd54c9 Author: Ivan Chen <ivan@tagg.id> Date: Tue Jun 22 19:14:06 2021 -0400 Add alert for gallery and camera commit 0561794c67d827c918029f2e06572fd03b4531fd Author: Ivan Chen <ivan@tagg.id> Date: Tue Jun 22 18:51:57 2021 -0400 Finish poc for for video streaming commit 457b5cf34c032e7b73f972d5ba801ff420915190 Author: Ivan Chen <ivan@tagg.id> Date: Tue Jun 22 18:37:20 2021 -0400 Squashed commit of the following: commit b6e4676b6ea262580453963ed6cfd85932d32341 Author: Ivan Chen <ivan@tagg.id> Date: Mon Jun 21 19:04:08 2021 -0400 Add library, Add sample code commit 49dfe6a52e09bdb218e2b1ceb5a8df9ed46873f1 Author: Ivan Chen <ivan@tagg.id> Date: Tue Jun 22 18:37:12 2021 -0400 Squashed commit of the following: commit b1c2002caa349dc96f81d3cc3e00ea545f4e654e Author: Ivan Chen <ivan@tagg.id> Date: Tue Jun 22 15:28:18 2021 -0400 Add video for camerea commit ee890e517dd3688a4fd63c64592fdb6ce683d7b4 Author: Ivan Chen <ivan@tagg.id> Date: Tue Jun 22 18:36:47 2021 -0400 Improve poc UX
Diffstat (limited to 'src')
-rw-r--r--src/components/moments/Moment.tsx50
-rw-r--r--src/components/moments/MomentPostContent.tsx41
-rw-r--r--src/components/profile/MomentMoreInfoDrawer.tsx11
-rw-r--r--src/components/profile/ProfileBody.tsx1
-rw-r--r--src/constants/regex.ts2
-rw-r--r--src/services/MomentService.ts16
6 files changed, 97 insertions, 24 deletions
diff --git a/src/components/moments/Moment.tsx b/src/components/moments/Moment.tsx
index 6441bca3..1c266307 100644
--- a/src/components/moments/Moment.tsx
+++ b/src/components/moments/Moment.tsx
@@ -5,6 +5,7 @@ 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 {useDispatch, useSelector} from 'react-redux';
import DeleteIcon from '../../assets/icons/delete-logo.svg';
import DownIcon from '../../assets/icons/down_icon.svg';
import BigPlusIcon from '../../assets/icons/plus-icon-white.svg';
@@ -16,6 +17,8 @@ import {
handlePresignedURL,
handleVideoUpload,
} from '../../services/MomentService';
+import {loadUserMoments} from '../../store/actions';
+import {RootState} from '../../store/rootReducer';
import {MomentType, ScreenType} from '../../types';
import {normalize, SCREEN_WIDTH} from '../../utils';
import MomentTile from './MomentTile';
@@ -46,6 +49,23 @@ const Moment: React.FC<MomentProps> = ({
externalStyles,
}) => {
const navigation = useNavigation();
+ const dispatch = useDispatch();
+ const {
+ user: {userId},
+ } = useSelector((state: RootState) => state.user);
+
+ const uploadVideo = async (filePath: string) => {
+ const randHash = Math.random().toString(36).substring(7);
+ const filename = `poc_${randHash}.mov`;
+ const presignedURL = await handlePresignedURL(filename, title);
+ if (presignedURL) {
+ console.log('presigned' + JSON.stringify(presignedURL));
+ Alert.alert('Upload begin in background...');
+ await handleVideoUpload(filename, filePath, presignedURL);
+ Alert.alert('Finish uploading, refreshing moments...');
+ dispatch(loadUserMoments(userId));
+ }
+ };
/**
* 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,
@@ -58,12 +78,19 @@ const Moment: React.FC<MomentProps> = ({
mediaType: 'video',
})
.then(async (vid) => {
+ // if ('path' in vid) {
+ // console.log(vid);
+ // // vid.path is compressed mp4, vid.sourceURL is uncompressed original
+ // if (vid.path) {
+ // uploadVideo(vid.path);
+ // }
if (vid.path) {
+ const randHash = Math.random().toString(36).substring(7);
navigation.navigate('CaptionScreen', {
screenType,
title,
media: {
- filename: `poc_${Math.random().toString(36).substring(7)}.mov`,
+ filename: `poc_${randHash}.mov`,
uri: vid.path,
isVideo: true,
},
@@ -148,7 +175,26 @@ const Moment: React.FC<MomentProps> = ({
<PlusIcon
width={23}
height={23}
- onPress={() => navigateToVideoPicker()}
+ onPress={() =>
+ Alert.alert('Video Upload', 'pick one', [
+ {
+ text: 'gallery',
+ onPress: navigateToVideoPicker,
+ },
+ {
+ text: 'camera (simulator will not work)',
+ onPress: () =>
+ ImagePicker.openCamera({
+ mediaType: 'video',
+ }).then((vid) => {
+ console.log(vid);
+ if (vid.path) {
+ uploadVideo(vid.path);
+ }
+ }),
+ },
+ ])
+ }
color={'black'}
style={styles.horizontalMargin}
/>
diff --git a/src/components/moments/MomentPostContent.tsx b/src/components/moments/MomentPostContent.tsx
index aca2999c..27a68e47 100644
--- a/src/components/moments/MomentPostContent.tsx
+++ b/src/components/moments/MomentPostContent.tsx
@@ -3,6 +3,7 @@ import React, {useContext, useEffect, useRef, useState} from 'react';
import {Image, StyleSheet, Text, View, ViewProps} from 'react-native';
import {TouchableWithoutFeedback} from 'react-native-gesture-handler';
import Animated, {EasingNode} from 'react-native-reanimated';
+import Video from 'react-native-video';
import {useDispatch, useStore} from 'react-redux';
import {MomentContext} from '../../screens/profile/IndividualMoment';
import {RootState} from '../../store/rootReducer';
@@ -54,6 +55,12 @@ const MomentPostContent: React.FC<MomentPostContentProps> = ({
useState<MomentCommentPreviewType | null>(moment.comment_preview);
const {keyboardVisible, scrollTo} = useContext(MomentContext);
const [hideText, setHideText] = useState(false);
+ const isVideo = !(
+ moment.moment_url.endsWith('jpg') ||
+ moment.moment_url.endsWith('JPG') ||
+ moment.moment_url.endsWith('PNG') ||
+ moment.moment_url.endsWith('png')
+ );
useEffect(() => {
setTags(momentTags);
@@ -83,12 +90,32 @@ const MomentPostContent: React.FC<MomentPostContentProps> = ({
setVisible(!visible);
setFadeValue(new Animated.Value(0));
}}>
- <Image
- ref={imageRef}
- style={styles.image}
- source={{uri: moment.moment_url}}
- resizeMode={'cover'}
- />
+ {isVideo ? (
+ <Video
+ // ref={imageRef}
+ source={{
+ uri: moment.moment_url,
+ }}
+ // HLS m3u8 version
+ // source={{
+ // uri: 'https://multiplatform-f.akamaihd.net/i/multi/will/bunny/big_buck_bunny_,640x360_400,640x360_700,640x360_1000,950x540_1500,.f4v.csmil/master.m3u8',
+ // }}
+ // mp4 version
+ // source={{
+ // uri: 'http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4',
+ // }}
+ volume={1}
+ style={styles.image}
+ // style={styles.video}
+ />
+ ) : (
+ <Image
+ ref={imageRef}
+ style={styles.image}
+ source={{uri: moment.moment_url}}
+ resizeMode={'cover'}
+ />
+ )}
{tags.length > 0 && (
<Image
source={require('../../assets/icons/tag_indicate.png')}
@@ -96,7 +123,7 @@ const MomentPostContent: React.FC<MomentPostContentProps> = ({
/>
)}
</TouchableWithoutFeedback>
- {visible && (
+ {visible && !isVideo && (
<Animated.View style={[styles.tapTag, {opacity: fadeValue}]}>
<MomentTags
editing={false}
diff --git a/src/components/profile/MomentMoreInfoDrawer.tsx b/src/components/profile/MomentMoreInfoDrawer.tsx
index a796ffd8..c70df875 100644
--- a/src/components/profile/MomentMoreInfoDrawer.tsx
+++ b/src/components/profile/MomentMoreInfoDrawer.tsx
@@ -32,6 +32,13 @@ interface MomentMoreInfoDrawerProps extends ViewProps {
tags: MomentTagType[];
}
+type DrawerButtonType = [
+ string,
+ (event: GestureResponderEvent) => void,
+ JSX.Element?,
+ TextStyle?,
+][];
+
const MomentMoreInfoDrawer: React.FC<MomentMoreInfoDrawerProps> = (props) => {
const {
setIsOpen,
@@ -46,9 +53,7 @@ const MomentMoreInfoDrawer: React.FC<MomentMoreInfoDrawerProps> = (props) => {
const navigation = useNavigation();
- const [drawerButtons, setDrawerButtons] = useState<
- [string, (event: GestureResponderEvent) => void, JSX.Element?, TextStyle?][]
- >([]);
+ const [drawerButtons, setDrawerButtons] = useState<DrawerButtonType>([]);
const handleDeleteMoment = async () => {
setIsOpen(false);
diff --git a/src/components/profile/ProfileBody.tsx b/src/components/profile/ProfileBody.tsx
index c0ee508a..cc001516 100644
--- a/src/components/profile/ProfileBody.tsx
+++ b/src/components/profile/ProfileBody.tsx
@@ -80,7 +80,6 @@ const ProfileBody: React.FC<ProfileBodyProps> = ({
);
}}>{`${website}`}</Text>
)}
-
{userXId && isBlocked && (
<View style={styles.toggleButtonContainer}>
<ToggleButton
diff --git a/src/constants/regex.ts b/src/constants/regex.ts
index f934185d..61523203 100644
--- a/src/constants/regex.ts
+++ b/src/constants/regex.ts
@@ -36,7 +36,7 @@ export const nameRegex: RegExp = /^[A-Za-z'\-,. ]{2,20}$/;
* - match alphanumerics, and special characters used in URLs
*/
export const websiteRegex: RegExp =
- /^$|^(https?:\/\/)?(www\.)?[-a-zA-Z0-9@:%._+~#=]{1,50}\.[a-zA-Z0-9()]{2,6}\b([-a-zA-Z0-9()@:%_+.~#?&\/=]{0,35})$/;
+ /^$|^(https?:\/\/)?(www\.)?[-a-zA-Z0-9@:%._+~#=]{1,50}\.[a-zA-Z0-9()]{2,6}\b([-a-zA-Z0-9()@:%_+.~#?&/=]{0,35})$/;
/**
* The website regex has the following constraints
diff --git a/src/services/MomentService.ts b/src/services/MomentService.ts
index d0ed56ab..da1bfb97 100644
--- a/src/services/MomentService.ts
+++ b/src/services/MomentService.ts
@@ -1,5 +1,4 @@
import AsyncStorage from '@react-native-community/async-storage';
-import {Image, Video} from 'react-native-image-crop-picker';
import RNFetchBlob from 'rn-fetch-blob';
import {
MOMENTS_ENDPOINT,
@@ -262,20 +261,17 @@ export const handlePresignedURL = async (
/**
* 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 filename: the filename
+ * @param filePath: the path to the file, including filename
* @param urlObj PresignedURLResponse | undefined
* @returns responseURL or boolean
*/
export const handleVideoUpload = async (
- file: Video | Image | undefined,
+ filename: string,
+ filePath: string,
urlObj: PresignedURLResponse | undefined,
) => {
try {
- let fileName = file?.filename;
- if (fileName === null || '') {
- console.log('Invalid filename');
- return false;
- }
if (urlObj === null || urlObj === undefined) {
console.log('Invalid urlObj');
return false;
@@ -299,10 +295,10 @@ export const handleVideoUpload = async (
urlObj.response_url.fields['x-amz-signature'],
);
form.append('file', {
- uri: file?.sourceURL,
+ uri: filePath,
// 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,
+ name: filename,
});
const response = await fetch(urlObj.response_url.url, {
method: 'POST',