- 17 files unreferenced by the app (knip): hello-wave, parallax-scroll-view, themed-*, icon-symbol, Button, GlassCard, ScreenWrapper, Models catalog, duplicated theme/color-scheme hooks - scripts/reset-project.js and its npm script: it moves app/ to app-example and would wipe the project - dependencies only used by those files: expo-image, expo-symbols, expo-web-browser, react-native-sse, @babel/plugin-transform-runtime - GitHub Actions workflow running typecheck, lint, tests and the web export
100 lines
3.1 KiB
TypeScript
100 lines
3.1 KiB
TypeScript
import { useThemeColor } from '@/hooks/useThemeColor';
|
|
import { MessageSquare, Sparkles } from 'lucide-react-native';
|
|
import React from 'react';
|
|
import { StyleSheet, Text, TouchableOpacity, View } from 'react-native';
|
|
|
|
const PROMPT_SUGGESTIONS = [
|
|
'Explain recursion in simple terms',
|
|
'Write a short poem about coding',
|
|
'What are the best practices for React Native?',
|
|
'Help me debug a JavaScript error',
|
|
];
|
|
|
|
interface EmptyStateProps {
|
|
onSelectPrompt: (prompt: string) => void;
|
|
}
|
|
|
|
export function EmptyState({ onSelectPrompt }: EmptyStateProps) {
|
|
const colors = useThemeColor();
|
|
|
|
return (
|
|
<View style={[styles.emptyState, { backgroundColor: colors.backgroundColor }]}>
|
|
<View style={[styles.emptyIconWrap, { backgroundColor: colors.cardBackground, shadowColor: colors.shadow }]}>
|
|
<MessageSquare size={40} color={colors.textMuted} />
|
|
</View>
|
|
<Text style={[styles.emptyTitle, { color: colors.text }]}>Start a conversation</Text>
|
|
<Text style={[styles.emptySubtitle, { color: colors.textMuted }]}>
|
|
Send a message to begin chatting with your local AI model.
|
|
</Text>
|
|
|
|
<View style={styles.suggestionsWrap}>
|
|
{PROMPT_SUGGESTIONS.map((prompt) => (
|
|
<TouchableOpacity
|
|
key={prompt}
|
|
style={[styles.suggestionChip, { backgroundColor: colors.cardBackground, borderColor: colors.border }]}
|
|
onPress={() => onSelectPrompt(prompt)}
|
|
activeOpacity={0.7}
|
|
accessibilityRole="button"
|
|
accessibilityLabel={prompt}
|
|
>
|
|
<Sparkles size={14} color={colors.textMuted} />
|
|
<Text style={[styles.suggestionText, { color: colors.text }]} numberOfLines={1}>{prompt}</Text>
|
|
</TouchableOpacity>
|
|
))}
|
|
</View>
|
|
</View>
|
|
);
|
|
}
|
|
|
|
const styles = StyleSheet.create({
|
|
emptyState: {
|
|
flex: 1,
|
|
alignItems: 'center',
|
|
justifyContent: 'center',
|
|
paddingHorizontal: 32,
|
|
paddingBottom: 80,
|
|
},
|
|
emptyIconWrap: {
|
|
width: 80,
|
|
height: 80,
|
|
borderRadius: 40,
|
|
alignItems: 'center',
|
|
justifyContent: 'center',
|
|
marginBottom: 20,
|
|
shadowOffset: { width: 0, height: 4 },
|
|
shadowOpacity: 0.05,
|
|
shadowRadius: 10,
|
|
elevation: 2,
|
|
},
|
|
emptyTitle: {
|
|
fontSize: 22,
|
|
fontWeight: '700',
|
|
marginBottom: 8,
|
|
},
|
|
emptySubtitle: {
|
|
fontSize: 15,
|
|
textAlign: 'center',
|
|
lineHeight: 22,
|
|
marginBottom: 32,
|
|
},
|
|
suggestionsWrap: {
|
|
width: '100%',
|
|
maxWidth: 400,
|
|
gap: 12,
|
|
},
|
|
suggestionChip: {
|
|
flexDirection: 'row',
|
|
alignItems: 'center',
|
|
gap: 12,
|
|
borderWidth: 1,
|
|
borderRadius: 16,
|
|
paddingHorizontal: 16,
|
|
paddingVertical: 14,
|
|
},
|
|
suggestionText: {
|
|
fontSize: 15,
|
|
flex: 1,
|
|
fontWeight: '500',
|
|
},
|
|
});
|