forked from Expensify/App
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #73 from software-mansion-labs/wave9/welcome-video…
…-cdOut [Wave9] Welcome Video as separate Screen
- Loading branch information
Showing
22 changed files
with
321 additions
and
63 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,161 @@ | ||
import type {VideoReadyForDisplayEvent} from 'expo-av'; | ||
import React, {useCallback, useEffect, useRef, useState} from 'react'; | ||
import type {LayoutChangeEvent, LayoutRectangle} from 'react-native'; | ||
import {View} from 'react-native'; | ||
import useLocalize from '@hooks/useLocalize'; | ||
import useNetwork from '@hooks/useNetwork'; | ||
import useOnboardingLayout from '@hooks/useOnboardingLayout'; | ||
import useThemeStyles from '@hooks/useThemeStyles'; | ||
import useWindowDimensions from '@hooks/useWindowDimensions'; | ||
import Navigation from '@libs/Navigation/Navigation'; | ||
import variables from '@styles/variables'; | ||
import CONST from '@src/CONST'; | ||
import Button from './Button'; | ||
import Lottie from './Lottie'; | ||
import LottieAnimations from './LottieAnimations'; | ||
import Modal from './Modal'; | ||
import Text from './Text'; | ||
import VideoPlayer from './VideoPlayer'; | ||
|
||
// Aspect ratio and height of the video. | ||
// Useful before video loads to reserve space. | ||
const VIDEO_ASPECT_RATIO = 484 / 272.25; | ||
const VIDEO_HEIGHT = 320; | ||
|
||
const MODAL_PADDING = variables.spacing2; | ||
|
||
type VideoLoadedEventType = { | ||
srcElement: { | ||
videoWidth: number; | ||
videoHeight: number; | ||
}; | ||
}; | ||
|
||
type VideoPlaybackStatusEventType = { | ||
isLoaded: boolean; | ||
}; | ||
|
||
type VideoStatus = 'video' | 'animation'; | ||
|
||
function OnboardingWelcomeVideo() { | ||
const {translate} = useLocalize(); | ||
const styles = useThemeStyles(); | ||
const containerDimensions = useRef<LayoutRectangle>({width: 0, height: 0, x: 0, y: 0}); | ||
const [isModalVisible, setIsModalVisible] = useState(true); | ||
const {isSmallScreenWidth} = useWindowDimensions(); | ||
const {shouldUseNarrowLayout} = useOnboardingLayout(); | ||
const [welcomeVideoStatus, setWelcomeVideoStatus] = useState<VideoStatus>('video'); | ||
const [isWelcomeVideoStatusLocked, setIsWelcomeVideoStatusLocked] = useState(false); | ||
const [isVideoLoaded, setIsVideoLoaded] = useState(false); | ||
const [videoAspectRatio, setVideoAspectRatio] = useState(VIDEO_ASPECT_RATIO); | ||
const {isOffline} = useNetwork(); | ||
|
||
useEffect(() => { | ||
if (isWelcomeVideoStatusLocked) { | ||
return; | ||
} | ||
|
||
if (isOffline) { | ||
setWelcomeVideoStatus('animation'); | ||
setIsWelcomeVideoStatusLocked(true); | ||
} else if (!isOffline && isVideoLoaded) { | ||
setWelcomeVideoStatus('video'); | ||
setIsWelcomeVideoStatusLocked(true); | ||
} | ||
}, [isOffline, isVideoLoaded, isWelcomeVideoStatusLocked]); | ||
|
||
const storeContainerDimensions = (event: LayoutChangeEvent) => { | ||
containerDimensions.current = event.nativeEvent.layout; | ||
}; | ||
|
||
const closeModal = useCallback(() => { | ||
setIsModalVisible(false); | ||
Navigation.goBack(); | ||
}, []); | ||
|
||
const setAspectRatio = (e: VideoReadyForDisplayEvent | VideoLoadedEventType | undefined) => { | ||
if (!e) { | ||
return; | ||
} | ||
|
||
// TODO: Figure out why on mobile there's e.naturalSize and on web it's e.srcElement | ||
if ('naturalSize' in e) { | ||
setVideoAspectRatio(e.naturalSize.width / e.naturalSize.height); | ||
} else { | ||
setVideoAspectRatio(e.srcElement.videoWidth / e.srcElement.videoHeight); | ||
} | ||
}; | ||
|
||
const setVideoStatus = (e: VideoPlaybackStatusEventType) => { | ||
setIsVideoLoaded(e.isLoaded); | ||
}; | ||
|
||
const getWelcomeVideo = () => { | ||
if (welcomeVideoStatus === 'video') { | ||
const videoWidth = containerDimensions.current.width - 2 * MODAL_PADDING; | ||
|
||
return ( | ||
<View | ||
style={[ | ||
// Prevent layout jumps by reserving height for the video | ||
{height: VIDEO_HEIGHT - 2 * MODAL_PADDING}, | ||
]} | ||
> | ||
<VideoPlayer | ||
// Temporary file supplied for testing purposes, to | ||
// be changed when correct one gets uploaded on backend | ||
url="https://d23dyxeqlo5psv.cloudfront.net/big_buck_bunny.mp4" | ||
videoPlayerStyle={[styles.onboardingVideoPlayer, {width: videoWidth, height: videoWidth / videoAspectRatio}]} | ||
onVideoLoaded={setAspectRatio} | ||
onPlaybackStatusUpdate={setVideoStatus} | ||
shouldShowProgressVolumeOnly | ||
shouldPlay | ||
isLooping | ||
/> | ||
</View> | ||
); | ||
} | ||
|
||
return ( | ||
<Lottie | ||
source={LottieAnimations.Hands} | ||
style={styles.w100} | ||
webStyle={isSmallScreenWidth ? styles.h100 : styles.w100} | ||
autoPlay | ||
loop | ||
/> | ||
); | ||
}; | ||
|
||
return ( | ||
<Modal | ||
isVisible={isModalVisible} | ||
type={shouldUseNarrowLayout ? CONST.MODAL.MODAL_TYPE.CENTERED_SMALL : CONST.MODAL.MODAL_TYPE.BOTTOM_DOCKED} | ||
onClose={closeModal} | ||
innerContainerStyle={shouldUseNarrowLayout ? {} : {paddingTop: MODAL_PADDING, paddingBottom: MODAL_PADDING}} | ||
> | ||
<View | ||
style={[shouldUseNarrowLayout ? {width: 500, height: 500} : {}, {maxHeight: '100%'}]} | ||
onLayout={storeContainerDimensions} | ||
> | ||
<View style={shouldUseNarrowLayout ? {padding: MODAL_PADDING} : {paddingHorizontal: MODAL_PADDING}}>{getWelcomeVideo()}</View> | ||
<View style={[shouldUseNarrowLayout ? [styles.mt5, styles.mh8] : [styles.mt3, styles.mh5]]}> | ||
<View style={[shouldUseNarrowLayout ? [styles.gap1, styles.mb8] : [styles.gap2, styles.mb10]]}> | ||
<Text style={styles.textHeroSmall}>{translate('onboarding.welcomeVideo.title')}</Text> | ||
<Text style={styles.textSupporting}>{translate('onboarding.welcomeVideo.description')}</Text> | ||
</View> | ||
<Button | ||
success | ||
pressOnEnter | ||
onPress={closeModal} | ||
text={translate('onboarding.welcomeVideo.button')} | ||
/> | ||
</View> | ||
</View> | ||
</Modal> | ||
); | ||
} | ||
|
||
OnboardingWelcomeVideo.displayName = 'OnboardingWelcomeVideo'; | ||
|
||
export default OnboardingWelcomeVideo; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.