From 6bfade4a171972c27cfb2cf36d2e8f4ab13d0189 Mon Sep 17 00:00:00 2001 From: cyberalby2 Date: Fri, 6 Mar 2026 22:03:06 +0100 Subject: [PATCH] Onboarding Screen Localization Patch --- src/i18n/locales/en.json | 27 +- src/i18n/locales/it.json | 27 +- src/screens/OnboardingScreen.tsx | 905 ++++++++++++++++--------------- 3 files changed, 502 insertions(+), 457 deletions(-) diff --git a/src/i18n/locales/en.json b/src/i18n/locales/en.json index d4b0109d..1bae5e1f 100644 --- a/src/i18n/locales/en.json +++ b/src/i18n/locales/en.json @@ -1509,11 +1509,28 @@ "tried_url": "Tried: {{url}}", "provider_logs": "Provider Logs", "no_logs_captured": "No logs captured." - }, - "first_time_welcome": { - "welcome_msg": "Welcome to Nuvio!", - "get_started": "To get started, install some addons to access content from various sources.", - "install_addons": "Install Addons" } + }, + "first_time_welcome": { + "welcome_msg": "Welcome to Nuvio!", + "get_started": "To get started, install some addons to access content from various sources.", + "install_addons": "Install Addons" + }, + "onboarding_screen": { + "welcome_title": "Welcome to\nNuvio", + "welcome_subtitle": "Your Ultimate Content Hub", + "welcome_desc": "Discover, organize, and manage your favorite movies and TV shows from multiple sources in one beautiful app.", + "addons_title": "Powerful\nAddons", + "addons_subtitle": "Extend Your Experience", + "addons_desc": "Install addons to access content from various platforms and services. Choose what works best for you.", + "discovery_title": "Smart\nDiscovery", + "discovery_subtitle": "Find What You Love", + "discovery_desc": "Browse trending content, search across all your sources, and get personalized recommendations.", + "library_title": "Your\nLibrary", + "library_subtitle": "Track & Organize", + "library_desc": "Save favorites, track your progress, and sync with Trakt to keep everything organized across devices.", + "swipe_to_continue": "Swipe to continue", + "skip": "Skip", + "get_started":"Get Started" } } diff --git a/src/i18n/locales/it.json b/src/i18n/locales/it.json index 3d0db7b2..2bc7254e 100644 --- a/src/i18n/locales/it.json +++ b/src/i18n/locales/it.json @@ -1509,11 +1509,28 @@ "tried_url": "Provato: {{url}}", "provider_logs": "Log Provider", "no_logs_captured": "Nessun log catturato." - }, - "first_time_welcome": { - "welcome_msg": "Benvenuto su Nuvio!", - "get_started": "Per iniziare, installa addons per accedere ai contenuti da varie fonti", - "install_addons": "Installa Addon" } + }, + "first_time_welcome": { + "welcome_msg": "Benvenuto su Nuvio!", + "get_started": "Per iniziare, installa addons per accedere ai contenuti da varie fonti", + "install_addons": "Installa Addon" + }, + "onboarding_screen": { + "welcome_title": "Benvenuto su\nNuvio", + "welcome_subtitle": "Il tuo Hub Contenuti definitivo", + "welcome_desc": "Scopri, organizza e gestisci i tuoi film e serie tv preferiti da diverse sorgenti in un'unica meravigliosa app.", + "addons_title": "Potenti\nAddons", + "addons_subtitle": "Estendi la tua esperienza", + "addons_desc": "Installa addon per accedere ai contenuti da diverse piattaforme e servizi. Scegli in base a ciò che è meglio per te.", + "discovery_title": "Smart\nDiscovery", + "discovery_subtitle": "Trova ciò che ami.", + "discovery_desc": "Naviga fra i contenuti in tendenza, cerca su tutte le tue fonti e ottieni suggerimenti personalizzati.", + "library_title": "La tua\nLibreria", + "library_subtitle": "Traccia & Organizza", + "library_desc": "Salva preferiti , traccia i tuoi progressi e sincronizza tutto con Trakt per mantenere l'organizzazione fra tutti i tuoi dispositivi.", + "swipe_to_continue": "Scorri per proseguire", + "skip": "Salta", + "get_started": "Inizia" } } diff --git a/src/screens/OnboardingScreen.tsx b/src/screens/OnboardingScreen.tsx index 10016c02..5992ca76 100644 --- a/src/screens/OnboardingScreen.tsx +++ b/src/screens/OnboardingScreen.tsx @@ -1,508 +1,519 @@ import React, { useState, useRef } from 'react'; import { - View, - Text, - StyleSheet, - Dimensions, - TouchableOpacity, - StatusBar, - Platform, + View, + Text, + StyleSheet, + Dimensions, + TouchableOpacity, + StatusBar, + Platform, } from 'react-native'; import Animated, { - useSharedValue, - useAnimatedStyle, - withSpring, - withTiming, - FadeIn, - FadeInUp, - useAnimatedScrollHandler, - interpolate, - Extrapolation, - runOnJS, - SharedValue, + useSharedValue, + useAnimatedStyle, + withSpring, + withTiming, + FadeIn, + FadeInUp, + useAnimatedScrollHandler, + interpolate, + Extrapolation, + runOnJS, + SharedValue, } from 'react-native-reanimated'; import { useTheme } from '../contexts/ThemeContext'; import { NavigationProp, useNavigation } from '@react-navigation/native'; import { RootStackParamList } from '../navigation/AppNavigator'; import { mmkvStorage } from '../services/mmkvStorage'; import { ShapeAnimation } from '../components/onboarding/ShapeAnimation'; +import { useTranslation } from 'react-i18next'; const { width, height } = Dimensions.get('window'); const SPRING_CONFIG = { - damping: 20, - stiffness: 90, - mass: 0.8, + damping: 20, + stiffness: 90, + mass: 0.8, }; interface OnboardingSlide { - id: string; - title: string; - subtitle: string; - description: string; + id: string; + title: string; + subtitle: string; + description: string; } -const onboardingData: OnboardingSlide[] = [ - { - id: '1', - title: 'Welcome to\nNuvio', - subtitle: 'Your Ultimate Content Hub', - description: 'Discover, organize, and manage your favorite movies and TV shows from multiple sources in one beautiful app.', - }, - { - id: '2', - title: 'Powerful\nAddons', - subtitle: 'Extend Your Experience', - description: 'Install addons to access content from various platforms and services. Choose what works best for you.', - }, - { - id: '3', - title: 'Smart\nDiscovery', - subtitle: 'Find What You Love', - description: 'Browse trending content, search across all your sources, and get personalized recommendations.', - }, - { - id: '4', - title: 'Your\nLibrary', - subtitle: 'Track & Organize', - description: 'Save favorites, track your progress, and sync with Trakt to keep everything organized across devices.', - }, -]; - // Animated Slide Component with parallax const AnimatedSlide = ({ - item, - index, - scrollX + item, + index, + scrollX, }: { - item: OnboardingSlide; - index: number; - scrollX: SharedValue; + item: OnboardingSlide; + index: number; + scrollX: SharedValue; }) => { - const inputRange = [(index - 1) * width, index * width, (index + 1) * width]; + const inputRange = [(index - 1) * width, index * width, (index + 1) * width]; - const titleStyle = useAnimatedStyle(() => { - const translateX = interpolate( - scrollX.value, - inputRange, - [width * 0.3, 0, -width * 0.3], - Extrapolation.CLAMP - ); - const opacity = interpolate( - scrollX.value, - inputRange, - [0, 1, 0], - Extrapolation.CLAMP - ); - const scale = interpolate( - scrollX.value, - inputRange, - [0.8, 1, 0.8], - Extrapolation.CLAMP - ); - return { - transform: [{ translateX }, { scale }], - opacity, - }; - }); + const titleStyle = useAnimatedStyle(() => { + const translateX = interpolate( + scrollX.value, + inputRange, + [width * 0.3, 0, -width * 0.3], + Extrapolation.CLAMP, + ); + const opacity = interpolate( + scrollX.value, + inputRange, + [0, 1, 0], + Extrapolation.CLAMP, + ); + const scale = interpolate( + scrollX.value, + inputRange, + [0.8, 1, 0.8], + Extrapolation.CLAMP, + ); + return { + transform: [{ translateX }, { scale }], + opacity, + }; + }); - const subtitleStyle = useAnimatedStyle(() => { - const translateX = interpolate( - scrollX.value, - inputRange, - [width * 0.5, 0, -width * 0.5], - Extrapolation.CLAMP - ); - const opacity = interpolate( - scrollX.value, - inputRange, - [0, 1, 0], - Extrapolation.CLAMP - ); - return { - transform: [{ translateX }], - opacity, - }; - }); + const subtitleStyle = useAnimatedStyle(() => { + const translateX = interpolate( + scrollX.value, + inputRange, + [width * 0.5, 0, -width * 0.5], + Extrapolation.CLAMP, + ); + const opacity = interpolate( + scrollX.value, + inputRange, + [0, 1, 0], + Extrapolation.CLAMP, + ); + return { + transform: [{ translateX }], + opacity, + }; + }); - const descriptionStyle = useAnimatedStyle(() => { - const translateX = interpolate( - scrollX.value, - inputRange, - [width * 0.7, 0, -width * 0.7], - Extrapolation.CLAMP - ); - const opacity = interpolate( - scrollX.value, - inputRange, - [0, 1, 0], - Extrapolation.CLAMP - ); - return { - transform: [{ translateX }], - opacity, - }; - }); + const descriptionStyle = useAnimatedStyle(() => { + const translateX = interpolate( + scrollX.value, + inputRange, + [width * 0.7, 0, -width * 0.7], + Extrapolation.CLAMP, + ); + const opacity = interpolate( + scrollX.value, + inputRange, + [0, 1, 0], + Extrapolation.CLAMP, + ); + return { + transform: [{ translateX }], + opacity, + }; + }); - return ( - - - - {item.title} - + return ( + + + + {item.title} + - - {item.subtitle} - + + {item.subtitle} + - - {item.description} - - - - ); + + {item.description} + + + + ); }; const OnboardingScreen = () => { - const { currentTheme } = useTheme(); - const navigation = useNavigation>(); - const [currentIndex, setCurrentIndex] = useState(0); - const flatListRef = useRef>(null); - const scrollX = useSharedValue(0); + const { currentTheme } = useTheme(); + const navigation = useNavigation>(); + const [currentIndex, setCurrentIndex] = useState(0); + const flatListRef = useRef>(null); + const scrollX = useSharedValue(0); + const { t } = useTranslation(); + const onboardingData: OnboardingSlide[] = [ + { + id: '1', + title: t('onboarding_screen.welcome_title'), + subtitle: t('onboarding_screen.welcome_subtitle'), + description: t('onboarding_screen.welcome_desc'), + }, + { + id: '2', //addons + title: t('onboarding_screen.addons_title'), + subtitle: t('onboarding_screen.addons_subtitle'), + description: t('onboarding_screen.addons_desc'), + }, + { + id: '3', // discovery + title: t('onboarding_screen.discovery_title'), + subtitle: t('onboarding_screen.discovery_subtitle'), + description: t('onboarding_screen.discovery_desc'), + }, + { + id: '4', // library + title: t('onboarding_screen.library_title'), + subtitle: t('onboarding_screen.library_subtitle'), + description: t('onboarding_screen.library_desc'), + }, + ]; - const updateIndex = (index: number) => { - setCurrentIndex(index); - }; + const updateIndex = (index: number) => { + setCurrentIndex(index); + }; - const onScroll = useAnimatedScrollHandler({ - onScroll: (event) => { - scrollX.value = event.contentOffset.x; - }, - onMomentumEnd: (event) => { - const slideIndex = Math.round(event.contentOffset.x / width); - runOnJS(updateIndex)(slideIndex); - }, - }); + const onScroll = useAnimatedScrollHandler({ + onScroll: (event) => { + scrollX.value = event.contentOffset.x; + }, + onMomentumEnd: (event) => { + const slideIndex = Math.round(event.contentOffset.x / width); + runOnJS(updateIndex)(slideIndex); + }, + }); - const progressStyle = useAnimatedStyle(() => { - const progress = interpolate( - scrollX.value, - [0, (onboardingData.length - 1) * width], - [0, 100], - Extrapolation.CLAMP - ); - return { - width: `${progress}%`, - }; - }); + const progressStyle = useAnimatedStyle(() => { + const progress = interpolate( + scrollX.value, + [0, (onboardingData.length - 1) * width], + [0, 100], + Extrapolation.CLAMP, + ); + return { + width: `${progress}%`, + }; + }); - const handleNext = () => { - if (currentIndex < onboardingData.length - 1) { - const nextIndex = currentIndex + 1; - flatListRef.current?.scrollToOffset({ - offset: nextIndex * width, - animated: true - }); - } else { - handleGetStarted(); - } - }; + const handleNext = () => { + if (currentIndex < onboardingData.length - 1) { + const nextIndex = currentIndex + 1; + flatListRef.current?.scrollToOffset({ + offset: nextIndex * width, + animated: true, + }); + } else { + handleGetStarted(); + } + }; - const handleSkip = () => { - (async () => { - try { - await mmkvStorage.setItem('hasCompletedOnboarding', 'true'); - await mmkvStorage.setItem('showLoginHintToastOnce', 'true'); - } catch { } - navigation.reset({ index: 0, routes: [{ name: 'MainTabs' }] }); - })(); - }; + const handleSkip = () => { + (async () => { + try { + await mmkvStorage.setItem('hasCompletedOnboarding', 'true'); + await mmkvStorage.setItem('showLoginHintToastOnce', 'true'); + } catch {} + navigation.reset({ index: 0, routes: [{ name: 'MainTabs' }] }); + })(); + }; - const handleGetStarted = async () => { - try { - await mmkvStorage.setItem('hasCompletedOnboarding', 'true'); - navigation.reset({ index: 0, routes: [{ name: 'MainTabs' }] }); - } catch (error) { - if (__DEV__) console.error('Error saving onboarding status:', error); - navigation.reset({ index: 0, routes: [{ name: 'MainTabs' }] }); - } - }; + const handleGetStarted = async () => { + try { + await mmkvStorage.setItem('hasCompletedOnboarding', 'true'); + navigation.reset({ index: 0, routes: [{ name: 'MainTabs' }] }); + } catch (error) { + if (__DEV__) console.error('Error saving onboarding status:', error); + navigation.reset({ index: 0, routes: [{ name: 'MainTabs' }] }); + } + }; - const renderSlide = ({ item, index }: { item: OnboardingSlide; index: number }) => ( - - ); + const renderSlide = ({ + item, + index, + }: { + item: OnboardingSlide; + index: number; + }) => ; - // Animated pagination dots - const PaginationDot = ({ index }: { index: number }) => { - const dotStyle = useAnimatedStyle(() => { - const inputRange = [(index - 1) * width, index * width, (index + 1) * width]; - const dotWidth = interpolate( - scrollX.value, - inputRange, - [8, 32, 8], - Extrapolation.CLAMP - ); - const opacity = interpolate( - scrollX.value, - inputRange, - [0.3, 1, 0.3], - Extrapolation.CLAMP - ); - return { - width: dotWidth, - opacity, - }; - }); + // Animated pagination dots + const PaginationDot = ({ index }: { index: number }) => { + const dotStyle = useAnimatedStyle(() => { + const inputRange = [(index - 1) * width, index * width, (index + 1) * width]; + const dotWidth = interpolate( + scrollX.value, + inputRange, + [8, 32, 8], + Extrapolation.CLAMP, + ); + const opacity = interpolate( + scrollX.value, + inputRange, + [0.3, 1, 0.3], + Extrapolation.CLAMP, + ); + return { + width: dotWidth, + opacity, + }; + }); - return ; - }; + return ; + }; - // Animated button - const buttonScale = useSharedValue(1); + // Animated button + const buttonScale = useSharedValue(1); - const buttonStyle = useAnimatedStyle(() => ({ - transform: [{ scale: buttonScale.value }], - })); + const buttonStyle = useAnimatedStyle(() => ({ + transform: [{ scale: buttonScale.value }], + })); - // Animated opacity for button and swipe indicator based on scroll - const lastSlideStart = (onboardingData.length - 1) * width; + // Animated opacity for button and swipe indicator based on scroll + const lastSlideStart = (onboardingData.length - 1) * width; - const buttonOpacityStyle = useAnimatedStyle(() => { - const opacity = interpolate( - scrollX.value, - [lastSlideStart - width * 0.3, lastSlideStart], - [0, 1], - Extrapolation.CLAMP - ); - return { opacity }; - }); + const buttonOpacityStyle = useAnimatedStyle(() => { + const opacity = interpolate( + scrollX.value, + [lastSlideStart - width * 0.3, lastSlideStart], + [0, 1], + Extrapolation.CLAMP, + ); + return { opacity }; + }); - const swipeOpacityStyle = useAnimatedStyle(() => { - const opacity = interpolate( - scrollX.value, - [lastSlideStart - width * 0.3, lastSlideStart], - [1, 0], - Extrapolation.CLAMP - ); - return { opacity }; - }); + const swipeOpacityStyle = useAnimatedStyle(() => { + const opacity = interpolate( + scrollX.value, + [lastSlideStart - width * 0.3, lastSlideStart], + [1, 0], + Extrapolation.CLAMP, + ); + return { opacity }; + }); - const handlePressIn = () => { - buttonScale.value = withSpring(0.95, { damping: 15, stiffness: 400 }); - }; + const handlePressIn = () => { + buttonScale.value = withSpring(0.95, { damping: 15, stiffness: 400 }); + }; - const handlePressOut = () => { - buttonScale.value = withSpring(1, { damping: 15, stiffness: 400 }); - }; + const handlePressOut = () => { + buttonScale.value = withSpring(1, { damping: 15, stiffness: 400 }); + }; - return ( - - + return ( + + - - {/* Shape Animation Background - iOS only */} - {Platform.OS === 'ios' && } + + {/* Shape Animation Background - iOS only */} + {Platform.OS === 'ios' && } - {/* Header */} - - - Skip - + {/* Header */} + + + {t('onboarding_screen.skip')} + - {/* Smooth Progress Bar */} - - - - + {/* Smooth Progress Bar */} + + + + - {/* Slides */} - item.id} - onScroll={onScroll} - scrollEventThrottle={16} - decelerationRate="fast" - snapToInterval={width} - snapToAlignment="start" - bounces={false} - style={{ flex: 1 }} - /> + {/* Slides */} + item.id} + onScroll={onScroll} + scrollEventThrottle={16} + decelerationRate="fast" + snapToInterval={width} + snapToAlignment="start" + bounces={false} + style={{ flex: 1 }} + /> - {/* Footer */} - - {/* Smooth Pagination */} - - {onboardingData.map((_, index) => ( - - ))} - + {/* Footer */} + + {/* Smooth Pagination */} + + {onboardingData.map((_, index) => ( + + ))} + - {/* Button and Swipe indicator with crossfade based on scroll */} - - {/* Swipe Indicator - fades out on last slide */} - - Swipe to continue - - + {/* Button and Swipe indicator with crossfade based on scroll */} + + {/* Swipe Indicator - fades out on last slide */} + + + {t('onboarding_screen.swipe_to_continue')} + + + - {/* Get Started Button - fades in on last slide */} - - - - Get Started - - - - - - - - ); + {/* Get Started Button - fades in on last slide */} + + + + + {t('onboarding_screen.get_started')} + + + + + + + + + ); }; const styles = StyleSheet.create({ - container: { - flex: 1, - backgroundColor: '#0A0A0A', - }, - fullScreenContainer: { - flex: 1, - paddingTop: Platform.OS === 'ios' ? 60 : (StatusBar.currentHeight || 24) + 16, - }, - header: { - flexDirection: 'row', - justifyContent: 'space-between', - alignItems: 'center', - paddingHorizontal: 24, - paddingBottom: 20, - }, - skipButton: { - paddingVertical: 8, - paddingHorizontal: 4, - }, - skipText: { - fontSize: 15, - fontWeight: '500', - color: 'rgba(255, 255, 255, 0.4)', - }, - progressContainer: { - flex: 1, - height: 3, - borderRadius: 1.5, - marginLeft: 24, - backgroundColor: 'rgba(255, 255, 255, 0.08)', - overflow: 'hidden', - }, - progressBar: { - height: '100%', - borderRadius: 1.5, - backgroundColor: '#FFFFFF', - }, - slide: { - width, - flex: 1, - justifyContent: Platform.OS === 'ios' ? 'flex-start' : 'center', // Top on iOS, center on Android - paddingHorizontal: 32, - paddingTop: Platform.OS === 'ios' ? '20%' : 0, // Padding only on iOS - }, - textContainer: { - alignItems: 'flex-start', // Text always left-aligned - }, - title: { - fontSize: 52, - fontWeight: '800', - letterSpacing: -2, - lineHeight: 56, - marginBottom: 16, - color: '#FFFFFF', - }, - subtitle: { - fontSize: 17, - fontWeight: '600', - color: 'rgba(255, 255, 255, 0.6)', - marginBottom: 20, - letterSpacing: 0.3, - }, - description: { - fontSize: 15, - lineHeight: 24, - color: 'rgba(255, 255, 255, 0.4)', - maxWidth: 300, - textAlign: 'left', // Always left-aligned text - }, - footer: { - paddingHorizontal: 24, - paddingBottom: Platform.OS === 'ios' ? 50 : 32, - }, - pagination: { - flexDirection: 'row', - justifyContent: 'center', - alignItems: 'center', - marginBottom: 32, - gap: 6, - }, - paginationDot: { - height: 8, - borderRadius: 4, - backgroundColor: '#FFFFFF', - }, - button: { - backgroundColor: '#FFFFFF', - borderRadius: 16, - paddingVertical: 18, - alignItems: 'center', - justifyContent: 'center', - }, - buttonText: { - fontSize: 16, - fontWeight: '700', - color: '#0A0A0A', - letterSpacing: 0.3, - }, - swipeIndicator: { - flexDirection: 'row', - alignItems: 'center', - justifyContent: 'center', - paddingVertical: 18, - gap: 8, - }, - swipeText: { - fontSize: 14, - fontWeight: '500', - color: 'rgba(255, 255, 255, 0.4)', - letterSpacing: 0.3, - }, - swipeArrow: { - fontSize: 18, - color: 'rgba(255, 255, 255, 0.4)', - }, - footerButtonContainer: { - height: 56, - position: 'relative', - }, - absoluteFill: { - position: 'absolute', - top: 0, - left: 0, - right: 0, - bottom: 0, - }, + container: { + flex: 1, + backgroundColor: '#0A0A0A', + }, + fullScreenContainer: { + flex: 1, + paddingTop: Platform.OS === 'ios' ? 60 : (StatusBar.currentHeight || 24) + 16, + }, + header: { + flexDirection: 'row', + justifyContent: 'space-between', + alignItems: 'center', + paddingHorizontal: 24, + paddingBottom: 20, + }, + skipButton: { + paddingVertical: 8, + paddingHorizontal: 4, + }, + skipText: { + fontSize: 15, + fontWeight: '500', + color: 'rgba(255, 255, 255, 0.4)', + }, + progressContainer: { + flex: 1, + height: 3, + borderRadius: 1.5, + marginLeft: 24, + backgroundColor: 'rgba(255, 255, 255, 0.08)', + overflow: 'hidden', + }, + progressBar: { + height: '100%', + borderRadius: 1.5, + backgroundColor: '#FFFFFF', + }, + slide: { + width, + flex: 1, + justifyContent: Platform.OS === 'ios' ? 'flex-start' : 'center', // Top on iOS, center on Android + paddingHorizontal: 32, + paddingTop: Platform.OS === 'ios' ? '20%' : 0, // Padding only on iOS + }, + textContainer: { + alignItems: 'flex-start', // Text always left-aligned + }, + title: { + fontSize: 52, + fontWeight: '800', + letterSpacing: -2, + lineHeight: 56, + marginBottom: 16, + color: '#FFFFFF', + }, + subtitle: { + fontSize: 17, + fontWeight: '600', + color: 'rgba(255, 255, 255, 0.6)', + marginBottom: 20, + letterSpacing: 0.3, + }, + description: { + fontSize: 15, + lineHeight: 24, + color: 'rgba(255, 255, 255, 0.4)', + maxWidth: 300, + textAlign: 'left', // Always left-aligned text + }, + footer: { + paddingHorizontal: 24, + paddingBottom: Platform.OS === 'ios' ? 50 : 32, + }, + pagination: { + flexDirection: 'row', + justifyContent: 'center', + alignItems: 'center', + marginBottom: 32, + gap: 6, + }, + paginationDot: { + height: 8, + borderRadius: 4, + backgroundColor: '#FFFFFF', + }, + button: { + backgroundColor: '#FFFFFF', + borderRadius: 16, + paddingVertical: 18, + alignItems: 'center', + justifyContent: 'center', + }, + buttonText: { + fontSize: 16, + fontWeight: '700', + color: '#0A0A0A', + letterSpacing: 0.3, + }, + swipeIndicator: { + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'center', + paddingVertical: 18, + gap: 8, + }, + swipeText: { + fontSize: 14, + fontWeight: '500', + color: 'rgba(255, 255, 255, 0.4)', + letterSpacing: 0.3, + }, + swipeArrow: { + fontSize: 18, + color: 'rgba(255, 255, 255, 0.4)', + }, + footerButtonContainer: { + height: 56, + position: 'relative', + }, + absoluteFill: { + position: 'absolute', + top: 0, + left: 0, + right: 0, + bottom: 0, + }, }); -export default OnboardingScreen; \ No newline at end of file +export default OnboardingScreen;