diff options
Diffstat (limited to 'src/screens/profile')
| -rw-r--r-- | src/screens/profile/CaptionScreen.tsx | 113 | ||||
| -rw-r--r-- | src/screens/profile/IndividualMoment.tsx | 55 |
2 files changed, 105 insertions, 63 deletions
diff --git a/src/screens/profile/CaptionScreen.tsx b/src/screens/profile/CaptionScreen.tsx index 75533a9b..05db8ed7 100644 --- a/src/screens/profile/CaptionScreen.tsx +++ b/src/screens/profile/CaptionScreen.tsx @@ -15,6 +15,7 @@ import { } from 'react-native'; import {MentionInputControlled} from '../../components'; import {Button, normalize} from 'react-native-elements'; +import Video from 'react-native-video'; import {useDispatch, useSelector} from 'react-redux'; import FrontArrow from '../../assets/icons/front-arrow.svg'; import {SearchBackground} from '../../components'; @@ -27,7 +28,13 @@ import { SUCCESS_PIC_UPLOAD, } from '../../constants/strings'; import {MainStackParams} from '../../routes'; -import {patchMoment, postMoment, postMomentTags} from '../../services'; +import { + handlePresignedURL, + handleVideoUpload, + patchMoment, + postMoment, + postMomentTags, +} from '../../services'; import { loadUserMoments, updateProfileCompletionStage, @@ -51,7 +58,7 @@ interface CaptionScreenProps { } const CaptionScreen: React.FC<CaptionScreenProps> = ({route, navigation}) => { - const {title, image, screenType, selectedTags, moment} = route.params; + const {title, screenType, selectedTags, moment} = route.params; const { user: {userId}, } = useSelector((state: RootState) => state.user); @@ -62,6 +69,16 @@ const CaptionScreen: React.FC<CaptionScreenProps> = ({route, navigation}) => { selectedTags ? selectedTags : [], ); const [taggedList, setTaggedList] = useState<string>(''); + const mediaUri = moment ? moment.moment_url : route.params.media!.uri; + // TODO: change this once moment refactor is done + const isMediaAVideo = moment + ? !( + moment.moment_url.endsWith('.jpg') || + moment.moment_url.endsWith('.JPG') || + moment.moment_url.endsWith('.png') || + moment.moment_url.endsWith('.PNG') + ) + : route.params.media?.isVideo ?? false; useEffect(() => { setTags(selectedTags ? selectedTags : []); @@ -120,36 +137,50 @@ const CaptionScreen: React.FC<CaptionScreenProps> = ({route, navigation}) => { const handleShare = async () => { setLoading(true); - if (!image?.filename || !title) { - return; - } - const momentResponse = await postMoment( - image.filename, - image.path, - caption, - title, - userId, - ); - if (!momentResponse) { + if (moment || !title) { handleFailed(); return; } - const momentTagResponse = await postMomentTags( - momentResponse.moment_id, - formattedTags(), - ); - if (!momentTagResponse) { - handleFailed(); - return; + let profileCompletionStage; + let momentId; + // separate upload logic for image/video + if (isMediaAVideo) { + const presignedURLResponse = await handlePresignedURL(title); + if (!presignedURLResponse) { + handleFailed(); + return; + } + momentId = presignedURLResponse.moment_id; + const fileHash = presignedURLResponse.response_url.fields.key; + if (fileHash !== null && fileHash !== '' && fileHash !== undefined) { + await handleVideoUpload(mediaUri, presignedURLResponse); + } else { + handleFailed(); + } + } else { + const momentResponse = await postMoment(mediaUri, caption, title, userId); + if (!momentResponse) { + handleFailed(); + return; + } + profileCompletionStage = momentResponse.profile_completion_stage; + momentId = momentResponse.moment_id; + } + if (momentId) { + const momentTagResponse = await postMomentTags(momentId, formattedTags()); + if (!momentTagResponse) { + handleFailed(); + return; + } } dispatch(loadUserMoments(userId)); - dispatch( - updateProfileCompletionStage(momentResponse.profile_completion_stage), - ); + if (profileCompletionStage) { + dispatch(updateProfileCompletionStage(profileCompletionStage)); + } handleSuccess(); }; - const handleDone = async () => { + const handleDoneEditing = async () => { setLoading(true); if (moment?.moment_id) { const success = await patchMoment( @@ -186,19 +217,26 @@ const CaptionScreen: React.FC<CaptionScreenProps> = ({route, navigation}) => { title={moment ? 'Done' : 'Share'} titleStyle={styles.shareButtonTitle} buttonStyle={styles.button} - onPress={moment ? handleDone : handleShare} + onPress={moment ? handleDoneEditing : handleShare} /> </View> <CaptionScreenHeader style={styles.header} - {...{title: moment ? moment.moment_category : title}} - /> - {/* this is the image we want to center our tags' initial location within */} - <Image - style={styles.image} - source={{uri: moment ? moment.moment_url : image?.path}} - resizeMode={'contain'} + {...{title: moment ? moment.moment_category : title ?? ''}} /> + {isMediaAVideo ? ( + <Video + style={styles.media} + source={{uri: mediaUri}} + repeat={true} + /> + ) : ( + <Image + style={styles.media} + source={{uri: mediaUri}} + resizeMode={'contain'} + /> + )} <MentionInputControlled containerStyle={styles.text} placeholder="Write something....." @@ -210,11 +248,10 @@ const CaptionScreen: React.FC<CaptionScreenProps> = ({route, navigation}) => { <TouchableOpacity onPress={() => navigation.navigate('TagFriendsScreen', { - imagePath: moment - ? moment.moment_url - : image - ? image.path - : '', + media: { + uri: mediaUri, + isVideo: isMediaAVideo, + }, selectedTags: tags, }) } @@ -257,7 +294,7 @@ const styles = StyleSheet.create({ header: { marginVertical: 20, }, - image: { + media: { position: 'relative', width: SCREEN_WIDTH, aspectRatio: 1, diff --git a/src/screens/profile/IndividualMoment.tsx b/src/screens/profile/IndividualMoment.tsx index ca31ad5b..7d231312 100644 --- a/src/screens/profile/IndividualMoment.tsx +++ b/src/screens/profile/IndividualMoment.tsx @@ -1,22 +1,17 @@ import {RouteProp} from '@react-navigation/native'; import {StackNavigationProp} from '@react-navigation/stack'; import React, {useEffect, useRef, useState} from 'react'; -import {FlatList, Keyboard} from 'react-native'; +import {FlatList, Keyboard, ViewToken} from 'react-native'; import {useSelector} from 'react-redux'; import {MomentPost, TabsGradient} from '../../components'; -import {AVATAR_DIM} from '../../constants'; import {MainStackParams} from '../../routes'; import {RootState} from '../../store/rootreducer'; import {MomentPostType} from '../../types'; -import {isIPhoneX} from '../../utils'; - -/** - * Individual moment view opened when user clicks on a moment tile - */ +import {SCREEN_HEIGHT} from '../../utils'; type MomentContextType = { keyboardVisible: boolean; - scrollTo: (index: number) => void; + currentVisibleMomentId: string | undefined; }; export const MomentContext = React.createContext({} as MomentContextType); @@ -48,6 +43,26 @@ const IndividualMoment: React.FC<IndividualMomentProps> = ({route}) => { ); const initialIndex = momentData.findIndex((m) => m.moment_id === moment_id); const [keyboardVisible, setKeyboardVisible] = useState(false); + const [currentVisibleMomentId, setCurrentVisibleMomentId] = useState< + string | undefined + >(); + const [viewableItems, setViewableItems] = useState<ViewToken[]>([]); + + // https://stackoverflow.com/a/57502343 + const viewabilityConfigCallback = useRef( + (info: {viewableItems: ViewToken[]}) => { + setViewableItems(info.viewableItems); + }, + ); + + useEffect(() => { + if (viewableItems.length > 0) { + const index = viewableItems[0].index; + if (index !== null && momentData.length > 0) { + setCurrentVisibleMomentId(momentData[index].moment_id); + } + } + }, [viewableItems]); useEffect(() => { const showKeyboard = () => setKeyboardVisible(true); @@ -60,20 +75,11 @@ const IndividualMoment: React.FC<IndividualMomentProps> = ({route}) => { }; }, []); - const scrollTo = (index: number) => { - // TODO: make this dynamic - const offset = isIPhoneX() ? -(AVATAR_DIM + 100) : -(AVATAR_DIM + 160); - scrollRef.current?.scrollToIndex({ - index: index, - viewOffset: offset, - }); - }; - return ( <MomentContext.Provider value={{ keyboardVisible, - scrollTo, + currentVisibleMomentId, }}> <FlatList ref={scrollRef} @@ -89,13 +95,12 @@ const IndividualMoment: React.FC<IndividualMomentProps> = ({route}) => { keyExtractor={(item, _) => item.moment_id} showsVerticalScrollIndicator={false} initialScrollIndex={initialIndex} - onScrollToIndexFailed={(info) => { - setTimeout(() => { - scrollRef.current?.scrollToIndex({ - index: info.index, - }); - }, 500); - }} + onViewableItemsChanged={viewabilityConfigCallback.current} + getItemLayout={(data, index) => ({ + length: SCREEN_HEIGHT, + offset: SCREEN_HEIGHT * index, + index, + })} pagingEnabled /> <TabsGradient /> |
