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;