import { FlatList, View, Box, useBreakpointValue, Pressable } from "native-base"; import React, { FC, memo, useCallback, useState, useMemo, useRef, useEffect } from "react"; import { LayoutChangeEvent, NativeScrollEvent, NativeSyntheticEvent } from "react-native"; import { CentreBox } from "./CentreBox"; import { IClaimCard } from "../buttons"; import ClaimCard from "./ClaimCard"; import ArrowLeft from "../../assets/svg/arrow-left.svg"; import ArrowRight from "../../assets/svg/arrow-right.svg"; import SvgXml from "../images/SvgXml.web"; interface ClaimCarouselProps { cards: Array; isMobile: boolean; claimed?: boolean; } interface SlideMarkProps { isActive: boolean; isLast: boolean; } const SlideMark: FC = memo(({ isActive, isLast }) => ( )); const ClaimCardItem: FC<{ item: IClaimCard; index: number }> = ({ item, index }) => { return ; }; const SlidesComponent = memo( ({ activeSlide, slidesNumber, data }: { activeSlide: number; slidesNumber: number; data: IClaimCard[] }) => ( <> {Array(slidesNumber) .fill(0) .map((_, index, arr) => ( ))} ) ); const getItemLayout = (_: IClaimCard[] | null | undefined, index: number) => ({ index, length: 275, offset: (275 - 20) * index }); const Separator = () => ; const ClaimCarousel: FC = ({ cards, claimed, isMobile }) => { const [slidesNumber, setSlidesNumber] = useState(1); const [activeSlide, setActiveSlide] = useState(0); const [activeContentWidth, setActiveContentWidth] = useState("auto"); const flatListRef = useRef(); const [layoutOffset, setLayoutOffset] = useState(0); const activeCards = useMemo(() => cards.filter(card => !card.hide), [cards, claimed]); const contentWidth = useBreakpointValue({ base: activeContentWidth, lg: claimed ? "auto" : "100%", "2xl": claimed ? "auto" : activeContentWidth }); const listWidth = useBreakpointValue({ base: "auto", lg: "100%", "2xl": 650 }); //start-hotfix: on mobile flatListLayout only updates on initial mount // so we need to handle the slidesnumber change after claim sets manually const updateSlidesNumber = useCallback(() => { setSlidesNumber(activeCards.length); }, [activeCards, claimed, slidesNumber]); useEffect(() => { if (isMobile) { updateSlidesNumber(); } }, [/* used */ claimed]); // end-of-hotfix const onFlatListLayoutChange = useCallback( (event: LayoutChangeEvent) => { const contentWidth = activeCards.length * 275 + (activeCards.length - 1) * 20; const layoutWidth = event.nativeEvent.layout.width; setActiveContentWidth(contentWidth); if (layoutWidth >= contentWidth) { setSlidesNumber(0); return; } const slides = isMobile ? activeCards.length : Math.ceil((contentWidth - layoutWidth + 36) / (275 + 20)); setSlidesNumber(slides); }, [activeCards, setSlidesNumber] ); const onScroll = useCallback( (event: NativeSyntheticEvent) => { const offSetX = event.nativeEvent.contentOffset.x; const currentSlide = Math.floor(offSetX / (275 + (offSetX === 0 ? 20 : -20))); setLayoutOffset(offSetX); if (activeSlide === currentSlide) return; setActiveSlide(currentSlide); }, [activeSlide, setActiveSlide] ); const casRight = useCallback(() => { if (!flatListRef.current) { return; } const isLast = activeSlide === slidesNumber - 1; flatListRef.current.scrollToOffset({ animated: true, index: isLast ? 0 : activeSlide + 1, offset: isLast ? 0 : layoutOffset + 275 }); }, [activeSlide, flatListRef, onScroll, slidesNumber, layoutOffset, activeCards]); const casLeft = useCallback(() => { if (!flatListRef.current) { return; } const isFirst = activeSlide === 0; flatListRef.current.scrollToOffset({ animated: true, index: isFirst ? slidesNumber - 1 : activeSlide - 1, offset: isFirst ? layoutOffset + (slidesNumber - 1) * 275 : layoutOffset - 350 }); }, [activeSlide, flatListRef, onScroll, slidesNumber, layoutOffset, activeCards]); const getFlatListRef = useCallback( (flatList: any) => { flatListRef.current = flatList; }, [activeSlide, onScroll, casLeft, casRight] ); return ( {isMobile && ( )} ); }; export default ClaimCarousel;