Created
August 2, 2024 18:49
-
-
Save kedarshenoy/cbc3097ec41706b0c19c58dd3523d567 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
this is main Stack | |
import React, { useState, useRef, useEffect, useCallback } from 'react'; | |
import { View, StyleSheet, Animated, useWindowDimensions } from 'react-native'; | |
import { PanGestureHandler, ScrollView, State } from 'react-native-gesture-handler'; | |
const ROTATION = 60; | |
const SWIPE_VELOCITY = 800; | |
const QUICK_PUSH_VELOCITY = 1000; | |
const DealsAIStack = ({ data, renderItem, onSwipeRight, onSwipeLeft, onQuickPush }) => { | |
const [currentIndex, setCurrentIndex] = useState(0); | |
const [nextIndex, setNextIndex] = useState(1); | |
const currentProfile = data[currentIndex]; | |
const nextProfile = data[nextIndex]; | |
const { width: screenWidth } = useWindowDimensions(); | |
const hiddenTranslateX = 2 * screenWidth; | |
const translateX = useRef(new Animated.Value(0)).current; | |
const [top,setTop]=useState(false); | |
const rotate = translateX.interpolate({ | |
inputRange: [-hiddenTranslateX, 0, hiddenTranslateX], | |
outputRange: [`-${ROTATION}deg`, '0deg', `${ROTATION}deg`], | |
}); | |
const cardStyle = { | |
transform: [ | |
{ translateX }, | |
{ rotate }, | |
], | |
}; | |
const nextCardStyle = { | |
opacity: translateX.interpolate({ | |
inputRange: [-hiddenTranslateX, 0, hiddenTranslateX], | |
outputRange: [1, 0.5, 1], | |
}), | |
transform: [ | |
{ | |
scale: translateX.interpolate({ | |
inputRange: [-hiddenTranslateX, 0, hiddenTranslateX], | |
outputRange: [1, 0, 1], | |
extrapolate: 'clamp', | |
}), | |
}, | |
], | |
}; | |
const onGestureEvent = Animated.event( | |
[{ nativeEvent: { translationX: translateX } }], | |
{ useNativeDriver: true } | |
); | |
const onHandlerStateChange = useCallback((event) => { | |
if (event.nativeEvent.state === State.END) { | |
const { velocityX, velocityY, translationX } = event.nativeEvent; | |
if (Math.abs(velocityX) > QUICK_PUSH_VELOCITY && Math.abs(velocityX) > Math.abs(velocityY)) { | |
// Handle quick push horizontally | |
onQuickPush && onQuickPush(currentProfile); | |
Animated.spring(translateX, { | |
toValue: hiddenTranslateX * Math.sign(velocityX), | |
useNativeDriver: true, | |
}).start(() => { | |
setNextCard(); | |
}); | |
return; | |
} | |
if (Math.abs(velocityX) < SWIPE_VELOCITY || Math.abs(velocityY) > Math.abs(velocityX)) { | |
// Handle vertical scroll or slow swipe | |
Animated.spring(translateX, { | |
toValue: 0, | |
useNativeDriver: true, | |
}).start(); | |
return; | |
} | |
Animated.spring(translateX, { | |
toValue: hiddenTranslateX * Math.sign(velocityX), | |
useNativeDriver: true, | |
}).start(() => { | |
const onSwipe = velocityX > 0 ? onSwipeRight : onSwipeLeft; | |
onSwipe && onSwipe(currentProfile); | |
setNextCard(); | |
}); | |
} | |
}, [currentProfile, hiddenTranslateX, onQuickPush, onSwipeLeft, onSwipeRight, translateX]); | |
const setNextCard = useCallback(() => { | |
setCurrentIndex((prevIndex) => | |
{ | |
return prevIndex + 1}); | |
translateX.setValue(0); | |
}, [translateX]); | |
useEffect(() => { | |
setNextIndex(currentIndex + 1); | |
}, [currentIndex]); | |
return ( | |
<View style={styles.root}> | |
{nextProfile && ( | |
<View style={styles.nextCardContainer}> | |
<Animated.View style={[styles.animatedCard, nextCardStyle]}> | |
{renderItem({ item: nextProfile,top:top })} | |
</Animated.View> | |
</View> | |
)} | |
{currentProfile && ( | |
<PanGestureHandler | |
onGestureEvent={onGestureEvent} | |
onHandlerStateChange={onHandlerStateChange} | |
activeOffsetY={[-20, 20]} // Adjust this to allow vertical quick pushes | |
activeOffsetX={[-10, 10]} // This ensures horizontal swipes are detected | |
> | |
<Animated.View style={[styles.animatedCard, cardStyle]}> | |
{/* <ScrollView ref={(ref) => (scrollViewRef.current[currentIndex] = ref)}> */} | |
{renderItem({ item: currentProfile,top:top})} | |
{/* </ScrollView> */} | |
</Animated.View> | |
</PanGestureHandler> | |
)} | |
</View> | |
); | |
}; | |
const styles = StyleSheet.create({ | |
root: { | |
flex: 1, | |
// width: '100%', | |
height: 700, | |
// borderWidth:2, | |
// borderColor:'black' | |
// top: 10 | |
}, | |
animatedCard: { | |
// justifyContent: 'center', | |
}, | |
nextCardContainer: { | |
...StyleSheet.absoluteFillObject, | |
justifyContent: 'center', | |
// alignItems: 'center', | |
}, | |
}); | |
export default DealsAIStack; | |
-------------------------------------------------------------------------------------------------------------------------------- | |
This is render item/card | |
import { StyleSheet, View, ScrollView } from 'react-native'; | |
import React, { useRef, useEffect } from 'react'; | |
import DealsAiProduct from './DealsAiProduct'; | |
import DealsAiProductDesc from './DealsAiProductDesc'; | |
import { FlatList } from 'react-native-gesture-handler'; | |
export default function DealsAIWrapper({ product }) { | |
const scrollViewRef = useRef(null); | |
const products = [product]; | |
const renderItem = ({ item }) => <DealsAiProduct product={item} />; | |
const flatListRef = useRef(null); | |
// Define the key extractor function | |
const keyExtractor = (item) => "fgrfdrh"; | |
// useEffect(() => { | |
// // if (scrollViewRef.current) { | |
// scrollViewRef.current.scrollTo({ y: 0, animated: true }); | |
// // } | |
// if(scrollViewRef.current.y >0 ){ | |
// console.log("not at begining ") | |
// } | |
// }, [product]); | |
// useEffect(() => { | |
// // Scroll to the top whenever the product changes | |
// if (flatListRef.current) { | |
// flatListRef.current.scrollToOffset({ offset: 0, animated: true }); | |
// } | |
// }, [product]); | |
useEffect(() => { | |
// Scroll to the top whenever the `top` prop changes | |
if (flatListRef.current && top) { | |
flatListRef.current.scrollToOffset({ offset: 0, animated: true }); | |
} | |
}, [top]); | |
return ( | |
<View style={styles.container}> | |
<ScrollView ref={scrollViewRef}> | |
<DealsAiProduct product={product} /> | |
</ScrollView> | |
{/* <FlatList | |
ref={flatListRef} | |
data={products} // Pass the single item array | |
renderItem={renderItem} // Render function for each item | |
keyExtractor={keyExtractor} // Key extractor for each item | |
/> */} | |
</View> | |
); | |
} | |
const styles = StyleSheet.create({ | |
container: { | |
// width: '100%', | |
height: '100%', | |
// borderRadius: 10, | |
// shadowColor: '#000', | |
shadowOffset: { width: 0, height: 2 }, | |
shadowOpacity: 0.1, | |
shadowRadius: 4, | |
elevation: 5, | |
justifyContent: 'center', | |
alignItems: 'center', | |
// padding: 10, | |
}, | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment