import React, { useEffect, useMemo, useState } from 'react'; import { Modal, Pressable, StyleSheet, Text, TouchableOpacity, View } from 'react-native'; import type { AlertButton } from 'react-native'; import { MaterialCommunityIcons } from '@expo/vector-icons'; import { LinearGradient } from 'expo-linear-gradient'; import { bindDialogListener, DialogPayload } from '../../services/dialogService'; import { borderRadius, shadows, spacing, useAppColors, type AppColors } from '../../theme'; function createDialogHostStyles(colors: AppColors) { return StyleSheet.create({ backdrop: { flex: 1, backgroundColor: 'rgba(0, 0, 0, 0.36)', justifyContent: 'center', alignItems: 'center', paddingHorizontal: spacing.xl, }, container: { width: '100%', maxWidth: 380, backgroundColor: colors.background.paper, borderRadius: borderRadius['2xl'], paddingHorizontal: spacing.xl, paddingTop: spacing.lg, paddingBottom: spacing.lg, ...shadows.lg, }, iconHeader: { alignItems: 'center', marginBottom: spacing.md, }, iconBadge: { width: 42, height: 42, borderRadius: borderRadius.full, justifyContent: 'center', alignItems: 'center', }, title: { color: colors.text.primary, fontSize: 18, fontWeight: '700', textAlign: 'center', }, message: { marginTop: spacing.md, color: colors.text.secondary, fontSize: 14, lineHeight: 21, textAlign: 'center', }, actions: { marginTop: spacing.xl, gap: spacing.sm, }, actionButton: { height: 46, borderRadius: borderRadius.lg, borderWidth: 1, borderColor: `${colors.primary.main}28`, backgroundColor: colors.background.paper, justifyContent: 'center', alignItems: 'center', }, primaryButton: { backgroundColor: colors.primary.main, borderColor: colors.primary.main, }, cancelButton: { backgroundColor: colors.background.paper, borderColor: colors.divider, }, destructiveButton: { backgroundColor: `${colors.error.main}18`, borderColor: `${colors.error.main}40`, }, actionText: { color: colors.text.primary, fontSize: 15, fontWeight: '700', }, primaryText: { color: colors.text.inverse, }, cancelText: { color: colors.text.secondary, fontWeight: '600', }, destructiveText: { color: colors.error.main, }, }); } const AppDialogHost: React.FC = () => { const [dialog, setDialog] = useState(null); const colors = useAppColors(); const styles = useMemo(() => createDialogHostStyles(colors), [colors]); useEffect(() => { const unbind = bindDialogListener((payload) => { setDialog(payload); }); return unbind; }, []); const actions = useMemo(() => { if (!dialog?.actions?.length) return [{ text: '确定' }]; return dialog.actions; }, [dialog]); const onClose = () => { const cancelAction = actions.find((action) => action.style === 'cancel'); if (cancelAction?.onPress) { cancelAction.onPress(); } setDialog(null); }; const onActionPress = (action: AlertButton) => { action.onPress?.(); setDialog(null); }; return ( { if (dialog?.options?.cancelable ?? true) { onClose(); } }} > {dialog?.title || '提示'} {!!dialog?.message && {dialog.message}} {actions.map((action, index) => { const isDestructive = action.style === 'destructive'; const isCancel = action.style === 'cancel'; return ( onActionPress(action)} activeOpacity={0.8} > {action.text || '确定'} ); })} ); }; export default AppDialogHost;