import { useState, useEffect, useRef } from 'react'; import { Modal, View, Text, TextInput, Pressable, KeyboardAvoidingView, Platform, Image, ActivityIndicator, Animated, Dimensions, Easing, } from 'react-native'; import { useSafeAreaInsets } from 'react-native-safe-area-context'; import { Ionicons } from '@expo/vector-icons'; import { useTranslation } from 'react-i18next'; import { isValidDomain, normalizeDomain, type Tier, } from '../../hooks/useCustomDomains'; const SCREEN_HEIGHT = Dimensions.get('window').height; const SHEET_HEIGHT = SCREEN_HEIGHT * 0.65; // wie bei PostCommentsSheet — 65% der Screen-Höhe type Props = { visible: boolean; tier: Tier; onClose: () => void; onAdd: (domain: string) => Promise<{ ok: boolean; error?: string; alreadyGlobal?: boolean }>; }; export function AddDomainSheet({ visible, tier, onClose, onAdd }: Props) { const { t } = useTranslation(); const insets = useSafeAreaInsets(); const [input, setInput] = useState(''); const [confirmPermanent, setConfirmPermanent] = useState(false); const [adding, setAdding] = useState(false); const [error, setError] = useState(null); const valid = isValidDomain(input); const normalized = normalizeDomain(input); // Slide-up Animation für die Sheet (translateY von SHEET_HEIGHT → 0) const translateY = useRef(new Animated.Value(SHEET_HEIGHT)).current; const backdropOpacity = useRef(new Animated.Value(0)).current; useEffect(() => { if (visible) { translateY.setValue(SHEET_HEIGHT); backdropOpacity.setValue(0); Animated.parallel([ Animated.timing(translateY, { toValue: 0, duration: 280, easing: Easing.out(Easing.cubic), useNativeDriver: true, }), Animated.timing(backdropOpacity, { toValue: 1, duration: 220, useNativeDriver: true, }), ]).start(); } }, [visible, translateY, backdropOpacity]); function close() { setInput(''); setConfirmPermanent(false); setError(null); onClose(); } async function handleAdd() { if (!valid || !confirmPermanent || adding) return; setAdding(true); setError(null); const result = await onAdd(input); setAdding(false); if (result.ok) { close(); return; } if (result.alreadyGlobal) { setError(t('blocker.add_sheet_already_global', { domain: normalized })); } else { setError(result.error ?? t('blocker.add_sheet_add_failed')); } } const warningText = tier.plan === 'free' ? t('blocker.add_sheet_warning_free') : t('blocker.add_sheet_warning_pro'); return ( {/* Backdrop — Tap-outside schließt */} {/* Sheet — slide-up von unten, 65% der Screen-Höhe */} {/* Drag-handle */} {/* Header */} {t('common.cancel')} {t('blocker.add_sheet_title')} {/* Input */} {t('blocker.add_sheet_label')} { setInput(v); setError(null); }} placeholder={t('blocker.add_sheet_placeholder')} placeholderTextColor="#a3a3a3" autoCapitalize="none" autoCorrect={false} autoFocus keyboardType="url" returnKeyType="done" onSubmitEditing={handleAdd} style={{ backgroundColor: '#f5f5f5', borderRadius: 12, paddingHorizontal: 14, paddingVertical: 12, fontSize: 15, fontFamily: 'Nunito_400Regular', color: '#0a0a0a', }} /> {input && !valid && ( {t('blocker.add_sheet_invalid')} )} {/* Preview */} {valid && ( {normalized} )} {/* Warning */} {valid && ( {warningText} )} {/* Confirm-Checkbox */} {valid && ( setConfirmPermanent((v) => !v)} style={{ flexDirection: 'row', alignItems: 'flex-start', gap: 10, paddingVertical: 4, }} > {confirmPermanent && } {t('blocker.add_sheet_confirm_permanent')} )} {/* Error */} {error && ( {error} )} {/* Add-Button */} ({ backgroundColor: !valid || !confirmPermanent ? '#d4d4d4' : '#dc2626', borderRadius: 14, paddingVertical: 14, alignItems: 'center', opacity: pressed ? 0.85 : 1, marginBottom: insets.bottom > 0 ? 8 : 12, })} > {adding ? ( ) : ( {t('blocker.add_sheet_title')} )} ); }