mirror of
https://github.com/tapframe/NuvioStreaming.git
synced 2026-04-25 18:42:53 +00:00
159 lines
No EOL
4.1 KiB
TypeScript
159 lines
No EOL
4.1 KiB
TypeScript
import React from 'react';
|
|
import {
|
|
View,
|
|
Text,
|
|
StyleSheet,
|
|
FlatList,
|
|
TouchableOpacity,
|
|
ActivityIndicator,
|
|
} from 'react-native';
|
|
import FastImage from '@d11/react-native-fast-image';
|
|
import Animated, {
|
|
FadeIn,
|
|
} from 'react-native-reanimated';
|
|
import { useTheme } from '../../contexts/ThemeContext';
|
|
|
|
interface CastSectionProps {
|
|
cast: any[];
|
|
loadingCast: boolean;
|
|
onSelectCastMember: (castMember: any) => void;
|
|
isTmdbEnrichmentEnabled?: boolean;
|
|
}
|
|
|
|
export const CastSection: React.FC<CastSectionProps> = ({
|
|
cast,
|
|
loadingCast,
|
|
onSelectCastMember,
|
|
isTmdbEnrichmentEnabled = true,
|
|
}) => {
|
|
const { currentTheme } = useTheme();
|
|
|
|
if (loadingCast) {
|
|
return (
|
|
<View style={styles.loadingContainer}>
|
|
<ActivityIndicator size="small" color={currentTheme.colors.primary} />
|
|
</View>
|
|
);
|
|
}
|
|
|
|
if (!cast || cast.length === 0) {
|
|
return null;
|
|
}
|
|
|
|
return (
|
|
<Animated.View
|
|
style={styles.castSection}
|
|
entering={FadeIn.duration(300).delay(150)}
|
|
>
|
|
<View style={styles.sectionHeader}>
|
|
<Text style={[styles.sectionTitle, { color: currentTheme.colors.highEmphasis }]}>Cast</Text>
|
|
</View>
|
|
<FlatList
|
|
horizontal
|
|
data={cast}
|
|
showsHorizontalScrollIndicator={false}
|
|
contentContainerStyle={styles.castList}
|
|
keyExtractor={(item) => item.id.toString()}
|
|
renderItem={({ item, index }) => (
|
|
<Animated.View
|
|
entering={FadeIn.duration(300).delay(50 + index * 30)}
|
|
>
|
|
<TouchableOpacity
|
|
style={styles.castCard}
|
|
onPress={() => onSelectCastMember(item)}
|
|
activeOpacity={0.7}
|
|
>
|
|
<View style={styles.castImageContainer}>
|
|
{item.profile_path ? (
|
|
<FastImage
|
|
source={{
|
|
uri: `https://image.tmdb.org/t/p/w185${item.profile_path}`,
|
|
}}
|
|
style={styles.castImage}
|
|
resizeMode={FastImage.resizeMode.cover}
|
|
/>
|
|
) : (
|
|
<View style={[styles.castImagePlaceholder, { backgroundColor: currentTheme.colors.darkBackground }]}>
|
|
<Text style={[styles.placeholderText, { color: currentTheme.colors.textMuted }]}>
|
|
{item.name.split(' ').reduce((prev: string, current: string) => prev + current[0], '').substring(0, 2)}
|
|
</Text>
|
|
</View>
|
|
)}
|
|
</View>
|
|
<Text style={[styles.castName, { color: currentTheme.colors.text }]} numberOfLines={1}>{item.name}</Text>
|
|
{isTmdbEnrichmentEnabled && item.character && (
|
|
<Text style={[styles.characterName, { color: currentTheme.colors.textMuted }]} numberOfLines={1}>{item.character}</Text>
|
|
)}
|
|
</TouchableOpacity>
|
|
</Animated.View>
|
|
)}
|
|
/>
|
|
</Animated.View>
|
|
);
|
|
};
|
|
|
|
const styles = StyleSheet.create({
|
|
castSection: {
|
|
marginBottom: 24,
|
|
paddingHorizontal: 0,
|
|
},
|
|
loadingContainer: {
|
|
paddingVertical: 20,
|
|
alignItems: 'center',
|
|
justifyContent: 'center',
|
|
},
|
|
sectionHeader: {
|
|
flexDirection: 'row',
|
|
alignItems: 'center',
|
|
justifyContent: 'space-between',
|
|
marginBottom: 12,
|
|
paddingHorizontal: 16,
|
|
},
|
|
sectionTitle: {
|
|
fontSize: 18,
|
|
fontWeight: '700',
|
|
},
|
|
castList: {
|
|
paddingHorizontal: 16,
|
|
paddingBottom: 4,
|
|
},
|
|
castCard: {
|
|
marginRight: 16,
|
|
width: 90,
|
|
alignItems: 'center',
|
|
},
|
|
castImageContainer: {
|
|
width: 80,
|
|
height: 80,
|
|
borderRadius: 40,
|
|
overflow: 'hidden',
|
|
marginBottom: 8,
|
|
},
|
|
castImage: {
|
|
width: '100%',
|
|
height: '100%',
|
|
},
|
|
castImagePlaceholder: {
|
|
width: '100%',
|
|
height: '100%',
|
|
borderRadius: 40,
|
|
alignItems: 'center',
|
|
justifyContent: 'center',
|
|
},
|
|
placeholderText: {
|
|
fontSize: 24,
|
|
fontWeight: '600',
|
|
},
|
|
castName: {
|
|
fontSize: 14,
|
|
fontWeight: '600',
|
|
textAlign: 'center',
|
|
width: 90,
|
|
},
|
|
characterName: {
|
|
fontSize: 12,
|
|
textAlign: 'center',
|
|
width: 90,
|
|
marginTop: 2,
|
|
},
|
|
});
|