A React Native app for the ultimate thinking partner.
at main 2.9 kB view raw
1import React, { useState, useEffect, useRef } from 'react'; 2import { TextInput, StyleSheet, Platform } from 'react-native'; 3 4interface MessageInputProps { 5 onTextChange: (text: string) => void; 6 onSendMessage: () => void; 7 isSendingMessage: boolean; 8 colorScheme: 'light' | 'dark'; 9 onFocusChange: (focused: boolean) => void; 10 clearTrigger: number; 11} 12 13const MessageInput: React.FC<MessageInputProps> = ({ 14 onTextChange, 15 onSendMessage, 16 isSendingMessage, 17 colorScheme, 18 onFocusChange, 19 clearTrigger, 20}) => { 21 const [inputText, setInputText] = useState(''); 22 const inputRef = useRef<any>(null); 23 24 useEffect(() => { 25 if (clearTrigger > 0) { 26 setInputText(''); 27 } 28 }, [clearTrigger]); 29 30 const handleTextChange = React.useCallback((text: string) => { 31 setInputText(text); 32 onTextChange(text); 33 }, [onTextChange]); 34 35 const handleSubmit = React.useCallback(() => { 36 if (inputText.trim() && !isSendingMessage) { 37 onSendMessage(); 38 } 39 }, [inputText, isSendingMessage, onSendMessage]); 40 41 const inputStyle = React.useMemo(() => [ 42 styles.textInput, 43 { 44 color: colorScheme === 'dark' ? '#FFFFFF' : '#000000', 45 backgroundColor: colorScheme === 'dark' ? '#242424' : '#FFFFFF', 46 fontFamily: 'Lexend_400Regular', 47 } 48 ], [colorScheme]); 49 50 const handleContentSizeChange = React.useCallback((event: any) => { 51 if (Platform.OS !== 'web') { 52 // Native platforms can use onContentSizeChange 53 const contentHeight = event.nativeEvent.contentSize.height; 54 const newHeight = Math.min(Math.max(contentHeight, 40), 120); 55 if (inputRef.current) { 56 inputRef.current.setNativeProps({ style: { height: newHeight } }); 57 } 58 } 59 }, []); 60 61 const handleFocus = React.useCallback(() => onFocusChange(true), [onFocusChange]); 62 const handleBlur = React.useCallback(() => onFocusChange(false), [onFocusChange]); 63 64 return ( 65 <TextInput 66 ref={inputRef} 67 style={inputStyle} 68 placeholder="What's on your mind?" 69 placeholderTextColor={colorScheme === 'dark' ? '#666666' : '#999999'} 70 value={inputText} 71 onChangeText={handleTextChange} 72 onFocus={handleFocus} 73 onBlur={handleBlur} 74 multiline 75 maxLength={4000} 76 editable={!isSendingMessage} 77 autoFocus 78 onSubmitEditing={handleSubmit} 79 onContentSizeChange={handleContentSizeChange} 80 /> 81 ); 82}; 83 84const styles = StyleSheet.create({ 85 textInput: { 86 width: '100%', 87 minHeight: 40, 88 maxHeight: 120, 89 paddingLeft: 18, 90 paddingRight: 130, 91 paddingTop: 8, 92 paddingBottom: 8, 93 borderRadius: 24, 94 fontSize: 16, 95 lineHeight: 24, 96 borderWidth: 0, 97 ...(Platform.OS === 'web' && { 98 // @ts-ignore 99 outline: 'none', 100 WebkitAppearance: 'none', 101 MozAppearance: 'none', 102 resize: 'none', 103 overflowY: 'auto', 104 }), 105 }, 106}); 107 108export default React.memo(MessageInput);