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 = ({}) => { 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 ( {showLoading && ( <> Uploading Moment... )} {momentUploadProgressBar.status === MomentUploadStatusType.Done && ( Beautiful, the Moment was uploaded successfully! )} {momentUploadProgressBar.status === MomentUploadStatusType.Error && ( Unable to upload Moment. Please retry )} ); }; 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;