All files / components/Comments CommentList.tsx

100% Statements 10/10
83.33% Branches 10/12
100% Functions 2/2
100% Lines 10/10

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98                                                  3x                 5x 5x     5x     5x 1x                     4x 1x                           3x     6x                                                    
/**
 * 评论列表组件
 * 职责:展示评论列表和空状态
 */
import { memo } from 'react';
import { ActivityIndicator } from 'react-native';
import { Text, YStack } from 'tamagui';
import { Button } from '@/src/design-system/components';
import { IconSymbol } from '@/src/components/ui/IconSymbol';
import { Colors } from '@/src/constants/theme';
import { useThemeAwareColorScheme } from '@/src/hooks/useThemeAwareColorScheme';
import type { Comment } from '@/src/lib/supabase';
 
import { CommentItem } from './CommentItem';
 
interface CommentListProps {
  comments: Comment[];
  currentUserId?: string;
  isLoading: boolean;
  hasMore: boolean;
  onLike: (commentId: number) => void;
  onDelete: (commentId: number) => void;
  onLoadMore: () => void;
}
 
export const CommentList = memo(function CommentList({
  comments,
  currentUserId,
  isLoading,
  hasMore,
  onLike,
  onDelete,
  onLoadMore,
}: CommentListProps) {
  const colorScheme = useThemeAwareColorScheme();
  const colors = Colors[colorScheme];
 
  // 防御性编程:确保 comments 是数组
  const safeComments = Array.isArray(comments) ? comments : [];
 
  // 加载中状态
  if (isLoading && safeComments.length === 0) {
    return (
      <YStack alignItems="center" paddingVertical="$6">
        <ActivityIndicator size="large" color={colors.tint as any} />
        <Text fontSize="$3" color={colors.icon as any} marginTop="$2">
          加载中...
        </Text>
      </YStack>
    );
  }
 
  // 空状态
  if (safeComments.length === 0) {
    return (
      <YStack alignItems="center" paddingVertical="$6" gap="$2">
        <IconSymbol name="bubble.left" size={48} color={(colors.icon + '40') as any} />
        <Text fontSize="$4" color={colors.icon as any}>
          还没有评论
        </Text>
        <Text fontSize="$2" color={colors.icon as any}>
          快来发表第一条评论吧~
        </Text>
      </YStack>
    );
  }
 
  // 评论列表
  return (
    <YStack>
      {safeComments.map((comment) => (
        <CommentItem
          key={comment.id}
          comment={comment}
          currentUserId={currentUserId}
          onLike={onLike}
          onDelete={onDelete}
        />
      ))}
 
      {/* 加载更多按钮 */}
      {hasMore && (
        <Button
          size="$3"
          variant="outlined"
          onPress={onLoadMore}
          borderColor={colors.iconAlpha30 as any}
          color={colors.text as any}
          marginTop="$2"
          disabled={isLoading}
        >
          {isLoading ? '加载中...' : '加载更多'}
        </Button>
      )}
    </YStack>
  );
});