import React, { ComponentType, useEffect, useState, useMemo } from 'react'; import { Dimensions, ImageSourcePropType, ScrollView, StyleSheet, TouchableWithoutFeedback, View, ViewStyle, } from 'react-native'; import LinearGradient from 'react-native-linear-gradient'; import { isNil } from 'lodash'; import { IconXSuccessprompt1 } from '../../icons'; import { IconXFailureprompt1 } from '../../icons'; import { IconXAbnormalprompt1 } from '../../icons'; import { IconXReminderreminder1 } from '../../icons'; import { IconXRide1, IconMAClose1 } from '../../icons'; import { Component } from '../../core/dialog/dialog-instance'; import { renderTextLikeJSX } from '../../core/helpers'; import ShouldRender from '../ShouldRender'; import { useKeyboard } from '../../utils'; import ModalFooter from './ModalFooter'; import { ModalProps, StatusType } from './interface'; import { useLocale } from '../Locale/locale'; import createStyle from './styles/modal.style'; import { useTheme } from '../Theme/Theme'; import Image from '../Image'; type Icon = ComponentType<{ color?: string; size?: string | number; fillColor?: string; }>; const IconUrlMap: { [key: string]: Icon } = { success: IconXSuccessprompt1, error: IconXFailureprompt1, warning: IconXAbnormalprompt1, info: IconXReminderreminder1, }; const rnRenderIcon = (status: StatusType) => { const IconComponent = IconUrlMap[status]; if (!IconComponent) return null; return ; }; const Modal: React.FC = (props) => { const locale = useLocale().Dialog; const token = useTheme(); const styles = createStyle(token); const { visible: propsVisible, status, statusStyle, style, content, contentStyle, title, titleStyle, message, messageStyle, extraNode, extraNodeStyle, footer, showConfirmButton = true, confirmButtonText, confirmButtonLoading, confirmButtonProps, onPressConfirm, showCancelButton, cancelButtonText, cancelButtonLoading, cancelButtonProps, onPressCancel, actions, imgSource, imgSize = 'middle', solidButton, buttonsDirection, marketingHeight, isMarketingModal, onClose, closeIcon, ...restProps } = props; const [visible, setVisible] = useState(false); const [isOverflow, setIsOverflow] = useState(false); // 内容是否超出最大高度 //监听键盘弹起,并获取键盘高度 const [keyboardHeight, setKeyboardHeight] = useState(0); useKeyboard( (e) => setKeyboardHeight(e.endCoordinates.height as number), () => setKeyboardHeight(0) ); const keyboardStyle = useMemo(() => { return {}; }, [keyboardHeight]); useEffect(() => { setVisible(propsVisible || false); }, [propsVisible]); const titleJSX = renderTextLikeJSX( title, StyleSheet.flatten([styles.titleText, titleStyle]) ); const contentJSX = renderTextLikeJSX(content); const messageJSX = renderTextLikeJSX( message, StyleSheet.flatten([ styles.messageText, messageStyle, isOverflow && styles.messageTextOverflow, ]) ); const footerProps = { showConfirmButton, showCancelButton, confirmButtonProps: { key: 'confirm', text: confirmButtonText ?? locale.confirmButtonText, onPress: onPressConfirm, color: '#ff7a00', loading: confirmButtonLoading, ...confirmButtonProps, }, cancelButtonProps: { key: 'cancel', text: cancelButtonText ?? locale.cancelButtonText, onPress: onPressCancel, cancelButtonLoading, ...cancelButtonProps, }, actions, solidButton: solidButton || (solidButton !== false && !!imgSource), buttonsDirection, }; const imgStyle = { small: styles.imgSmall, middle: styles.imgMiddle, large: styles.imgLarge, }[imgSize]; const modalWidth = Dimensions.get('window').width - 55; const maxHeight = Dimensions.get('window').height * 0.7; const onContentSizeChange = (_: number, height: number) => { setIsOverflow(height >= maxHeight - 1); }; const height = marketingHeight ? modalWidth * (4 / 3) : 'auto'; return ( 0 && keyboardStyle, style, ])} visible={visible} {...restProps} showCancelButton={false} showConfirmButton={false} overlayStyle={styles.overlayStyle} duration={120} > {rnRenderIcon(status as StatusType)} {contentJSX} {titleJSX} {messageJSX} {extraNode} {footer} {imgSize === 'large' ? ( ) : isMarketingModal ? ( ) : ( )} {closeIcon} ); }; export default Modal;