ui changes

This commit is contained in:
tapframe 2025-11-08 02:29:04 +05:30
parent 1c083f836b
commit a6168a7d64
2 changed files with 69 additions and 58 deletions

View file

@ -14,6 +14,7 @@ import { NavigationProp, useNavigation } from '@react-navigation/native';
import { RootStackParamList } from '../../navigation/AppNavigator'; import { RootStackParamList } from '../../navigation/AppNavigator';
import { LinearGradient } from 'expo-linear-gradient'; import { LinearGradient } from 'expo-linear-gradient';
import FastImage from '@d11/react-native-fast-image'; import FastImage from '@d11/react-native-fast-image';
import { SvgUri } from 'react-native-svg';
import { MaterialIcons } from '@expo/vector-icons'; import { MaterialIcons } from '@expo/vector-icons';
import Animated, { import Animated, {
FadeIn, FadeIn,
@ -36,8 +37,6 @@ import { useSafeAreaInsets } from 'react-native-safe-area-context';
interface AppleTVHeroProps { interface AppleTVHeroProps {
featuredContent: StreamingContent | null; featuredContent: StreamingContent | null;
allFeaturedContent?: StreamingContent[]; allFeaturedContent?: StreamingContent[];
isSaved: boolean;
handleSaveToLibrary: () => void;
loading?: boolean; loading?: boolean;
onRetry?: () => void; onRetry?: () => void;
} }
@ -50,11 +49,37 @@ const STATUS_BAR_HEIGHT = StatusBar.currentHeight || 0;
// Calculate hero height - 65% of screen height // Calculate hero height - 65% of screen height
const HERO_HEIGHT = height * 0.75; const HERO_HEIGHT = height * 0.75;
// Animated Pagination Dot Component
const PaginationDot: React.FC<{ isActive: boolean; onPress: () => void }> = React.memo(
({ isActive, onPress }) => {
const animatedStyle = useAnimatedStyle(() => {
return {
width: withTiming(isActive ? 32 : 8, {
duration: 300,
easing: Easing.out(Easing.cubic),
}),
opacity: withTiming(isActive ? 0.9 : 0.3, {
duration: 300,
easing: Easing.out(Easing.cubic),
}),
};
});
return (
<TouchableOpacity
onPress={onPress}
activeOpacity={0.7}
hitSlop={{ top: 10, bottom: 10, left: 10, right: 10 }}
>
<Animated.View style={[styles.paginationDot, animatedStyle]} />
</TouchableOpacity>
);
}
);
const AppleTVHero: React.FC<AppleTVHeroProps> = ({ const AppleTVHero: React.FC<AppleTVHeroProps> = ({
featuredContent, featuredContent,
allFeaturedContent, allFeaturedContent,
isSaved,
handleSaveToLibrary,
loading, loading,
onRetry, onRetry,
}) => { }) => {
@ -108,7 +133,7 @@ const AppleTVHero: React.FC<AppleTVHeroProps> = ({
// Retry after remaining time // Retry after remaining time
startAutoPlay(); startAutoPlay();
} }
}, 5000); // Auto-advance every 5 seconds }, 25000); // Auto-advance every 25 seconds
}, [items.length]); }, [items.length]);
useEffect(() => { useEffect(() => {
@ -334,7 +359,7 @@ const AppleTVHero: React.FC<AppleTVHeroProps> = ({
</View> </View>
{/* Content Overlay */} {/* Content Overlay */}
<View style={[styles.contentContainer, { paddingBottom: 40 + insets.bottom }]}> <View style={[styles.contentContainer, { paddingBottom: 0 + insets.bottom }]}>
{/* Logo or Title with Fade Animation */} {/* Logo or Title with Fade Animation */}
<Animated.View <Animated.View
key={`logo-${currentIndex}`} key={`logo-${currentIndex}`}
@ -342,20 +367,33 @@ const AppleTVHero: React.FC<AppleTVHeroProps> = ({
> >
{currentItem.logo && !logoError[currentIndex] ? ( {currentItem.logo && !logoError[currentIndex] ? (
<View style={styles.logoContainer}> <View style={styles.logoContainer}>
<FastImage {currentItem.logo.toLowerCase().endsWith('.svg') ? (
source={{ <SvgUri
uri: currentItem.logo, uri={currentItem.logo}
priority: FastImage.priority.high, width="100%"
cache: FastImage.cacheControl.immutable, height="100%"
}} onLoad={() => setLogoLoaded((prev) => ({ ...prev, [currentIndex]: true }))}
style={styles.logo} onError={() => {
resizeMode={FastImage.resizeMode.contain} setLogoError((prev) => ({ ...prev, [currentIndex]: true }));
onLoad={() => setLogoLoaded((prev) => ({ ...prev, [currentIndex]: true }))} logger.warn('[AppleTVHero] SVG Logo load failed:', currentItem.logo);
onError={() => { }}
setLogoError((prev) => ({ ...prev, [currentIndex]: true })); />
logger.warn('[AppleTVHero] Logo load failed:', currentItem.logo); ) : (
}} <FastImage
/> source={{
uri: currentItem.logo,
priority: FastImage.priority.high,
cache: FastImage.cacheControl.immutable,
}}
style={styles.logo}
resizeMode={FastImage.resizeMode.contain}
onLoad={() => setLogoLoaded((prev) => ({ ...prev, [currentIndex]: true }))}
onError={() => {
setLogoError((prev) => ({ ...prev, [currentIndex]: true }));
logger.warn('[AppleTVHero] Logo load failed:', currentItem.logo);
}}
/>
)}
</View> </View>
) : ( ) : (
<View style={styles.titleContainer}> <View style={styles.titleContainer}>
@ -389,32 +427,19 @@ const AppleTVHero: React.FC<AppleTVHeroProps> = ({
{/* Action Buttons - Always Visible */} {/* Action Buttons - Always Visible */}
<View style={styles.buttonsContainer}> <View style={styles.buttonsContainer}>
{/* Play Button */} {/* Info Button */}
<TouchableOpacity <TouchableOpacity
style={styles.playButton} style={styles.playButton}
onPress={() => { onPress={() => {
navigation.navigate('Streams', { navigation.navigate('Metadata', {
id: currentItem.id, id: currentItem.id,
type: currentItem.type, type: currentItem.type,
}); });
}} }}
activeOpacity={0.8} activeOpacity={0.8}
> >
<MaterialIcons name="play-arrow" size={28} color="#000" /> <MaterialIcons name="info-outline" size={28} color="#000" />
<Text style={styles.playButtonText}>Play</Text> <Text style={styles.playButtonText}>Info</Text>
</TouchableOpacity>
{/* Add to List Button */}
<TouchableOpacity
style={styles.secondaryButton}
onPress={handleSaveToLibrary}
activeOpacity={0.7}
>
<MaterialIcons
name={isSaved ? 'check' : 'add'}
size={24}
color="#fff"
/>
</TouchableOpacity> </TouchableOpacity>
</View> </View>
@ -422,19 +447,11 @@ const AppleTVHero: React.FC<AppleTVHeroProps> = ({
{items.length > 1 && ( {items.length > 1 && (
<View style={styles.paginationContainer}> <View style={styles.paginationContainer}>
{items.map((_, index) => ( {items.map((_, index) => (
<TouchableOpacity <PaginationDot
key={index} key={index}
isActive={index === currentIndex}
onPress={() => handleDotPress(index)} onPress={() => handleDotPress(index)}
activeOpacity={0.7} />
hitSlop={{ top: 10, bottom: 10, left: 10, right: 10 }}
>
<Animated.View
style={[
styles.paginationDot,
index === currentIndex && styles.paginationDotActive,
]}
/>
</TouchableOpacity>
))} ))}
</View> </View>
)} )}
@ -549,7 +566,7 @@ const styles = StyleSheet.create({
alignItems: 'center', alignItems: 'center',
justifyContent: 'center', justifyContent: 'center',
gap: 12, gap: 12,
marginBottom: 24, marginBottom: 20,
}, },
playButton: { playButton: {
flexDirection: 'row', flexDirection: 'row',
@ -558,7 +575,7 @@ const styles = StyleSheet.create({
backgroundColor: '#fff', backgroundColor: '#fff',
paddingVertical: 14, paddingVertical: 14,
paddingHorizontal: 32, paddingHorizontal: 32,
borderRadius: 8, borderRadius: 24,
gap: 8, gap: 8,
minWidth: 140, minWidth: 140,
}, },
@ -581,15 +598,11 @@ const styles = StyleSheet.create({
flexDirection: 'row', flexDirection: 'row',
alignItems: 'center', alignItems: 'center',
gap: 8, gap: 8,
marginTop: 12,
}, },
paginationDot: { paginationDot: {
width: 8,
height: 8, height: 8,
borderRadius: 4, borderRadius: 4,
backgroundColor: 'rgba(255,255,255,0.3)',
},
paginationDotActive: {
width: 32,
backgroundColor: 'rgba(255,255,255,0.9)', backgroundColor: 'rgba(255,255,255,0.9)',
}, },
bottomBlend: { bottomBlend: {
@ -597,7 +610,7 @@ const styles = StyleSheet.create({
bottom: 0, bottom: 0,
left: 0, left: 0,
right: 0, right: 0,
height: 60, height: 40,
pointerEvents: 'none', pointerEvents: 'none',
}, },
// Loading & Empty States // Loading & Empty States

View file

@ -643,8 +643,6 @@ const HomeScreen = () => {
<AppleTVHero <AppleTVHero
featuredContent={featuredContent || null} featuredContent={featuredContent || null}
allFeaturedContent={allFeaturedContent || []} allFeaturedContent={allFeaturedContent || []}
isSaved={isSaved}
handleSaveToLibrary={handleSaveToLibrary}
loading={featuredLoading} loading={featuredLoading}
/> />
); );