diff options
Diffstat (limited to 'src/components/moments')
-rw-r--r-- | src/components/moments/Moment.tsx | 52 | ||||
-rw-r--r-- | src/components/moments/MomentPost.tsx | 132 | ||||
-rw-r--r-- | src/components/moments/legacy/MomentPostContent.tsx | 49 |
3 files changed, 176 insertions, 57 deletions
diff --git a/src/components/moments/Moment.tsx b/src/components/moments/Moment.tsx index 9449271b..1e1cadce 100644 --- a/src/components/moments/Moment.tsx +++ b/src/components/moments/Moment.tsx @@ -1,6 +1,6 @@ import {useNavigation} from '@react-navigation/native'; import React from 'react'; -import {StyleProp, StyleSheet, View, ViewStyle} from 'react-native'; +import {Alert, StyleProp, StyleSheet, View, ViewStyle} from 'react-native'; import {Text} from 'react-native-animatable'; import {ScrollView, TouchableOpacity} from 'react-native-gesture-handler'; import LinearGradient from 'react-native-linear-gradient'; @@ -12,6 +12,8 @@ import UpIcon from '../../assets/icons/up_icon.svg'; import {TAGG_LIGHT_BLUE} from '../../constants'; import {MomentType, ScreenType} from '../../types'; import {normalize, SCREEN_WIDTH} from '../../utils'; +import {navigateToVideoPicker} from '../../utils/camera'; +import ImagePicker from 'react-native-image-crop-picker'; import MomentTile from './MomentTile'; interface MomentProps { @@ -41,6 +43,17 @@ const Moment: React.FC<MomentProps> = ({ }) => { const navigation = useNavigation(); + const navigateToCaptionScreenForVideo = (uri: string) => { + navigation.navigate('CaptionScreen', { + screenType, + title, + media: { + uri, + isVideo: true, + }, + }); + }; + const navigateToCameraScreen = () => { navigation.navigate('CameraScreen', { title, @@ -84,7 +97,37 @@ const Moment: React.FC<MomentProps> = ({ <PlusIcon width={23} height={23} - onPress={() => navigateToCameraScreen()} + onPress={() => + Alert.alert('Video Upload', 'pick one', [ + { + text: 'gallery', + onPress: () => + navigateToVideoPicker((vid) => + navigateToCaptionScreenForVideo(vid.path), + ), + }, + { + text: 'camera (simulator will not work)', + onPress: () => + ImagePicker.openCamera({ + mediaType: 'video', + }) + .then((vid) => { + if (vid.path) { + navigateToCaptionScreenForVideo(vid.path); + } + }) + .catch((err) => console.error(err)), + }, + ]) + } + color={'black'} + style={styles.horizontalMargin} + /> + <PlusIcon + width={23} + height={23} + onPress={navigateToCameraScreen} color={TAGG_LIGHT_BLUE} style={styles.horizontalMargin} /> @@ -114,7 +157,7 @@ const Moment: React.FC<MomentProps> = ({ /> ))} {(images === undefined || images.length === 0) && !userXId && ( - <TouchableOpacity onPress={() => navigateToCameraScreen()}> + <TouchableOpacity onPress={navigateToCameraScreen}> <LinearGradient colors={['rgba(105, 141, 211, 1)', 'rgba(105, 141, 211, 0.3)']}> <View style={styles.defaultImage}> @@ -150,9 +193,6 @@ const styles = StyleSheet.create({ color: TAGG_LIGHT_BLUE, maxWidth: '70%', }, - flexer: { - flex: 1, - }, scrollContainer: { height: SCREEN_WIDTH / 3.25, backgroundColor: '#eee', diff --git a/src/components/moments/MomentPost.tsx b/src/components/moments/MomentPost.tsx index 6eccf5ab..319542f9 100644 --- a/src/components/moments/MomentPost.tsx +++ b/src/components/moments/MomentPost.tsx @@ -1,5 +1,5 @@ import {useNavigation} from '@react-navigation/native'; -import React, {useContext, useEffect, useRef, useState} from 'react'; +import React, {useContext, useEffect, useMemo, useRef, useState} from 'react'; import { Image, KeyboardAvoidingView, @@ -12,6 +12,7 @@ import { View, } from 'react-native'; import Animated, {EasingNode} from 'react-native-reanimated'; +import Video from 'react-native-video'; import {useDispatch, useSelector, useStore} from 'react-redux'; import {headerBarOptions} from '../../routes'; import {MomentContext} from '../../screens/profile/IndividualMoment'; @@ -71,7 +72,16 @@ const MomentPost: React.FC<MomentPostProps> = ({ const [momentTagId, setMomentTagId] = useState<string>(''); const imageRef = useRef(null); - const {keyboardVisible} = useContext(MomentContext); + const videoRef = useRef<Video>(null); + const {keyboardVisible, currentVisibleMomentId} = useContext(MomentContext); + const isVideo = !( + moment.moment_url.endsWith('jpg') || + moment.moment_url.endsWith('JPG') || + moment.moment_url.endsWith('PNG') || + moment.moment_url.endsWith('png') || + moment.moment_url.endsWith('GIF') || + moment.moment_url.endsWith('gif') + ); /* * Load tags on initial render to pass tags data to moment header and content @@ -126,13 +136,15 @@ const MomentPost: React.FC<MomentPostProps> = ({ * determine if image must be displayed in full screen or not */ useEffect(() => { - Image.getSize( - moment.moment_url, - (w, h) => { - setAspectRatio(w / h); - }, - (err) => console.log(err), - ); + if (!isVideo) { + Image.getSize( + moment.moment_url, + (w, h) => { + setAspectRatio(w / h); + }, + (err) => console.log(err), + ); + } }, []); /* @@ -155,22 +167,31 @@ const MomentPost: React.FC<MomentPostProps> = ({ } }, [keyboardVisible, hideText]); - const MomentPosterPreview = () => ( - <View style={styles.momentPosterContainer}> - <TouchableOpacity - onPress={() => - navigateToProfile(state, dispatch, navigation, screenType, user) - } - style={styles.header}> - <TaggAvatar - style={styles.avatar} - userXId={userXId} - screenType={screenType} - editable={false} - /> - <Text style={styles.headerText}>{user.username}</Text> - </TouchableOpacity> - </View> + useEffect(() => { + if (moment.moment_id !== currentVisibleMomentId) { + videoRef.current?.seek(0); + } + }, [currentVisibleMomentId]); + + const momentPosterPreview = useMemo( + () => ( + <View style={styles.momentPosterContainer}> + <TouchableOpacity + onPress={() => + navigateToProfile(state, dispatch, navigation, screenType, user) + } + style={styles.header}> + <TaggAvatar + style={styles.avatar} + userXId={userXId} + screenType={screenType} + editable={false} + /> + <Text style={styles.headerText}>{user.username}</Text> + </TouchableOpacity> + </View> + ), + [user.username], ); return ( @@ -178,17 +199,44 @@ const MomentPost: React.FC<MomentPostProps> = ({ <StatusBar barStyle={'light-content'} /> <View style={styles.mainContainer}> <View style={styles.imageContainer}> - <Image - source={{uri: moment.moment_url}} - style={[ - styles.image, - { - height: SCREEN_WIDTH / aspectRatio, - }, - ]} - resizeMode={'contain'} - ref={imageRef} - /> + {isVideo ? ( + <View + ref={imageRef} + style={[ + styles.media, + { + height: SCREEN_WIDTH / aspectRatio, + }, + ]}> + <Video + ref={videoRef} + source={{ + uri: moment.moment_url, + }} + volume={1} + style={[ + styles.media, + { + height: SCREEN_WIDTH / aspectRatio, + }, + ]} + repeat={true} + resizeMode={'contain'} + onLoad={(response) => { + const {width, height} = response.naturalSize; + setAspectRatio(width / height); + }} + paused={moment.moment_id !== currentVisibleMomentId} + /> + </View> + ) : ( + <Image + source={{uri: moment.moment_url}} + style={styles.media} + resizeMode={'contain'} + ref={imageRef} + /> + )} </View> {visible && ( <Animated.View style={[styles.tagsContainer, {opacity: fadeValue}]}> @@ -233,9 +281,13 @@ const MomentPost: React.FC<MomentPostProps> = ({ /> )} <View style={styles.commentsCountContainer}> - <CommentsCount moment={moment} screenType={screenType} /> + <CommentsCount + momentId={moment.moment_id} + count={commentCount} + screenType={screenType} + /> </View> - <MomentPosterPreview /> + {momentPosterPreview} {!hideText && ( <> {moment.caption !== '' && @@ -281,8 +333,9 @@ const MomentPost: React.FC<MomentPostProps> = ({ }; const styles = StyleSheet.create({ - image: { + media: { zIndex: 0, + flex: 1, }, imageContainer: { height: SCREEN_HEIGHT, @@ -340,6 +393,7 @@ const styles = StyleSheet.create({ }, commentsCountContainer: { position: 'absolute', + zIndex: 3, right: '2%', bottom: SCREEN_HEIGHT * 0.12, }, diff --git a/src/components/moments/legacy/MomentPostContent.tsx b/src/components/moments/legacy/MomentPostContent.tsx index 6388be27..0e6e5eed 100644 --- a/src/components/moments/legacy/MomentPostContent.tsx +++ b/src/components/moments/legacy/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'; @@ -32,14 +33,12 @@ interface MomentPostContentProps extends ViewProps { screenType: ScreenType; moment: MomentPostType; momentTags: MomentTagType[]; - index: number; } const MomentPostContent: React.FC<MomentPostContentProps> = ({ screenType, moment, style, momentTags, - index, }) => { const [tags, setTags] = useState<MomentTagType[]>(momentTags); const state: RootState = useStore().getState(); @@ -55,8 +54,14 @@ const MomentPostContent: React.FC<MomentPostContentProps> = ({ ); const [commentPreview, setCommentPreview] = useState<MomentCommentPreviewType | null>(moment.comment_preview); - const {keyboardVisible, scrollTo} = useContext(MomentContext); + const {keyboardVisible} = 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); @@ -78,7 +83,6 @@ const MomentPostContent: React.FC<MomentPostContentProps> = ({ setHideText(false); } }, [keyboardVisible, hideText]); - return ( <View style={[styles.container, style]}> <TouchableWithoutFeedback @@ -86,12 +90,34 @@ 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 ? ( + <View ref={imageRef}> + <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} + repeat={true} + /> + </View> + ) : ( + <Image + ref={imageRef} + style={styles.image} + source={{uri: moment.moment_url}} + resizeMode={'cover'} + /> + )} {tags.length > 0 && ( <Image source={require('../../assets/icons/tag_indicate.png')} @@ -115,7 +141,7 @@ const MomentPostContent: React.FC<MomentPostContentProps> = ({ renderTextWithMentions({ value: moment.caption, styles: styles.captionText, - partTypes: mentionPartTypes('white'), + partTypes: mentionPartTypes('white', 'caption'), onPress: (user: UserType) => navigateToProfile( state, @@ -145,7 +171,6 @@ const MomentPostContent: React.FC<MomentPostContentProps> = ({ }} onFocus={() => { setHideText(true); - scrollTo(index); }} isKeyboardAvoiding={false} theme={'dark'} |