import { Ionicons } from "@expo/vector-icons"; import { Image } from "expo-image"; import React, { useRef, useState } from "react"; import { Animated, Easing, Platform, Pressable, View } from "react-native"; import { Text } from "@/components/common/Text"; import { useScaledTVSizes } from "@/constants/TVSizes"; import { useScaledTVTypography } from "@/constants/TVTypography"; import { GlassPosterView, isGlassEffectAvailable, } from "@/modules/glass-poster"; import { scaleSize } from "@/utils/scaleSize"; export interface TVSeriesSeasonCardProps { title: string; subtitle?: string; imageUrl: string | null; onPress: () => void; hasTVPreferredFocus?: boolean; /** Setter function for the ref (for focus guide destinations) */ refSetter?: (ref: View | null) => void; } export const TVSeriesSeasonCard: React.FC = ({ title, subtitle, imageUrl, onPress, hasTVPreferredFocus, refSetter, }) => { const typography = useScaledTVTypography(); const sizes = useScaledTVSizes(); const [focused, setFocused] = useState(false); // Check if glass effect is available (tvOS 26+) const useGlass = Platform.OS === "ios" && isGlassEffectAvailable(); // Scale animation for focus (only used when NOT using glass effect) const scale = useRef(new Animated.Value(1)).current; const animateTo = (value: number) => Animated.timing(scale, { toValue: value, duration: 150, easing: Easing.out(Easing.quad), useNativeDriver: true, }).start(); const renderPoster = () => { if (useGlass) { return ( ); } return ( {imageUrl ? ( ) : ( )} ); }; return ( { setFocused(true); // Only animate scale when not using glass effect (glass handles its own focus visual) if (!useGlass) { animateTo(1.05); } }} onBlur={() => { setFocused(false); if (!useGlass) { animateTo(1); } }} hasTVPreferredFocus={hasTVPreferredFocus} > {renderPoster()} {title} {subtitle && ( {subtitle} )} ); };