feat: update onboarding and application flows
This commit is contained in:
+66
-67
@@ -1,19 +1,8 @@
|
||||
import AsyncStorage from '@react-native-async-storage/async-storage'
|
||||
import { useCallback, useEffect, useRef, useState } from 'react'
|
||||
import {
|
||||
ActivityIndicator,
|
||||
Image,
|
||||
Platform,
|
||||
StyleSheet,
|
||||
Text,
|
||||
TouchableOpacity,
|
||||
View,
|
||||
} from 'react-native'
|
||||
import { background, icons } from '../assets'
|
||||
import EntryJingle from '../components/EntryJingle'
|
||||
import { useCallback, useMemo, useState } from 'react'
|
||||
import { Image, StyleSheet, Text, TouchableOpacity, View } from 'react-native'
|
||||
import { background, icons, videos } from '../assets'
|
||||
import FullscreenIntroVideo from '../components/FullscreenIntroVideo'
|
||||
import { videosRef } from '../config/firebase'
|
||||
import useDataFromRef from '../hooks/useDataFromRef'
|
||||
import Page from '../layouts/Page'
|
||||
import { Routes } from '../navigation'
|
||||
import { navigate, reset } from '../navigation/NavigationService'
|
||||
@@ -22,45 +11,25 @@ import { Palette } from '../styles'
|
||||
import { FONT_FAMILY } from '../styles/Fonts'
|
||||
|
||||
const LANGUAGE_STORAGE_KEY = 'preferredLanguage'
|
||||
const FLOW_PHASE = {
|
||||
JINGLE: 'jingle',
|
||||
LANGUAGE: 'language',
|
||||
WELCOME_VIDEO: 'welcomeVideo',
|
||||
}
|
||||
|
||||
export default function LandingPage() {
|
||||
export default function LandingPage({ route }) {
|
||||
const { currentUID } = useUser()
|
||||
const [videoUrl, setVideoUrl] = useState(null)
|
||||
const [phase, setPhase] = useState(() =>
|
||||
route?.params?.startAtLanguage ? FLOW_PHASE.LANGUAGE : FLOW_PHASE.JINGLE
|
||||
)
|
||||
const [selectedLanguage, setSelectedLanguage] = useState(null)
|
||||
const continuationHandledRef = useRef(false)
|
||||
const isAuthenticated = !!currentUID
|
||||
|
||||
const { data: welcomeVideo, loading: welcomeVideoLoading } = useDataFromRef({
|
||||
ref: selectedLanguage ? videosRef.doc(selectedLanguage) : null,
|
||||
initialState: null,
|
||||
simpleRef: true,
|
||||
condition: !!selectedLanguage,
|
||||
refreshArray: [selectedLanguage],
|
||||
})
|
||||
|
||||
const openRegistration = useCallback(() => {
|
||||
navigate(Routes.Register)
|
||||
}, [])
|
||||
|
||||
const handleSelectLanguage = useCallback(async (language) => {
|
||||
try {
|
||||
await AsyncStorage.setItem(LANGUAGE_STORAGE_KEY, language)
|
||||
} catch (error) {
|
||||
console.warn('LandingPage: failed to persist language', error)
|
||||
}
|
||||
continuationHandledRef.current = false
|
||||
setSelectedLanguage(language)
|
||||
}, [])
|
||||
|
||||
const handleVideoClose = useCallback(() => {
|
||||
setVideoUrl(null)
|
||||
openRegistration()
|
||||
}, [openRegistration])
|
||||
|
||||
useEffect(() => {
|
||||
if (!isAuthenticated) {
|
||||
return
|
||||
}
|
||||
const openMainMenu = useCallback(() => {
|
||||
reset({
|
||||
index: 0,
|
||||
routes: [
|
||||
@@ -73,33 +42,55 @@ export default function LandingPage() {
|
||||
},
|
||||
],
|
||||
})
|
||||
}, [isAuthenticated])
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
if (
|
||||
!selectedLanguage ||
|
||||
welcomeVideoLoading ||
|
||||
continuationHandledRef.current ||
|
||||
isAuthenticated
|
||||
) {
|
||||
const handleJingleClose = useCallback(() => {
|
||||
if (isAuthenticated) {
|
||||
openMainMenu()
|
||||
return
|
||||
}
|
||||
setPhase(FLOW_PHASE.LANGUAGE)
|
||||
}, [isAuthenticated, openMainMenu])
|
||||
|
||||
continuationHandledRef.current = true
|
||||
const nextVideoUrl =
|
||||
Platform.OS === 'web' ? welcomeVideo?.registrationIntroWeb : welcomeVideo?.registrationIntro
|
||||
|
||||
if (typeof nextVideoUrl === 'string' && nextVideoUrl.trim().length > 0) {
|
||||
setVideoUrl(nextVideoUrl)
|
||||
return
|
||||
const handleSelectLanguage = useCallback(async (language) => {
|
||||
try {
|
||||
await AsyncStorage.setItem(LANGUAGE_STORAGE_KEY, language)
|
||||
} catch (error) {
|
||||
console.warn('LandingPage: failed to persist language', error)
|
||||
}
|
||||
setSelectedLanguage(language)
|
||||
setPhase(FLOW_PHASE.WELCOME_VIDEO)
|
||||
}, [])
|
||||
|
||||
openRegistration()
|
||||
}, [isAuthenticated, openRegistration, selectedLanguage, welcomeVideo, welcomeVideoLoading])
|
||||
const handleWelcomeVideoClose = useCallback(() => {
|
||||
setSelectedLanguage(null)
|
||||
setPhase(FLOW_PHASE.LANGUAGE)
|
||||
requestAnimationFrame(openRegistration)
|
||||
}, [openRegistration])
|
||||
|
||||
const activeVideo = useMemo(() => {
|
||||
if (phase === FLOW_PHASE.JINGLE) return videos.entryJingle
|
||||
if (phase !== FLOW_PHASE.WELCOME_VIDEO) return null
|
||||
return selectedLanguage === 'en' ? videos.welcomeEn : videos.welcomeFr
|
||||
}, [phase, selectedLanguage])
|
||||
|
||||
const activeVideoClose =
|
||||
phase === FLOW_PHASE.JINGLE ? handleJingleClose : handleWelcomeVideoClose
|
||||
const skipLabel =
|
||||
phase === FLOW_PHASE.JINGLE
|
||||
? 'Passer / Skip'
|
||||
: selectedLanguage === 'en'
|
||||
? 'Skip video'
|
||||
: 'Passer la vidéo'
|
||||
const playLabel =
|
||||
phase === FLOW_PHASE.JINGLE
|
||||
? 'Lancer le jingle / Play jingle'
|
||||
: selectedLanguage === 'en'
|
||||
? 'Play video with sound'
|
||||
: 'Lire la vidéo avec le son'
|
||||
|
||||
return (
|
||||
<>
|
||||
<EntryJingle active={!isAuthenticated && !selectedLanguage} />
|
||||
<Page title="Landing Page" backgroundImg={background.homeBGWeb}>
|
||||
<View
|
||||
style={{
|
||||
@@ -109,7 +100,7 @@ export default function LandingPage() {
|
||||
}}
|
||||
>
|
||||
<View style={styles.content}>
|
||||
{!selectedLanguage && (
|
||||
{phase === FLOW_PHASE.LANGUAGE ? (
|
||||
<View style={styles.languageRow}>
|
||||
<TouchableOpacity
|
||||
style={[styles.languageButton]}
|
||||
@@ -126,14 +117,22 @@ export default function LandingPage() {
|
||||
<Text style={styles.languageText}>English</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
)}
|
||||
{selectedLanguage && welcomeVideoLoading ? (
|
||||
<ActivityIndicator color={Palette.white} size="large" />
|
||||
) : null}
|
||||
</View>
|
||||
</View>
|
||||
</Page>
|
||||
<FullscreenIntroVideo url={videoUrl} visible={!!videoUrl} onClose={handleVideoClose} />
|
||||
{activeVideo ? (
|
||||
<FullscreenIntroVideo
|
||||
key={phase}
|
||||
url={activeVideo}
|
||||
visible
|
||||
onClose={activeVideoClose}
|
||||
contentFit="contain"
|
||||
requireAudio
|
||||
skipLabel={skipLabel}
|
||||
playLabel={playLabel}
|
||||
/>
|
||||
) : null}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user