import { Dimensions, Image, StyleSheet, Text, View, type ViewStyle, type ImageSourcePropType, Platform } from 'react-native' import React, { useEffect } from 'react' import { GestureDetector } from 'react-native-gesture-handler' import Animated, {Easing, useAnimatedStyle, useSharedValue, withSpring, withTiming} from 'react-native-reanimated' const Toast = ({ message, visible = false, duration = 2000, speed = 300, progress = false, bounce = false, autoDismiss = false, centerText = false, dismissGesture, icon = undefined, style = {}, dismiss }: { message: string, visible: boolean, duration?: number, speed?: number, progress?: boolean, bounce?: boolean, autoDismiss?: boolean, centerText?: boolean, icon?: ImageSourcePropType, dismissGesture: any, style?: ViewStyle | undefined | ViewStyle[], dismiss: () => void }) => { const initialToastPosition = -Dimensions.get('window').height const toastVisiblePosition = Platform.OS == 'ios' ? 50 : 0 const progressValue = useSharedValue(Dimensions.get('window').width) const topValue = useSharedValue(initialToastPosition) let hideToastTimeout: NodeJS.Timeout const dismissToast = () => { topValue.value = withTiming(initialToastPosition, { duration: 400 }) dismiss() } useEffect(() => { if (visible) { topValue.value = initialToastPosition animateProgressBar() if (bounce) { topValue.value = withSpring(toastVisiblePosition, { mass: .7, damping: 10, stiffness: 100, overshootClamping: false, restDisplacementThreshold: 0.01, restSpeedThreshold: 2 }) } else { topValue.value = withTiming(toastVisiblePosition, { duration: speed, easing: Easing.linear }) } hideToastTimeout = setTimeout(() => { if (autoDismiss) { dismissToast() } }, duration + 1800); } else { dismissToast() } return () => { clearTimeout(hideToastTimeout) } }, [visible]) const animateProgressBar = () => { progressValue.value = Dimensions.get('window').width - 20 progressValue.value = withTiming(0, { duration: duration + 2000, }) } const animatedContainerStyle = useAnimatedStyle(() => { return { transform: [ { translateY: topValue.value, } ], } }) const animatedProgressBar = useAnimatedStyle(() => { return { width: progressValue.value } }) const Icon = () => { if (!icon) { return null } return ( ) } return ( {message} { progress && ( ) } ) } const styles = StyleSheet.create({ container: { position: 'absolute', zIndex: 10000000000, width: Dimensions.get('window').width - 20, marginHorizontal: 10, marginTop: 15, borderRadius: 5 } }) export default Toast