diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/components/moments/Moment.tsx | 54 | ||||
-rw-r--r-- | src/components/moments/MomentPostContent.tsx | 41 | ||||
-rw-r--r-- | src/components/profile/MomentMoreInfoDrawer.tsx | 11 | ||||
-rw-r--r-- | src/components/profile/ProfileBody.tsx | 1 | ||||
-rw-r--r-- | src/constants/regex.ts | 2 | ||||
-rw-r--r-- | src/screens/chat/ChatListScreen.tsx | 2 | ||||
-rw-r--r-- | src/services/MomentService.ts | 16 |
7 files changed, 94 insertions, 33 deletions
diff --git a/src/components/moments/Moment.tsx b/src/components/moments/Moment.tsx index 34b2c7ea..e4acebdf 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, @@ -62,21 +82,16 @@ const Moment: React.FC<MomentProps> = ({ 'Screenshots', 'UserLibrary', ], - width: 580, - height: 580, - cropping: false, cropperToolbarTitle: 'select a video', mediaType: 'video', }) .then(async (vid) => { if ('path' in vid) { - let fileName = vid.filename || ''; - if (fileName.endsWith('.heic') || fileName.endsWith('.HEIC')) { - fileName = fileName.split('.')[0] + '.jpg'; + console.log(vid); + // vid.path is compressed mp4, vid.sourceURL is uncompressed original + if (vid.path) { + uploadVideo(vid.path); } - let presignedURL = await handlePresignedURL(fileName, title); - console.log('presigned' + JSON.stringify(presignedURL)); - handleVideoUpload(vid, presignedURL); } }) .catch((err) => { @@ -153,7 +168,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/screens/chat/ChatListScreen.tsx b/src/screens/chat/ChatListScreen.tsx index 1df5c2da..0f5d8073 100644 --- a/src/screens/chat/ChatListScreen.tsx +++ b/src/screens/chat/ChatListScreen.tsx @@ -6,10 +6,10 @@ import {useStore} from 'react-redux'; import {ChannelList, Chat} from 'stream-chat-react-native'; import {ChatContext} from '../../App'; import {TabsGradient} from '../../components'; +import EmptyContentView from '../../components/common/EmptyContentView'; import {ChannelPreview, MessagesHeader} from '../../components/messages'; import {MainStackParams} from '../../routes'; import {RootState} from '../../store/rootReducer'; -import EmptyContentView from '../../components/common/EmptyContentView'; import { LocalAttachmentType, LocalChannelType, 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', |