A React Native app for the ultimate thinking partner.
at main 197 lines 4.9 kB view raw
1import React, { useState } from 'react'; 2import { 3 View, 4 Text, 5 StyleSheet, 6 TextInput, 7 TouchableOpacity, 8 ActivityIndicator, 9 SafeAreaView, 10 useColorScheme, 11 Linking, 12} from 'react-native'; 13import { StatusBar } from 'expo-status-bar'; 14import { useFonts, Lexend_400Regular, Lexend_600SemiBold, Lexend_700Bold } from '@expo-google-fonts/lexend'; 15import { darkTheme } from './src/theme'; 16 17interface CoLoginScreenProps { 18 onLogin: (apiKey: string) => Promise<void>; 19 isLoading: boolean; 20 error: string | null; 21} 22 23export default function CoLoginScreen({ onLogin, isLoading, error }: CoLoginScreenProps) { 24 const colorScheme = useColorScheme(); 25 const [apiKey, setApiKey] = useState(''); 26 27 const [fontsLoaded] = useFonts({ 28 Lexend_400Regular, 29 Lexend_600SemiBold, 30 Lexend_700Bold, 31 }); 32 33 if (!fontsLoaded) { 34 return null; 35 } 36 37 const handleLogin = async () => { 38 if (!apiKey.trim()) return; 39 await onLogin(apiKey.trim()); 40 }; 41 42 return ( 43 <SafeAreaView style={styles.container}> 44 <View style={styles.content}> 45 <View style={styles.header}> 46 <Text style={styles.title}>co</Text> 47 </View> 48 49 <View style={styles.form}> 50 <Text style={styles.label}>Letta API Key</Text> 51 <TextInput 52 style={styles.input} 53 placeholder="Enter your Letta API key" 54 placeholderTextColor={darkTheme.colors.text.tertiary} 55 value={apiKey} 56 onChangeText={setApiKey} 57 autoCapitalize="none" 58 autoCorrect={false} 59 autoFocus 60 editable={!isLoading} 61 secureTextEntry 62 /> 63 64 {error && ( 65 <View style={styles.errorContainer}> 66 <Text style={styles.errorText}>{error}</Text> 67 </View> 68 )} 69 70 <TouchableOpacity 71 style={[styles.button, isLoading && styles.buttonDisabled]} 72 onPress={handleLogin} 73 disabled={isLoading || !apiKey.trim()} 74 > 75 {isLoading ? ( 76 <ActivityIndicator size="small" color="#fff" /> 77 ) : ( 78 <Text style={styles.buttonText}>Connect</Text> 79 )} 80 </TouchableOpacity> 81 82 <Text style={styles.helpText}> 83 Don't have an API key? Visit letta.com to create one. 84 </Text> 85 86 <View style={styles.githubLink}> 87 <Text style={styles.githubText}> 88 co is{' '} 89 <Text 90 style={styles.githubLinkText} 91 onPress={() => Linking.openURL('https://github.com/letta-ai/co')} 92 > 93 open source 94 </Text> 95 {' '}and welcomes contributions 96 </Text> 97 </View> 98 </View> 99 </View> 100 <StatusBar style="auto" /> 101 </SafeAreaView> 102 ); 103} 104 105const styles = StyleSheet.create({ 106 container: { 107 flex: 1, 108 backgroundColor: darkTheme.colors.background.primary, 109 }, 110 content: { 111 flex: 1, 112 justifyContent: 'center', 113 paddingHorizontal: 32, 114 }, 115 header: { 116 alignItems: 'center', 117 marginBottom: 48, 118 }, 119 title: { 120 fontSize: 48, 121 fontFamily: 'Lexend_700Bold', 122 color: darkTheme.colors.text.primary, 123 letterSpacing: -1, 124 }, 125 form: { 126 width: '100%', 127 maxWidth: 400, 128 alignSelf: 'center', 129 }, 130 label: { 131 fontSize: 14, 132 fontFamily: 'Lexend_600SemiBold', 133 color: darkTheme.colors.text.primary, 134 marginBottom: 8, 135 }, 136 input: { 137 height: 48, 138 borderWidth: 1, 139 borderColor: darkTheme.colors.border.primary, 140 borderRadius: 8, 141 paddingHorizontal: 16, 142 fontSize: 16, 143 fontFamily: 'Lexend_400Regular', 144 backgroundColor: darkTheme.colors.background.secondary, 145 color: darkTheme.colors.text.primary, 146 marginBottom: 16, 147 }, 148 errorContainer: { 149 backgroundColor: 'rgba(255, 59, 48, 0.1)', 150 borderRadius: 8, 151 padding: 12, 152 marginBottom: 16, 153 }, 154 errorText: { 155 color: '#ff3b30', 156 fontSize: 14, 157 fontFamily: 'Lexend_400Regular', 158 textAlign: 'center', 159 }, 160 button: { 161 height: 48, 162 backgroundColor: darkTheme.colors.interactive.primary, 163 borderRadius: 8, 164 justifyContent: 'center', 165 alignItems: 'center', 166 marginBottom: 16, 167 }, 168 buttonDisabled: { 169 opacity: 0.5, 170 }, 171 buttonText: { 172 color: '#fff', 173 fontSize: 16, 174 fontFamily: 'Lexend_600SemiBold', 175 }, 176 helpText: { 177 fontSize: 14, 178 fontFamily: 'Lexend_400Regular', 179 color: darkTheme.colors.text.tertiary, 180 textAlign: 'center', 181 lineHeight: 20, 182 }, 183 githubLink: { 184 marginTop: 24, 185 alignItems: 'center', 186 }, 187 githubText: { 188 fontSize: 13, 189 fontFamily: 'Lexend_400Regular', 190 color: darkTheme.colors.text.tertiary, 191 textAlign: 'center', 192 }, 193 githubLinkText: { 194 color: darkTheme.colors.interactive.primary, 195 textDecorationLine: 'underline', 196 }, 197});