import React, { useState, useCallback, useRef } from 'react'; import { View, Text, TouchableOpacity, StyleSheet, Platform, UIManager } from 'react-native'; import MessageContent from './MessageContent'; import { darkTheme } from '../theme'; // Enable LayoutAnimation on Android if (Platform.OS === 'android' && UIManager.setLayoutAnimationEnabledExperimental) { UIManager.setLayoutAnimationEnabledExperimental(true); } interface ExpandableMessageContentProps { content: string; isUser: boolean; isDark?: boolean; lineLimit?: number; onToggle?: (expanding: boolean) => void; } const ExpandableMessageContent: React.FC = ({ content, isUser, isDark = true, lineLimit = 3, onToggle }) => { const [isExpanded, setIsExpanded] = useState(false); const [shouldShowToggle, setShouldShowToggle] = useState(false); // Only apply expandable behavior to user messages if (!isUser) { return ; } // Simple heuristic: estimate if content would exceed line limit // Assuming average ~60 chars per line in the chat bubble const estimatedLines = content.length / 60; const hasLineBreaks = (content.match(/\n/g) || []).length; const totalEstimatedLines = Math.max(estimatedLines, hasLineBreaks + 1); // Show toggle if content is likely to exceed limit const showToggle = totalEstimatedLines > lineLimit; if (!showToggle) { return ; } const handleToggle = useCallback(() => { const nextExpanded = !isExpanded; // Notify parent before state change onToggle?.(nextExpanded); // Avoid global LayoutAnimation to prevent list flicker; just toggle state setIsExpanded(nextExpanded); }, [isExpanded, onToggle]); return ( {isExpanded ? 'See less' : 'See more'} ); }; const styles = StyleSheet.create({ collapsedContainer: { maxHeight: 72, // Approximately 3 lines with standard font size overflow: 'hidden', }, toggleButton: { marginTop: 4, paddingVertical: 2, }, toggleText: { fontSize: 13, fontWeight: '500', opacity: 0.6, }, }); export default React.memo(ExpandableMessageContent);