import { useTheme } from '@/hooks/useThemeColor'; import React, { useEffect } from 'react'; import { DimensionValue, View, ViewStyle } from 'react-native'; import Animated, { Easing, interpolate, useAnimatedStyle, useSharedValue, withRepeat, withTiming, } from 'react-native-reanimated'; interface SkeletonProps { width?: DimensionValue; height?: DimensionValue; borderRadius?: number; style?: ViewStyle; } export const Skeleton: React.FC = ({ width = '100%', height = 16, borderRadius = 4, style, }) => { const theme = useTheme(); const shimmerAnimation = useSharedValue(0); useEffect(() => { shimmerAnimation.value = withRepeat( withTiming(1, { duration: 1500, easing: Easing.ease, }), -1, false ); }, []); const animatedStyle = useAnimatedStyle(() => { const opacity = interpolate( shimmerAnimation.value, [0, 0.5, 1], [0.3, 0.7, 0.3] ); return { opacity, }; }); return ( ); }; // Preset skeleton components for common use cases export const SkeletonText: React.FC<{ lines?: number; lastLineWidth?: DimensionValue }> = ({ lines = 1, lastLineWidth = '75%', }) => ( {Array.from({ length: lines }).map((_, index) => ( ))} ); export const SkeletonProject: React.FC = () => ( ); export const SkeletonProjects: React.FC<{ count?: number }> = ({ count = 3 }) => ( {Array.from({ length: count }).map((_, index) => ( ))} ); // Chat-specific skeletons that look like real messages export const SkeletonChatMessage: React.FC<{ isUser?: boolean; lines?: number; width?: number; }> = ({ isUser = false, lines = 2, width }) => { const theme = useTheme(); // Realistic width calculations based on typical message lengths const getUserMessageWidth = () => { if (width) return width; // User messages: 80-200px for short, 120-250px for longer return lines === 1 ? 80 + Math.random() * 120 : 120 + Math.random() * 130; }; const getAIMessageWidth = (lineIndex: number, totalLines: number) => { if (lineIndex === totalLines - 1) { // Last line: shorter (100-180px) return 100 + Math.random() * 80; } // Other lines: longer (200-280px) return 200 + Math.random() * 80; }; return ( {isUser ? ( // User message bubble style ) : ( // AI message full width style {Array.from({ length: lines }).map((_, index) => ( ))} )} ); }; export const SkeletonChatMessages: React.FC = () => ( {/* User message - short */} {/* AI response - multiple lines */} {/* User message - longer */} {/* AI response - shorter */} {/* User message - medium */} );