A React Native app for the ultimate thinking partner.

fix(android): improve keyboard handling and chat spacing

- Switch to pan mode for better keyboard behavior with absolute positioning
- Remove KeyboardAvoidingView for Android to avoid conflicts
- Simplify padding logic to use safe area insets consistently
- Add bottom padding to chat messages for better visibility
- Remove unused keyboard height tracking code

+11 -27
+8 -25
App.tsx
··· 18 18 Image, 19 19 KeyboardAvoidingView, 20 20 ScrollView, 21 - Keyboard, 22 21 } from 'react-native'; 23 22 import { Ionicons } from '@expo/vector-icons'; 24 23 import { StatusBar } from 'expo-status-bar'; ··· 60 59 if (Platform.OS === 'android') { 61 60 SystemUI.setBackgroundColorAsync(darkTheme.colors.background.primary); 62 61 } 63 - }, []); 64 - 65 - // Keyboard height tracking for Android 66 - const [keyboardHeight, setKeyboardHeight] = useState(0); 67 - 68 - useEffect(() => { 69 - if (Platform.OS !== 'android') return; 70 - 71 - const showSubscription = Keyboard.addListener('keyboardDidShow', (e) => { 72 - setKeyboardHeight(e.endCoordinates.height); 73 - }); 74 - const hideSubscription = Keyboard.addListener('keyboardDidHide', () => { 75 - setKeyboardHeight(0); 76 - }); 77 - 78 - return () => { 79 - showSubscription.remove(); 80 - hideSubscription.remove(); 81 - }; 82 62 }, []); 83 63 84 64 const [fontsLoaded] = useFonts({ ··· 2176 2156 behavior={Platform.OS === 'ios' ? 'padding' : undefined} 2177 2157 style={styles.chatRow} 2178 2158 keyboardVerticalOffset={Platform.OS === 'ios' ? insets.top + 60 : 0} 2159 + enabled={Platform.OS === 'ios'} 2179 2160 > 2180 2161 {/* You View */} 2181 2162 <View style={[styles.memoryViewContainer, { display: currentView === 'you' ? 'flex' : 'none', backgroundColor: theme.colors.background.primary }]}> ··· 2258 2239 initialNumToRender={100} 2259 2240 contentContainerStyle={[ 2260 2241 styles.messagesList, 2261 - displayMessages.length === 0 && { flexGrow: 1 } 2242 + displayMessages.length === 0 && { flexGrow: 1 }, 2243 + { 2244 + paddingBottom: 120 2245 + } 2262 2246 ]} 2263 2247 ListHeaderComponent={ 2264 2248 hasMoreBefore ? ( ··· 2378 2362 style={[ 2379 2363 styles.inputContainer, 2380 2364 { 2381 - paddingBottom: Platform.OS === 'android' 2382 - ? (keyboardHeight > 0 ? keyboardHeight + 40 : 40) 2383 - : Math.max(insets.bottom, 16) 2365 + paddingBottom: Math.max(insets.bottom, 16) 2384 2366 }, 2385 2367 displayMessages.length === 0 && styles.inputContainerCentered 2386 2368 ]} ··· 3097 3079 maxWidth: 700, 3098 3080 width: '100%', 3099 3081 alignSelf: 'center', 3100 - paddingBottom: 100, // Space for input at bottom 3082 + paddingBottom: 180, // Space for input at bottom (accounts for expanded input height) 3101 3083 }, 3102 3084 messageContainer: { 3103 3085 paddingHorizontal: 18, ··· 3222 3204 left: 0, 3223 3205 right: 0, 3224 3206 paddingTop: 16, 3207 + paddingBottom: 24, 3225 3208 paddingHorizontal: 16, 3226 3209 alignItems: 'center', 3227 3210 },
+3 -2
app.json
··· 10 10 "splash": { 11 11 "image": "./assets/splash-icon.png", 12 12 "resizeMode": "contain", 13 - "backgroundColor": "#ffffff" 13 + "backgroundColor": "#1B1B23" 14 14 }, 15 15 "ios": { 16 - "supportsTablet": true 16 + "supportsTablet": true, 17 + "bundleIdentifier": "com.letta.co" 17 18 }, 18 19 "android": { 19 20 "adaptiveIcon": {