Files
RSSuper/src/app/add-feed.tsx
2026-03-28 23:51:50 -04:00

187 lines
4.2 KiB
TypeScript

// Add Feed Screen
import React, { useState } from 'react';
import {
View,
TextInput,
Button,
Text,
StyleSheet,
Alert,
ActivityIndicator,
} from 'react-native';
import { useRouter } from 'expo-router';
import { useFeedStore } from '@/stores/feed-store';
import { parseFeed } from '@/services/feed-service';
import { generateId } from '@/utils/helpers';
import { t } from '@/i18n';
export default function AddFeedScreen() {
const router = useRouter();
const [url, setUrl] = useState('');
const [title, setTitle] = useState('');
const [loading, setLoading] = useState(false);
const [preview, setPreview] = useState<any>(null);
const addSubscription = useFeedStore((state) => state.addSubscription);
const handlePreview = async () => {
if (!url) {
Alert.alert('Error', 'Please enter a feed URL');
return;
}
setLoading(true);
setPreview(null);
try {
const response = await fetch(url);
const text = await response.text();
const result = await parseFeed(url, text);
if (result.success && result.feed) {
setPreview(result.feed);
} else {
Alert.alert('Error', result.error || 'Failed to parse feed');
}
} catch (error) {
Alert.alert('Error', 'Failed to fetch feed');
} finally {
setLoading(false);
}
};
const handleAdd = async () => {
if (!url) {
Alert.alert('Error', 'Please enter a feed URL');
return;
}
if (!preview) {
Alert.alert('Error', 'Please preview the feed first');
return;
}
setLoading(true);
try {
const subscription = {
id: generateId(),
url,
title: title || preview.title,
enabled: true,
fetchInterval: 60, // Default 1 hour
createdAt: new Date(),
updatedAt: new Date(),
};
await addSubscription(subscription);
router.back();
} catch (error) {
Alert.alert('Error', 'Failed to add subscription');
} finally {
setLoading(false);
}
};
return (
<View style={styles.container}>
<Text style={styles.title}>{t('feed.add')}</Text>
<View style={styles.inputContainer}>
<Text style={styles.label}>URL</Text>
<TextInput
style={styles.input}
placeholder="https://example.com/feed.xml"
value={url}
onChangeText={setUrl}
autoCapitalize="none"
autoCorrect={false}
keyboardType="url"
/>
</View>
<View style={styles.inputContainer}>
<Text style={styles.label}>Title (optional)</Text>
<TextInput
style={styles.input}
placeholder="My Feed"
value={title}
onChangeText={setTitle}
/>
</View>
<Button
title={loading && !preview ? 'Loading...' : 'Preview'}
onPress={handlePreview}
disabled={loading || !url}
/>
{preview && (
<View style={styles.previewContainer}>
<Text style={styles.previewTitle}>{preview.title}</Text>
<Text style={styles.previewDescription}>
{preview.description || 'No description'}
</Text>
<Text style={styles.previewItems}>
{preview.items.length} items
</Text>
</View>
)}
<Button
title={loading ? 'Adding...' : 'Add Feed'}
onPress={handleAdd}
disabled={loading || !preview}
/>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
padding: 20,
paddingTop: 60,
},
title: {
fontSize: 24,
fontWeight: 'bold',
marginBottom: 30,
},
inputContainer: {
marginBottom: 20,
},
label: {
fontSize: 14,
marginBottom: 8,
},
input: {
borderWidth: 1,
borderColor: '#ccc',
borderRadius: 8,
padding: 12,
fontSize: 16,
},
previewContainer: {
marginTop: 20,
padding: 16,
borderWidth: 1,
borderColor: '#ddd',
borderRadius: 8,
},
previewTitle: {
fontSize: 18,
fontWeight: 'bold',
marginBottom: 8,
},
previewDescription: {
fontSize: 14,
color: '#666',
marginBottom: 8,
},
previewItems: {
fontSize: 12,
color: '#999',
},
});