import React, { useState, useEffect } from 'react'; import { View, Text, StyleSheet, ScrollView, SafeAreaView, StatusBar, TextInput, TouchableOpacity, Linking, Platform, Dimensions, Switch, } from 'react-native'; import CustomAlert from '../components/CustomAlert'; import { mmkvStorage } from '../services/mmkvStorage'; import { useNavigation } from '@react-navigation/native'; import { MaterialIcons } from '@expo/vector-icons'; import { useTheme } from '../contexts/ThemeContext'; import { useSafeAreaInsets } from 'react-native-safe-area-context'; import { useSettings } from '../hooks/useSettings'; import { SvgXml } from 'react-native-svg'; import { useTranslation } from 'react-i18next'; const { width } = Dimensions.get('window'); const isTablet = width >= 768; const AISettingsScreen: React.FC = () => { const { t } = useTranslation(); // CustomAlert state (must be inside the component) const [alertVisible, setAlertVisible] = useState(false); const [alertTitle, setAlertTitle] = useState(''); const [alertMessage, setAlertMessage] = useState(''); const [alertActions, setAlertActions] = useState void; style?: object }>>([ { label: 'OK', onPress: () => setAlertVisible(false) }, ]); const openAlert = ( title: string, message: string, actions?: Array<{ label: string; onPress?: () => void; style?: object }> ) => { setAlertTitle(title); setAlertMessage(message); if (actions && actions.length > 0) { setAlertActions( actions.map(a => ({ label: a.label, style: a.style, onPress: () => { a.onPress?.(); }, })) ); } else { setAlertActions([{ label: 'OK', onPress: () => setAlertVisible(false) }]); } setAlertVisible(true); }; const navigation = useNavigation(); const { currentTheme } = useTheme(); const insets = useSafeAreaInsets(); const { settings, updateSetting } = useSettings(); const OPENROUTER_SVG = ` OpenRouter `; const [apiKey, setApiKey] = useState(''); const [loading, setLoading] = useState(false); const [isKeySet, setIsKeySet] = useState(false); useEffect(() => { loadApiKey(); }, []); const loadApiKey = async () => { try { const savedKey = await mmkvStorage.getItem('openrouter_api_key'); if (savedKey) { setApiKey(savedKey); setIsKeySet(true); } } catch (error) { if (__DEV__) console.error('Error loading OpenRouter API key:', error); } }; const handleSaveApiKey = async () => { if (!apiKey.trim()) { openAlert(t('common.error'), t('ai_settings.error_invalid_key')); return; } if (!apiKey.startsWith('sk-or-')) { openAlert(t('common.error'), t('ai_settings.error_key_format')); return; } setLoading(true); try { await mmkvStorage.setItem('openrouter_api_key', apiKey.trim()); setIsKeySet(true); openAlert(t('common.success'), t('ai_settings.success_saved')); } catch (error) { openAlert(t('common.error'), t('ai_settings.error_save')); if (__DEV__) console.error('Error saving OpenRouter API key:', error); } finally { setLoading(false); } }; const handleRemoveApiKey = () => { openAlert( t('ai_settings.confirm_remove_title'), t('ai_settings.confirm_remove_msg'), [ { label: t('common.cancel'), onPress: () => { } }, { label: 'Remove', onPress: async () => { try { await mmkvStorage.removeItem('openrouter_api_key'); setApiKey(''); setIsKeySet(false); openAlert(t('common.success'), t('ai_settings.success_removed')); } catch (error) { openAlert(t('common.error'), t('ai_settings.error_remove')); } } } ] ); }; const handleGetApiKey = () => { Linking.openURL('https://openrouter.ai/keys'); }; return ( {/* Header */} navigation.goBack()} style={styles.backButton} > {t('settings.settings_title')} {/* Empty for now, but ready for future actions */} {t('ai_settings.title')} {/* Info Card */} {t('ai_settings.info_title')} {t('ai_settings.info_desc')} {t('ai_settings.feature_1')} {t('ai_settings.feature_2')} {t('ai_settings.feature_3')} {t('ai_settings.feature_4')} {/* API Key Configuration */} {t('ai_settings.api_key_section')} {t('ai_settings.api_key_label')} {t('ai_settings.api_key_desc')} {!isKeySet ? ( {loading ? t('ai_settings.saving') : t('ai_settings.save_api_key')} ) : ( {t('ai_settings.update')} {t('ai_settings.remove')} )} {t('ai_settings.get_free_key')} {/* Enable Toggle (top) */} {t('ai_settings.enable_chat')} updateSetting('aiChatEnabled', v)} trackColor={{ false: currentTheme.colors.elevation2, true: currentTheme.colors.primary }} thumbColor={settings.aiChatEnabled ? currentTheme.colors.white : currentTheme.colors.mediumEmphasis} ios_backgroundColor={currentTheme.colors.elevation2} /> {t('ai_settings.enable_chat_desc')} {/* Status Card */} {isKeySet && ( {t('ai_settings.chat_enabled')} {t('ai_settings.chat_enabled_desc')} )} {/* Usage Info */} {t('ai_settings.how_it_works')} {t('ai_settings.how_it_works_desc')} {/* OpenRouter branding */} setAlertVisible(false)} actions={alertActions} /> ); }; const styles = StyleSheet.create({ container: { flex: 1, }, header: { flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', paddingHorizontal: 16, paddingTop: Platform.OS === 'android' ? (StatusBar.currentHeight || 0) + 8 : 8, }, backButton: { flexDirection: 'row', alignItems: 'center', padding: 8, }, backText: { fontSize: 17, marginLeft: 8, }, headerActions: { flexDirection: 'row', alignItems: 'center', }, headerButton: { padding: 8, marginLeft: 8, }, headerTitle: { fontSize: 34, fontWeight: 'bold', paddingHorizontal: 20, marginBottom: 24, }, scrollView: { flex: 1, }, scrollContent: { paddingBottom: 40, }, infoCard: { borderRadius: 16, padding: 20, marginHorizontal: 16, marginBottom: 20, }, infoHeader: { flexDirection: 'row', alignItems: 'center', marginBottom: 12, }, infoTitle: { fontSize: 20, fontWeight: '700', marginLeft: 12, }, infoDescription: { fontSize: 16, lineHeight: 24, marginBottom: 16, }, featureList: { gap: 8, }, featureItem: { flexDirection: 'row', alignItems: 'center', }, featureText: { fontSize: 15, marginLeft: 8, flex: 1, }, card: { borderRadius: 16, padding: 20, marginHorizontal: 16, marginBottom: 20, }, cardTitle: { fontSize: 13, fontWeight: '600', letterSpacing: 0.8, marginBottom: 16, }, apiKeySection: { gap: 12, }, label: { fontSize: 16, fontWeight: '600', }, description: { fontSize: 14, lineHeight: 20, }, input: { borderRadius: 12, padding: 16, fontSize: 16, fontFamily: Platform.OS === 'ios' ? 'Menlo' : 'monospace', borderWidth: 1, }, buttonContainer: { marginTop: 8, }, buttonRow: { flexDirection: 'row', gap: 12, }, saveButton: { flexDirection: 'row', alignItems: 'center', justifyContent: 'center', paddingVertical: 14, paddingHorizontal: 20, borderRadius: 12, }, saveButtonText: { color: 'white', fontSize: 16, fontWeight: '600', }, updateButton: { flexDirection: 'row', alignItems: 'center', justifyContent: 'center', paddingVertical: 14, paddingHorizontal: 20, borderRadius: 12, flex: 1, }, updateButtonText: { color: 'white', fontSize: 16, fontWeight: '600', }, removeButton: { flexDirection: 'row', alignItems: 'center', justifyContent: 'center', paddingVertical: 14, paddingHorizontal: 20, borderRadius: 12, borderWidth: 2, flex: 1, }, removeButtonText: { fontSize: 16, fontWeight: '600', }, getKeyButton: { flexDirection: 'row', alignItems: 'center', justifyContent: 'center', paddingVertical: 12, paddingHorizontal: 16, borderRadius: 12, marginTop: 8, }, getKeyButtonText: { fontSize: 15, fontWeight: '500', }, statusCard: { borderRadius: 16, padding: 20, marginBottom: 20, }, statusHeader: { flexDirection: 'row', alignItems: 'center', marginBottom: 8, }, statusTitle: { fontSize: 18, fontWeight: '600', marginLeft: 12, }, statusDescription: { fontSize: 15, lineHeight: 22, }, usageCard: { borderRadius: 16, padding: 20, }, usageTitle: { fontSize: 18, fontWeight: '600', marginBottom: 12, }, usageText: { fontSize: 15, lineHeight: 24, }, }); export default AISettingsScreen;