All files / components/Comments CommentInput.tsx

92.85% Statements 13/14
86.36% Branches 19/22
100% Functions 2/2
100% Lines 13/13

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 99 100 101 102 103 104 105 106 107 108                                      3x         10x 10x   10x 1x   1x 1x 1x 1x   1x       10x   10x                                                                                                         3x                          
import { memo, useState } from 'react';
import { ActivityIndicator, StyleSheet, TextInput } from 'react-native';
import { Text, XStack, YStack } from 'tamagui';
import { Button } from '@/src/design-system/components';
import { IconSymbol } from '@/src/components/ui/IconSymbol';
import {
  primaryScale,
  neutralScale,
  errorScale,
  spacing,
  radius,
} from '@/src/design-system/tokens';
 
interface CommentInputProps {
  isAuthenticated: boolean;
  onSubmit: (content: string) => Promise<void>;
  placeholder?: string;
}
 
export const CommentInput = memo(function CommentInput({
  isAuthenticated,
  onSubmit,
  placeholder = '说点什么...',
}: CommentInputProps) {
  const [text, setText] = useState('');
  const [isSubmitting, setIsSubmitting] = useState(false);
 
  const handleSubmit = async () => {
    Iif (!text.trim()) return;
 
    try {
      setIsSubmitting(true);
      await onSubmit(text.trim());
      setText('');
    } finally {
      setIsSubmitting(false);
    }
  };
 
  const canSubmit = isAuthenticated && !isSubmitting && text.trim().length > 0;
 
  return (
    <YStack gap="$2">
      <TextInput
        placeholder={isAuthenticated ? placeholder : '登录后可以发表评论'}
        placeholderTextColor={neutralScale.neutral6}
        value={text}
        onChangeText={setText}
        multiline
        numberOfLines={3}
        textAlignVertical="top"
        editable={isAuthenticated}
        maxLength={500}
        style={styles.textInput}
      />
 
      <XStack justifyContent="space-between" alignItems="center">
        <YStack opacity={text.length > 0 ? 1 : 0}>
          {text.length > 0 && (
            <Text
              fontSize="$2"
              color={text.length > 500 ? errorScale.error7 : neutralScale.neutral7}
              opacity={text.length > 450 ? 1 : 0.5}
            >
              {text.length}/500
            </Text>
          )}
        </YStack>
 
        <Button
          size="$3"
          height={44}
          fontSize={15}
          backgroundColor={primaryScale.primary7}
          color="white"
          onPress={handleSubmit}
          disabled={!canSubmit}
          opacity={canSubmit ? 1 : 0.5}
          pressStyle={{ backgroundColor: primaryScale.primary9 }}
          icon={
            isSubmitting ? (
              <ActivityIndicator size="small" color="white" />
            ) : (
              <IconSymbol name="paperplane.fill" size={16} color="white" />
            )
          }
        >
          {isSubmitting ? '发送中...' : '发表'}
        </Button>
      </XStack>
    </YStack>
  );
});
 
const styles = StyleSheet.create({
  textInput: {
    minHeight: 80,
    borderWidth: 1,
    borderColor: neutralScale.neutral4,
    borderRadius: radius[6],
    paddingHorizontal: spacing[4],
    paddingVertical: spacing[3],
    fontSize: 15,
    color: neutralScale.neutral12,
    backgroundColor: neutralScale.neutral1,
  },
});