aboutsummaryrefslogtreecommitdiff
path: root/src/components/moments
diff options
context:
space:
mode:
Diffstat (limited to 'src/components/moments')
-rw-r--r--src/components/moments/MomentPost.tsx28
-rw-r--r--src/components/moments/MomentUploadProgressBar.tsx221
-rw-r--r--src/components/moments/TrimmerPlayer.tsx7
-rw-r--r--src/components/moments/index.ts1
4 files changed, 253 insertions, 4 deletions
diff --git a/src/components/moments/MomentPost.tsx b/src/components/moments/MomentPost.tsx
index 2e5807f4..f6917784 100644
--- a/src/components/moments/MomentPost.tsx
+++ b/src/components/moments/MomentPost.tsx
@@ -46,12 +46,14 @@ interface MomentPostProps {
moment: MomentPostType;
userXId: string | undefined;
screenType: ScreenType;
+ updateMomentViewCount: () => void;
}
const MomentPost: React.FC<MomentPostProps> = ({
moment,
userXId,
screenType,
+ updateMomentViewCount,
}) => {
const navigation = useNavigation();
const dispatch = useDispatch();
@@ -197,11 +199,18 @@ const MomentPost: React.FC<MomentPostProps> = ({
screenType={screenType}
editable={false}
/>
- <Text style={styles.headerText}>{user.username}</Text>
+ <View style={styles.profilePreviewContainer}>
+ <Text style={styles.headerText}>{user.username}</Text>
+ <Text style={styles.viewCount}>
+ {moment.view_count <= 9999
+ ? `${moment.view_count} Views`
+ : `${(moment.view_count / 1000).toFixed(1)}K Views`}
+ </Text>
+ </View>
</TouchableOpacity>
</View>
),
- [user.username],
+ [user.username, moment.view_count],
);
const momentMedia = isVideo ? (
@@ -227,6 +236,8 @@ const MomentPost: React.FC<MomentPostProps> = ({
setVideoProgress(localProgress);
}
}}
+ onEnd={updateMomentViewCount}
+
/>
</View>
) : (
@@ -432,7 +443,17 @@ const styles = StyleSheet.create({
fontSize: 15,
fontWeight: 'bold',
color: 'white',
- paddingHorizontal: '3%',
+ },
+ viewCount: {
+ height: normalize(12),
+ left: 0,
+ top: '8%',
+ fontSize: 11,
+ fontWeight: '600',
+ lineHeight: 13,
+ letterSpacing: 0.08,
+ textAlign: 'left',
+ color: '#fff',
},
header: {
alignItems: 'center',
@@ -500,6 +521,7 @@ const styles = StyleSheet.create({
position: 'absolute',
top: isIPhoneX() ? 75 : 70,
},
+ profilePreviewContainer: {paddingHorizontal: '3%'},
});
export default MomentPost;
diff --git a/src/components/moments/MomentUploadProgressBar.tsx b/src/components/moments/MomentUploadProgressBar.tsx
new file mode 100644
index 00000000..d56a8337
--- /dev/null
+++ b/src/components/moments/MomentUploadProgressBar.tsx
@@ -0,0 +1,221 @@
+import React, {useEffect} from 'react';
+import {Image, StyleSheet, Text} from 'react-native';
+import {View} from 'react-native-animatable';
+import {
+ cancelAnimation,
+ Easing,
+ useSharedValue,
+ withTiming,
+} from 'react-native-reanimated';
+import {useDispatch, useSelector} from 'react-redux';
+import {checkMomentDoneProcessing} from '../../services';
+import {loadUserMoments} from '../../store/actions';
+import {setMomentUploadProgressBar} from '../../store/reducers';
+import {RootState} from '../../store/rootReducer';
+import {MomentUploadStatusType} from '../../types';
+import {normalize, SCREEN_WIDTH, StatusBarHeight} from '../../utils';
+import {GradientProgressBar} from '../common';
+
+interface MomentUploadProgressBarProps {}
+
+const MomentUploadProgressBar: React.FC<MomentUploadProgressBarProps> =
+ ({}) => {
+ const dispatch = useDispatch();
+ const {userId: loggedInUserId} = useSelector(
+ (state: RootState) => state.user.user,
+ );
+ const {momentUploadProgressBar} = useSelector(
+ (state: RootState) => state.user,
+ );
+ const progress = useSharedValue(0);
+ const showLoading =
+ momentUploadProgressBar?.status ===
+ MomentUploadStatusType.UploadingToS3 ||
+ momentUploadProgressBar?.status ===
+ MomentUploadStatusType.WaitingForDoneProcessing;
+
+ useEffect(() => {
+ let doneProcessing = false;
+ const checkDone = async () => {
+ if (
+ momentUploadProgressBar &&
+ (await checkMomentDoneProcessing(momentUploadProgressBar!.momentId))
+ ) {
+ doneProcessing = true;
+ cancelAnimation(progress);
+ // upload is done, but let's finish the progress bar animation in a velocity of 10%/s
+ const finishProgressBarDuration = (1 - progress.value) * 10 * 1000;
+ progress.value = withTiming(1, {
+ duration: finishProgressBarDuration,
+ easing: Easing.linear,
+ });
+ // change status to Done 1s after the progress bar animation is done
+ setTimeout(() => {
+ dispatch(loadUserMoments(loggedInUserId));
+ dispatch({
+ type: setMomentUploadProgressBar.type,
+ payload: {
+ momentUploadProgressBar: {
+ ...momentUploadProgressBar,
+ status: MomentUploadStatusType.Done,
+ },
+ },
+ });
+ }, finishProgressBarDuration);
+ }
+ };
+ if (
+ momentUploadProgressBar?.status ===
+ MomentUploadStatusType.WaitingForDoneProcessing
+ ) {
+ checkDone();
+ const timer = setInterval(async () => {
+ if (!doneProcessing) {
+ checkDone();
+ }
+ }, 5 * 1000);
+ // timeout if takes longer than 1 minute to process
+ setTimeout(() => {
+ clearInterval(timer);
+ if (!doneProcessing) {
+ console.error('Check for done processing timed out');
+ dispatch({
+ type: setMomentUploadProgressBar.type,
+ payload: {
+ momentUploadProgressBar: {
+ ...momentUploadProgressBar,
+ status: MomentUploadStatusType.Error,
+ },
+ },
+ });
+ }
+ }, 60 * 1000);
+ return () => clearInterval(timer);
+ }
+ }, [momentUploadProgressBar?.status]);
+
+ useEffect(() => {
+ if (
+ momentUploadProgressBar?.status === MomentUploadStatusType.UploadingToS3
+ ) {
+ // e.g. 30s video => 30 * 3 = 60s
+ const videoDuration =
+ momentUploadProgressBar.originalVideoDuration ?? 30;
+ const durationInSeconds = videoDuration * 3;
+ progress.value = withTiming(1, {
+ duration: durationInSeconds * 1000,
+ easing: Easing.out(Easing.quad),
+ });
+ }
+ }, [momentUploadProgressBar?.status]);
+
+ useEffect(() => {
+ if (
+ momentUploadProgressBar?.status === MomentUploadStatusType.Done ||
+ momentUploadProgressBar?.status === MomentUploadStatusType.Error
+ ) {
+ progress.value = 0;
+ // clear this component after a duration
+ setTimeout(() => {
+ dispatch({
+ type: setMomentUploadProgressBar.type,
+ payload: {
+ momentUploadProgressBar: undefined,
+ },
+ });
+ }, 5000);
+ }
+ }, [momentUploadProgressBar?.status]);
+
+ if (!momentUploadProgressBar) {
+ return null;
+ }
+
+ return (
+ <View
+ style={[
+ styles.background,
+ momentUploadProgressBar?.status === MomentUploadStatusType.Error
+ ? styles.redBackground
+ : {},
+ ]}>
+ <View style={styles.container}>
+ {showLoading && (
+ <>
+ <Text style={styles.text}>Uploading Moment...</Text>
+ <GradientProgressBar style={styles.bar} progress={progress} />
+ </>
+ )}
+ {momentUploadProgressBar.status === MomentUploadStatusType.Done && (
+ <View style={styles.row}>
+ <Image
+ source={require('../../assets/images/green-check.png')}
+ style={styles.x}
+ />
+ <Text style={styles.text}>
+ Beautiful, the Moment was uploaded successfully!
+ </Text>
+ </View>
+ )}
+ {momentUploadProgressBar.status === MomentUploadStatusType.Error && (
+ <View style={styles.row}>
+ <Image
+ source={require('../../assets/images/white-x.png')}
+ style={styles.x}
+ />
+ <Text style={styles.whiteText}>
+ Unable to upload Moment. Please retry
+ </Text>
+ </View>
+ )}
+ </View>
+ </View>
+ );
+ };
+
+const styles = StyleSheet.create({
+ background: {
+ position: 'absolute',
+ zIndex: 999,
+ height: StatusBarHeight + normalize(84),
+ backgroundColor: 'white',
+ width: '100%',
+ alignItems: 'center',
+ },
+ container: {
+ justifyContent: 'center',
+ marginTop: StatusBarHeight,
+ height: normalize(84),
+ },
+ text: {
+ fontSize: normalize(14),
+ fontWeight: 'bold',
+ lineHeight: 17,
+ marginVertical: 12,
+ width: '80%',
+ },
+ bar: {
+ width: SCREEN_WIDTH * 0.9,
+ },
+ redBackground: {
+ backgroundColor: '#EA574C',
+ },
+ row: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ },
+ whiteText: {
+ color: 'white',
+ fontSize: normalize(14),
+ fontWeight: 'bold',
+ lineHeight: 17,
+ marginVertical: 12,
+ },
+ x: {
+ width: normalize(26),
+ height: normalize(26),
+ marginRight: 10,
+ },
+});
+
+export default MomentUploadProgressBar;
diff --git a/src/components/moments/TrimmerPlayer.tsx b/src/components/moments/TrimmerPlayer.tsx
index 87b3a786..8d1cd156 100644
--- a/src/components/moments/TrimmerPlayer.tsx
+++ b/src/components/moments/TrimmerPlayer.tsx
@@ -73,7 +73,12 @@ const TrimmerPlayer: React.FC<TrimmerPlayerProps> = ({
repeat={true}
onLoad={(payload) => {
setEnd(payload.duration);
- handleLoad(payload.naturalSize);
+ const {width, height} = payload.naturalSize;
+ if (payload.naturalSize.orientation === 'portrait') {
+ handleLoad(height, width, payload.duration);
+ } else {
+ handleLoad(width, height, payload.duration);
+ }
}}
onProgress={(e) => {
if (!paused) {
diff --git a/src/components/moments/index.ts b/src/components/moments/index.ts
index 16c9aed2..3f33ec53 100644
--- a/src/components/moments/index.ts
+++ b/src/components/moments/index.ts
@@ -5,3 +5,4 @@ export {default as TagFriendsFooter} from './TagFriendsFoooter';
export {default as MomentPost} from './MomentPost';
export {default as TaggedUsersDrawer} from './TaggedUsersDrawer';
export {default as TrimmerPlayer} from './TrimmerPlayer';
+export {default as MomentUploadProgressBar} from './MomentUploadProgressBar';