Facebook
From Gray Wolf, 3 Years ago, written in Plain Text.
Embed
Download Paste or View Raw
Hits: 75
  1. import { useDimensions } from "@react-native-community/hooks";
  2. import React, { useCallback, useRef, useState } from "react";
  3. import { Animated, ScrollView } from "react-native";
  4. import { Button, Dot } from "../../components";
  5. import { slides } from "../../data";
  6. import { Box } from "../../utils";
  7. import { Slider, SliderImage, SliderText, SliderTitle } from "./Slider";
  8. import { SubSlider, SubSliderItem } from "./SubSlider";
  9.  
  10. type OnboardingProps = {
  11.   onDone: () => void;
  12. };
  13.  
  14. const Onboarding = React.memo(({ onDone }: OnboardingProps) => {
  15.   const { width } = useDimensions().window;
  16.   const [completed, setCompleted] = useState<boolean>(false);
  17.   const scroll = useRef<ScrollView>(null);
  18.  
  19.   const x = React.useRef<Animated.Value>(new Animated.Value(0)).current;
  20.  
  21.   const onPress = useCallback((index: number) => {
  22.     scroll.current.scrollTo({ x: width * (index + 1), animated: true });
  23.   }, []);
  24.  
  25.   React.useEffect(() => {
  26.     x.addListener(({ value }) => {
  27.       if (Math.ceil(value / width) === slides.length - 1) {
  28.         setCompleted(true);
  29.       } else {
  30.         setCompleted(false);
  31.       }
  32.     });
  33.  
  34.     return () => x.removeAllListeners();
  35.   }, []);
  36.  
  37.   return (
  38.     <Box flex={1} backgroundColor="mainBackground">
  39.       <Box flex={3}>{renderScroll(scroll, width, x)}</Box>
  40.  
  41.       {renderSubSlider(x, width, completed, onDone, onPress)}
  42.     </Box>
  43.   );
  44. });
  45.  
  46. export default Onboarding;
  47.  
  48. const renderScroll = (
  49.   scroll: React.MutableRefObject<ScrollView>,
  50.   width: number,
  51.   x: Animated.Value
  52. ) => {
  53.   return (
  54.     <Animated.ScrollView
  55.       showsHorizontalScrollIndicator={false}
  56.       ref={scroll}
  57.       pagingEnabled
  58.       decelerationRate="normal"
  59.       snapToAlignment="center"
  60.       snapToInterval={width}
  61.       scrollEventThrottle={16}
  62.       onScroll={Animated.event([{ nativeEvent: { contentOffset: { x } } }], {
  63.         useNativeDriver: true,
  64.       })}
  65.       horizontal
  66.       bounces={false}
  67.       contentContainerStyle={{ flexGrow: 1 }}
  68.     >
  69.       {slides.map((data, index) => {
  70.         const opacity = x.interpolate({
  71.           inputRange: [
  72.             (index - 0.5) * width,
  73.             index * width,
  74.             (index + 0.5) * width,
  75.           ],
  76.           outputRange: [0.5, 1, 0.5],
  77.         });
  78.  
  79.         return (
  80.           <Slider key={index}>
  81.             <Animated.View style={{ opacity }}>
  82.               <SliderImage src={data.src} />
  83.               <Box paddingHorizontal="l">
  84.                 <SliderTitle>{data.label}</SliderTitle>
  85.                 <SliderText>{data.description}</SliderText>
  86.               </Box>
  87.             </Animated.View>
  88.           </Slider>
  89.         );
  90.       })}
  91.     </Animated.ScrollView>
  92.   );
  93. };
  94.  
  95. const renderSubSlider = (
  96.   x: Animated.Value,
  97.   width: number,
  98.   completed: boolean,
  99.   onDone: () => void,
  100.   onPress: (index: number) => void
  101. ) => {
  102.   return (
  103.     <SubSlider>
  104.       <SubSliderItem>
  105.         {slides.map((_, index) => {
  106.           return (
  107.             <Dot
  108.               key={index + 1}
  109.               currentIndex={Animated.divide(x, width)}
  110.               {...{ index }}
  111.             />
  112.           );
  113.         })}
  114.       </SubSliderItem>
  115.       <SubSliderItem>
  116.         <Button
  117.           onPress={() => {
  118.             if (completed) {
  119.               onDone();
  120.             } else {
  121.               onPress((x as any)._value / width);
  122.             }
  123.           }}
  124.           backgroundColor="onboardingButtonColor"
  125.           rounded
  126.           size="medium"
  127.         >
  128.           {completed ? "Get Started" : "Next"}
  129.         </Button>
  130.       </SubSliderItem>
  131.     </SubSlider>
  132.   );
  133. };
  134.