aboutsummaryrefslogtreecommitdiff
path: root/src/components/moments
diff options
context:
space:
mode:
Diffstat (limited to 'src/components/moments')
-rw-r--r--src/components/moments/Moment.tsx52
-rw-r--r--src/components/moments/MomentPost.tsx132
-rw-r--r--src/components/moments/legacy/MomentPostContent.tsx49
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'}