import React, { useEffect, useRef, useState } from "react"; import { View, Text, Pressable, Vibration, Animated, Easing, Dimensions, } from "react-native"; import AutoDragSort from "./AutoDragSort"; const { width, height } = Dimensions.get("window"); const DnDLikeIOS = ({ data = [], setNewDataSource, Item, IconDelete, parentWidth = width, parentHeight = height, childrenWidth = 75, childrenHeight = 75, widthIconDelete = 15, heightIconDelete = 15, radiusIconDelete = "50%", degLeft = "-10deg", degRight = "10deg", timeoutShake = 20000, valueShakeLeft = 0.25, durationShakeLeft = 75, valueShakeRight = -0.25, durationShakeRight = 75, marginChildrenBottom = 10, marginChildrenRight = 10, marginChildrenLeft = 10, marginChildrenTop = 10, topIconDelete = 0, leftIconDelete = 0, }) => { const tiltAnimation = useRef(new Animated.Value(0)).current; const isAnimating = useRef(false); const endAnimationTimeout = useRef(null); const [endAnimation, setEndAnimation] = useState(false); const [dataShow, setDataShow] = useState(data); const [childSPress, setChildSPress] = useState(false); const [childLPress, setChildLPress] = useState(false); useEffect(() => { if (setNewDataSource) { setNewDataSource(dataShow); } }, [dataShow]); useEffect(() => { if (endAnimation) { endAnimationTimeout.current = setTimeout(() => { stopShakeAnimation(); setChildLPress(false); setChildSPress(false); }, timeoutShake); } else { clearTimeout(endAnimationTimeout.current); } return () => { clearTimeout(endAnimationTimeout.current); }; }, [endAnimation]); useEffect(() => { if (childLPress) { handlerLongPress(); } }, [childLPress]); useEffect(() => { if (childSPress) { stopShakeAnimation(); } }, [childSPress]); const _renderItem = (item, index) => { return Item ? ( {endAnimation && renderIconDelete(item, index)} {Item(item, index)} ) : ( Hello ); }; const renderIconDelete = (item, index) => { return IconDelete ? ( handlerDeleteItem(index)} style={{ position: "absolute", backgroundColor: "#828282", zIndex: 9999, top: topIconDelete, left: leftIconDelete, width: widthIconDelete, height: heightIconDelete, justifyContent: "center", alignItems: "center", borderRadius: radiusIconDelete, }}> {IconDelete} ) : ( handlerDeleteItem(index)} style={{ position: "absolute", backgroundColor: "#828282", zIndex: 9999, top: topIconDelete, left: leftIconDelete, width: widthIconDelete, height: heightIconDelete, justifyContent: "center", alignItems: "center", borderRadius: radiusIconDelete, }}> ); }; const handlerDeleteItem = (index) => { const currentIndex = data.findIndex((i, idx) => idx === index); const updatedDataShow = [...dataShow]; updatedDataShow.splice(currentIndex, 1); setDataShow(updatedDataShow); clearTimeout(endAnimationTimeout.current); endAnimationTimeout.current = setTimeout(() => { stopShakeAnimation(); }, 500); }; const handlerLongPress = () => { Vibration.vibrate(); startShakeAnimation(); setEndAnimation(true); }; const startShakeAnimation = () => { isAnimating.current = true; Animated.loop( Animated.sequence([ Animated.timing(tiltAnimation, { toValue: valueShakeLeft, duration: durationShakeLeft, easing: Easing.inOut(Easing.ease), useNativeDriver: true, }), Animated.timing(tiltAnimation, { toValue: valueShakeRight, duration: durationShakeRight, easing: Easing.inOut(Easing.ease), useNativeDriver: true, }), Animated.timing(tiltAnimation, { toValue: valueShakeLeft, duration: durationShakeLeft, easing: Easing.inOut(Easing.ease), useNativeDriver: true, }), Animated.timing(tiltAnimation, { toValue: valueShakeRight, duration: durationShakeRight, easing: Easing.inOut(Easing.ease), useNativeDriver: true, }), ]) ).start(() => { tiltAnimation.setValue(0); }); }; const stopShakeAnimation = () => { setChildLPress(false); setChildSPress(false); setEndAnimation(false); tiltAnimation.stopAnimation(); tiltAnimation.setValue(0); }; return ( item?.item_id || index} renderItem={(item, index) => { return _renderItem(item, index); }} setChildSPress={setChildSPress} setChildLPress={setChildLPress} childLPress={childLPress} /> ); }; export default DnDLikeIOS;