From 0a840b1cb0e56c2cfd08c18a46741d97214cfd18 Mon Sep 17 00:00:00 2001 From: tapframe Date: Sun, 5 Oct 2025 20:33:51 +0530 Subject: [PATCH] UI changes --- src/components/metadata/CommentsSection.tsx | 120 ++++++++++++++++---- 1 file changed, 96 insertions(+), 24 deletions(-) diff --git a/src/components/metadata/CommentsSection.tsx b/src/components/metadata/CommentsSection.tsx index c6e2fd64..8f4de8bf 100644 --- a/src/components/metadata/CommentsSection.tsx +++ b/src/components/metadata/CommentsSection.tsx @@ -9,6 +9,7 @@ import { Dimensions, Alert, ScrollView, + Animated, } from 'react-native'; import { MaterialIcons } from '@expo/vector-icons'; import TraktIcon from '../../../assets/rating-icons/trakt.svg'; @@ -43,6 +44,15 @@ const CompactCommentCard: React.FC<{ onSpoilerPress: () => void; }> = ({ comment, theme, onPress, isSpoilerRevealed, onSpoilerPress }) => { const [isPressed, setIsPressed] = useState(false); + const fadeInOpacity = useRef(new Animated.Value(0)).current; + + React.useEffect(() => { + Animated.timing(fadeInOpacity, { + toValue: 1, + duration: 220, + useNativeDriver: true, + }).start(); + }, [fadeInOpacity]); // Safety check - ensure comment data exists if (!comment || !comment.comment) { @@ -119,23 +129,27 @@ const CompactCommentCard: React.FC<{ }; return ( - setIsPressed(true)} - onPressOut={() => setIsPressed(false)} - onPress={() => { - console.log('CompactCommentCard: TouchableOpacity pressed for comment:', comment.id); - onPress(); - }} - activeOpacity={1} > + setIsPressed(true)} + onPressOut={() => setIsPressed(false)} + onPress={() => { + console.log('CompactCommentCard: TouchableOpacity pressed for comment:', comment.id); + onPress(); + }} + activeOpacity={1} + > {/* Trakt Icon - Top Right Corner */} @@ -199,7 +213,8 @@ const CompactCommentCard: React.FC<{ )} - + + ); }; @@ -416,6 +431,7 @@ export const CommentsSection: React.FC = ({ }) => { const { currentTheme } = useTheme(); const { settings } = useSettings(); + const [hasLoadedOnce, setHasLoadedOnce] = React.useState(false); const { comments, @@ -434,6 +450,13 @@ export const CommentsSection: React.FC = ({ enabled: true, }); + // Track when first load completes to avoid premature empty state + React.useEffect(() => { + if (!loading) { + setHasLoadedOnce(true); + } + }, [loading]); + // Debug logging console.log('CommentsSection: Comments data:', comments); console.log('CommentsSection: Comments length:', comments?.length); @@ -484,6 +507,44 @@ export const CommentsSection: React.FC = ({ ); }, [loading, error, currentTheme]); + const renderSkeletons = useCallback(() => { + const placeholders = [0, 1, 2]; + return ( + + {placeholders.map((i) => ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ))} + + ); + }, [currentTheme]); + // Don't show section if not authenticated, if comments are disabled in settings, or if still checking authentication // Only show when authentication is definitively true and settings allow it if (isAuthenticated !== true || !settings.showTraktComments) { @@ -523,23 +584,18 @@ export const CommentsSection: React.FC = ({ )} - {loading && comments.length === 0 && ( - - - - Loading comments... - - + {loading && comments.length === 0 && renderSkeletons()} + + {(!loading && comments.length === 0 && hasLoadedOnce && !error) && ( + renderEmpty() )} - {comments.length === 0 ? ( - renderEmpty() - ) : ( - 0 && ( + item?.id?.toString() || Math.random().toString()} + keyExtractor={(item, index) => item?.id?.toString() || `comment-${index}`} renderItem={renderComment} contentContainerStyle={styles.horizontalList} removeClippedSubviews={false} @@ -566,7 +622,7 @@ export const CommentsSection: React.FC = ({ ) : ( <> - + Load More @@ -576,6 +632,8 @@ export const CommentsSection: React.FC = ({ ) : null } + extraData={loading} + style={{ opacity: 1 }} /> )} @@ -1034,6 +1092,20 @@ const styles = StyleSheet.create({ fontSize: 14, marginTop: 12, }, + skeletonLine: { + height: 12, + borderRadius: 6, + backgroundColor: 'rgba(255,255,255,0.06)', + }, + skeletonBadge: { + backgroundColor: 'rgba(255,255,255,0.08)', + }, + skeletonDot: { + width: 16, + height: 16, + borderRadius: 8, + backgroundColor: 'rgba(255,255,255,0.08)' + }, errorContainer: { flexDirection: 'row', alignItems: 'center',