import React, { useState, useEffect } from 'react'; import { View, Text, LayoutChangeEvent, Dimensions } from 'react-native'; import Icon, { IconNames } from '@pingtou/rn-vant-icons'; import { useThemeFactory } from '../Theme'; import type { ToastProps } from './type'; import createStyle from './style'; import Transitions from '../Transitions'; import Loading from '../Loading'; import { isDef } from '../utils/typeof'; const windowWidth = Dimensions.get('window').width; const windowHeight = Dimensions.get('window').height; export type TimoutTimer = ReturnType; const Toast = ( props: ToastProps & { clearTimer: React.MutableRefObject } ): JSX.Element => { const { position = 'middle', message, icon, type = 'info', loadingType = 'circular', duration = 2000, clearTimer, } = props; const [visible, setVisible] = useState(true); const [layoutStyle, setLayoutStyle] = useState<{ left: number; top: number }>({ left: 0, top: 0, }); const { styles, theme } = useThemeFactory(createStyle); const renderIcon = () => { const hasIcon = icon || type === 'success' || type === 'fail'; if (hasIcon) { const iconSize = props.iconSize || theme.toast_icon_size; if (React.isValidElement(icon)) return icon; return ( ); } if (type === 'loading') { return ( ); } return null; }; const renderMessage = () => { if (isDef(message) && message !== '') { return {message}; } return null; }; useEffect(() => { if (duration && duration > 0) { clearTimer.current = setTimeout(() => { setVisible(false); }, duration); } }, []); const onLayout = (event: LayoutChangeEvent) => { const { width, height } = event.nativeEvent.layout; const left = (windowWidth - width) / 2; let top = (windowHeight - height) / 2; if (position === 'top') { top = theme.toast_position_top_distance; } else if (position === 'bottom') { top = windowHeight - height - theme.toast_position_bottom_distance; } setLayoutStyle({ left, top }); }; return ( { if (status === 'exited') { props.onClose?.(); } else { props.onOpened?.(); } }} > {renderIcon()} {renderMessage()} ); }; export default Toast;