import React, { useState, useCallback } from 'react'; import { View, Text, TextInput, Pressable, ActivityIndicator, KeyboardAvoidingView, Platform, ScrollView, } from 'react-native'; import { Stack, router, useFocusEffect } from 'expo-router'; import { useTexts } from '~/hooks/useTexts'; import { Header } from '~/components/Header'; import { useTheme } from '~/hooks/useTheme'; import { useStore } from '~/store/store'; import { Dropdown } from '~/components/dropdown'; import { GERMAN_VOICES, QUALITY_LABELS, PROVIDER_LABELS, getVoiceById } from '~/constants/voices'; import { urlExtractorService } from '~/services/urlExtractorService'; export default function AddTextScreen() { const [title, setTitle] = useState(''); const [content, setContent] = useState(''); const [tags, setTags] = useState(''); const [loading, setLoading] = useState(false); const [error, setError] = useState(null); const { createText, refetch } = useTexts(); const { colors } = useTheme(); const { settings } = useStore(); const [selectedVoice, setSelectedVoice] = useState(settings.voice || 'de-DE-Neural2-A'); const [inputMode, setInputMode] = useState<'text' | 'url'>('text'); const [url, setUrl] = useState(''); const [extracting, setExtracting] = useState(false); const handleExtractUrl = async () => { if (!url.trim()) { setError('Bitte gib eine URL ein'); return; } setExtracting(true); setError(null); const { data, error: extractError } = await urlExtractorService.extractFromUrl(url); setExtracting(false); if (extractError) { setError(extractError.message); return; } if (data) { setTitle(data.title); setContent(urlExtractorService.formatExtractedContent(data)); if (data.tags.length > 0) { setTags(data.tags.join(', ')); } } }; const handleSave = async () => { if (!title.trim()) { setError('Bitte gib einen Titel ein'); return; } if (!content.trim()) { setError('Bitte gib einen Text ein'); return; } setLoading(true); setError(null); const tagsArray = tags .split(',') .map((tag) => tag.trim()) .filter((tag) => tag.length > 0); try { const { data, error } = await createText(title.trim(), content.trim(), { tags: tagsArray, tts: { speed: settings.speed || 1.0, voice: selectedVoice }, source: inputMode === 'url' ? url : undefined, }); if (error) { console.error('Error creating text:', error); setError(error); setLoading(false); } else { console.log('Text created successfully:', data); // Navigate back immediately - the list will refresh via useFocusEffect router.back(); } } catch (err) { console.error('Unexpected error:', err); setError(err instanceof Error ? err.message : 'Unerwarteter Fehler'); setLoading(false); } }; return (
{loading ? ( ) : ( Speichern )} } /> {error && ( {error} )} Titel Tags (durch Komma getrennt) Stimme { const provider = voice.provider; if (!groups[provider]) { groups[provider] = {}; } const quality = voice.quality; if (!groups[provider][quality]) { groups[provider][quality] = []; } groups[provider][quality].push(voice); return groups; }, {} as Record> ) ).map(([provider, qualityGroups]) => ({ title: PROVIDER_LABELS[provider as keyof typeof PROVIDER_LABELS], options: Object.entries(qualityGroups).flatMap(([quality, voices]) => voices.map((voice) => ({ label: `${QUALITY_LABELS[quality as keyof typeof QUALITY_LABELS]} - ${voice.label}`, value: voice.value, })) ), }))} /> setInputMode('text')} className={`mr-2 rounded-lg px-4 py-2 ${inputMode === 'text' ? colors.primary : colors.surface}`} > Text setInputMode('url')} className={`rounded-lg px-4 py-2 ${inputMode === 'url' ? colors.primary : colors.surface}`} > URL {inputMode === 'text' ? ( ) : ( {extracting ? ( ) : ( Text extrahieren )} {content && ( )} )} 💡 Tipp: Du kannst später Audio für diesen Text generieren und offline anhören. {loading ? ( ) : ( Speichern )} ); }