From d9239f3996f1fb389138754b64ed43cf4647ac2c Mon Sep 17 00:00:00 2001 From: Pablo Velez Vidal Date: Tue, 8 Nov 2022 16:39:50 +0100 Subject: [PATCH] remove the need for rerender the footer buttons when last slide --- app/screens/onboarding/footer_buttons.tsx | 59 ++++++++++++----------- app/screens/onboarding/index.tsx | 56 +++++++++------------ 2 files changed, 54 insertions(+), 61 deletions(-) diff --git a/app/screens/onboarding/footer_buttons.tsx b/app/screens/onboarding/footer_buttons.tsx index 05141003d..a587bba2a 100644 --- a/app/screens/onboarding/footer_buttons.tsx +++ b/app/screens/onboarding/footer_buttons.tsx @@ -12,11 +12,9 @@ import {makeStyleSheetFromTheme} from '@utils/theme'; type Props = { theme: Theme; - isLastSlide: boolean; lastSlideIndex: number; nextSlideHandler: () => void; signInHandler: () => void; - currentIndex: number; scrollX: Animated.SharedValue; }; @@ -38,9 +36,7 @@ const FooterButtons = ({ theme, nextSlideHandler, signInHandler, - isLastSlide, lastSlideIndex, - currentIndex, scrollX, }: Props) => { const {width} = useWindowDimensions(); @@ -49,10 +45,8 @@ const FooterButtons = ({ // keep in mind penultimate and ultimate slides to run buttons text/opacity/size animations const penultimateSlide = lastSlideIndex - 1; - const isPenultimateSlide = currentIndex === (lastSlideIndex - 1); - const needToAnimate = isLastSlide || isPenultimateSlide; - const inputRange = [penultimateSlide * width, lastSlideIndex * width]; + const inputRange = [(penultimateSlide * width), lastSlideIndex * width]; // the next button must resize in the last slide to be the 80% wide of the screen with animation const resizeStyle = useAnimatedStyle(() => { @@ -67,15 +61,26 @@ const FooterButtons = ({ }); // use for the opacity of the button text in the penultimate and last slide - const opacityTextStyle = useAnimatedStyle(() => { + const opacityNextTextStyle = useAnimatedStyle(() => { const interpolatedScale = interpolate( scrollX.value, - inputRange, - isLastSlide ? [0, 1] : [1, 0], // from last to penultimate it must fade out (from 1 to 0), once it starts getting the penultimate range it must fade in again (from 0 to 1) + [penultimateSlide * width, ((penultimateSlide * width) + (width / 2))], + [1, 0], // from last to penultimate it must fade out (from 1 to 0), once it starts getting the penultimate range it must fade in again (from 0 to 1) Extrapolate.CLAMP, ); - return {opacity: needToAnimate ? interpolatedScale : 1}; + return {opacity: interpolatedScale}; + }); + + const opacitySignInTextStyle = useAnimatedStyle(() => { + const interpolatedScale = interpolate( + scrollX.value, + [lastSlideIndex * width, ((penultimateSlide * width) + (width / 2))], + [1, 0], // from last to penultimate it must fade out (from 1 to 0), once it starts getting the penultimate range it must fade in again (from 0 to 1) + Extrapolate.CLAMP, + ); + + return {opacity: interpolatedScale}; }); // the sign in button should fade out until dissappear in the last slide @@ -90,8 +95,8 @@ const FooterButtons = ({ return {opacity: interpolatedScale}; }); - let mainButtonText = ( - + const nextButtonText = ( + ); - let mainButtonAction = nextSlideHandler; - - if (isLastSlide) { - mainButtonText = ( - - - - ); - mainButtonAction = signInHandler; - } + const signInButtonText = ( + + + + ); return ( mainButtonAction()} + onPress={() => nextSlideHandler()} style={[styles.button, buttonBackgroundStyle(theme, 'm', 'primary', 'default'), resizeStyle]} > - {mainButtonText} + {nextButtonText} + {signInButtonText} { const {width} = useWindowDimensions(); const styles = getStyleSheet(theme); - const [isLastSlide, setIsLastSlide] = useState(false); const slidesData = useSlidesData().slidesData; const lastSlideIndex = slidesData.length - 1; const slidesRef = useAnimatedRef(); - const currentIndex = useSharedValue(0); - const scrollX = useSharedValue(0); - const nextSlide = () => { + // const currentIndex = useSharedValue(0); + const scrollX = useSharedValue(0); + const currentIndex = useDerivedValue(() => Math.round(scrollX.value / width)); + + const moveToSlide = useCallback((slideIndexToMove: number) => { + slidesRef.current?.scrollTo({x: (slideIndexToMove * width), animated: true}); + }, [slidesRef.current]); + + const nextSlide = useCallback(() => { const nextSlideIndex = currentIndex.value + 1; if (slidesRef.current && currentIndex.value < lastSlideIndex) { moveToSlide(nextSlideIndex); + } else if (slidesRef.current && currentIndex.value === lastSlideIndex) { + signInHandler(); } - }; + }, [currentIndex.value, slidesRef.current, moveToSlide]); - const moveToSlide = (slideIndexToMove: number) => { - currentIndex.value = slideIndexToMove; - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - slidesRef?.current?.scrollTo({x: (slideIndexToMove * width), animated: true}); - }; - - const signInHandler = () => { - // temporal validation - setIsLastSlide(!isLastSlide); - }; + const signInHandler = useCallback(() => { + goToScreen(Screens.SERVER, '', {theme}); + }, []); const renderSlide = useCallback(({item, index}: ListRenderItemInfo) => { return ( @@ -64,17 +65,10 @@ const Onboarding = ({ ); }, []); - const toogleIsLastSlideValue = (isLast: boolean) => { - setIsLastSlide(isLast); - }; - - const handleScroll = useAnimatedScrollHandler(({contentOffset: {x}}) => { - const calculatedIndex = Math.round(x / width); - scrollX.value = x; - if (calculatedIndex !== currentIndex.value) { - currentIndex.value = calculatedIndex; - runOnJS(toogleIsLastSlideValue)(calculatedIndex === lastSlideIndex); - } + const scrollHandler = useAnimatedScrollHandler({ + onScroll: (event) => { + scrollX.value = event.contentOffset.x; + }, }); return ( @@ -93,7 +87,7 @@ const Onboarding = ({ showsHorizontalScrollIndicator={false} pagingEnabled={true} bounces={false} - onScroll={handleScroll} + onScroll={scrollHandler} ref={slidesRef} > {slidesData.map((item, index) => { @@ -108,10 +102,8 @@ const Onboarding = ({ />