import { Ionicons } from "@expo/vector-icons"; import React from "react"; import { ActivityIndicator, Animated, Pressable, StyleSheet, View, } from "react-native"; import { Text } from "@/components/common/Text"; import { useScaledTVTypography } from "@/constants/TVTypography"; import type { SubtitleSearchResult } from "@/hooks/useRemoteSubtitles"; import { scaleSize } from "@/utils/scaleSize"; import { useTVFocusAnimation } from "./hooks/useTVFocusAnimation"; export interface TVSubtitleResultCardProps { result: SubtitleSearchResult; hasTVPreferredFocus?: boolean; isDownloading?: boolean; onPress: () => void; } export const TVSubtitleResultCard = React.forwardRef< View, TVSubtitleResultCardProps >(({ result, hasTVPreferredFocus, isDownloading, onPress }, ref) => { const typography = useScaledTVTypography(); const styles = createStyles(typography); const { focused, handleFocus, handleBlur, animatedStyle } = useTVFocusAnimation({ scaleAmount: 1.03 }); return ( {/* Provider/Source badge */} {result.providerName} {/* Name */} {result.name} {/* Meta info row */} {/* Format */} {result.format?.toUpperCase()} {/* Rating if available */} {result.communityRating !== undefined && result.communityRating > 0 && ( {result.communityRating.toFixed(1)} )} {/* Download count if available */} {result.downloadCount !== undefined && result.downloadCount > 0 && ( {result.downloadCount.toLocaleString()} )} {/* Flags */} {result.isHashMatch && ( Hash Match )} {result.hearingImpaired && ( )} {result.aiTranslated && ( AI )} {/* Loading indicator when downloading */} {isDownloading && ( )} ); }); const createStyles = (typography: ReturnType) => StyleSheet.create({ resultCard: { width: scaleSize(220), minHeight: scaleSize(120), borderRadius: scaleSize(14), padding: scaleSize(14), borderWidth: scaleSize(1), }, providerBadge: { alignSelf: "flex-start", paddingHorizontal: scaleSize(8), paddingVertical: scaleSize(3), borderRadius: scaleSize(6), marginBottom: scaleSize(8), }, providerText: { fontSize: typography.callout, fontWeight: "600", textTransform: "uppercase", letterSpacing: 0.5, }, resultName: { fontSize: typography.callout, fontWeight: "500", marginBottom: scaleSize(8), lineHeight: scaleSize(18), }, resultMeta: { flexDirection: "row", alignItems: "center", gap: scaleSize(12), marginBottom: scaleSize(8), }, resultMetaText: { fontSize: typography.callout, }, ratingContainer: { flexDirection: "row", alignItems: "center", gap: scaleSize(3), }, downloadCountContainer: { flexDirection: "row", alignItems: "center", gap: scaleSize(3), }, flagsContainer: { flexDirection: "row", gap: scaleSize(6), flexWrap: "wrap", }, flag: { paddingHorizontal: scaleSize(6), paddingVertical: scaleSize(2), borderRadius: scaleSize(4), }, flagText: { fontSize: typography.callout, fontWeight: "600", color: "#fff", }, downloadingOverlay: { ...StyleSheet.absoluteFillObject, backgroundColor: "rgba(0,0,0,0.5)", borderRadius: scaleSize(14), justifyContent: "center", alignItems: "center", }, });