import React from 'react'; import {ActivityIndicator, Animated, Text, View} from 'react-native'; import {AntDesign as Icon} from '@expo/vector-icons'; import {WithTheme, WithThemeStyles} from '../style'; import ToastStyles, {ToastStyle} from './style'; export interface ToastProps extends WithThemeStyles { content: string; duration?: number; onClose?: () => void; mask?: boolean; type?: string; onAnimationEnd?: () => void; } export default class ToastContainer extends React.Component { static defaultProps = { duration: 3, mask: true, onClose() {}, }; anim: Animated.CompositeAnimation | null | undefined; constructor(props: ToastProps) { super(props); this.state = { fadeAnim: new Animated.Value(0), }; } componentDidMount() { const {onClose, onAnimationEnd} = this.props; const duration = this.props.duration as number; const timing = Animated.timing; if (this.anim) { this.anim = null; } const animArr = [ timing(this.state.fadeAnim, { toValue: 1, duration: 200, useNativeDriver: true, }), Animated.delay(duration * 1000), ]; if (duration > 0) { animArr.push( timing(this.state.fadeAnim, { toValue: 0, duration: 200, useNativeDriver: true, }), ); } this.anim = Animated.sequence(animArr); this.anim.start(() => { if (duration > 0) { this.anim = null; if (onClose) { onClose(); } if (onAnimationEnd) { onAnimationEnd(); } } }); } componentWillUnmount() { if (this.anim) { this.anim.stop(); this.anim = null; } } render() { const {type = '', content, mask} = this.props; return ( {(styles) => { const iconType: { [key: string]: string; } = { success: 'checkcircle', fail: 'closecircle', offline: 'frown', }; let iconDom: React.ReactElement | null = null; if (type === 'loading') { iconDom = ; } else if (type === 'info') { iconDom = null; } else { // @ts-ignore iconDom = ; } return ( {iconDom} {content} ); }} ); } }