Refactor CatalogSection, ContinueWatchingSection, and ThisWeekSection for improved styling and layout consistency

This update enhances the CatalogSection, ContinueWatchingSection, and ThisWeekSection components by refining styles, adjusting layout properties, and improving text visibility. Key changes include updated font sizes, weights, and colors for better readability, as well as modifications to button styles and spacing for a more cohesive user interface. Additionally, the gradient overlays and item containers have been optimized for a more polished appearance.
This commit is contained in:
tapframe 2025-06-21 16:01:34 +05:30
parent 14d8f92b8e
commit bc9f397ada
3 changed files with 258 additions and 138 deletions

View file

@ -80,13 +80,8 @@ const CatalogSection = ({ catalog }: CatalogSectionProps) => {
> >
<View style={styles.catalogHeader}> <View style={styles.catalogHeader}>
<View style={styles.titleContainer}> <View style={styles.titleContainer}>
<Text style={[styles.catalogTitle, { color: currentTheme.colors.highEmphasis }]}>{catalog.name}</Text> <Text style={[styles.catalogTitle, { color: currentTheme.colors.text }]}>{catalog.name}</Text>
<LinearGradient <View style={[styles.titleUnderline, { backgroundColor: currentTheme.colors.primary }]} />
colors={[currentTheme.colors.primary, currentTheme.colors.secondary]}
start={{ x: 0, y: 0 }}
end={{ x: 1, y: 0 }}
style={styles.titleUnderline}
/>
</View> </View>
<TouchableOpacity <TouchableOpacity
onPress={() => onPress={() =>
@ -96,10 +91,10 @@ const CatalogSection = ({ catalog }: CatalogSectionProps) => {
addonId: catalog.addon addonId: catalog.addon
}) })
} }
style={styles.seeAllButton} style={styles.viewAllButton}
> >
<Text style={[styles.seeAllText, { color: currentTheme.colors.primary }]}>See More</Text> <Text style={[styles.viewAllText, { color: currentTheme.colors.textMuted }]}>View All</Text>
<MaterialIcons name="arrow-forward" color={currentTheme.colors.primary} size={16} /> <MaterialIcons name="chevron-right" size={20} color={currentTheme.colors.textMuted} />
</TouchableOpacity> </TouchableOpacity>
</View> </View>
@ -130,41 +125,45 @@ const CatalogSection = ({ catalog }: CatalogSectionProps) => {
const styles = StyleSheet.create({ const styles = StyleSheet.create({
catalogContainer: { catalogContainer: {
marginBottom: 24, marginBottom: 28,
}, },
catalogHeader: { catalogHeader: {
flexDirection: 'row', flexDirection: 'row',
justifyContent: 'space-between', justifyContent: 'space-between',
alignItems: 'center', alignItems: 'center',
paddingHorizontal: 16, paddingHorizontal: 16,
marginBottom: 12, marginBottom: 16,
}, },
titleContainer: { titleContainer: {
position: 'relative', position: 'relative',
}, },
catalogTitle: { catalogTitle: {
fontSize: 19, fontSize: 24,
fontWeight: '700', fontWeight: '800',
letterSpacing: 0.2, letterSpacing: 0.5,
marginBottom: 4, marginBottom: 4,
}, },
titleUnderline: { titleUnderline: {
position: 'absolute', position: 'absolute',
bottom: -2, bottom: -2,
left: 0, left: 0,
width: 35, width: 40,
height: 2, height: 3,
borderRadius: 1, borderRadius: 2,
opacity: 0.8, opacity: 0.8,
}, },
seeAllButton: { viewAllButton: {
flexDirection: 'row', flexDirection: 'row',
alignItems: 'center', alignItems: 'center',
gap: 4, paddingVertical: 8,
paddingHorizontal: 10,
borderRadius: 20,
backgroundColor: 'rgba(255,255,255,0.1)',
}, },
seeAllText: { viewAllText: {
fontSize: 14, fontSize: 14,
fontWeight: '600', fontWeight: '600',
marginRight: 4,
}, },
catalogList: { catalogList: {
paddingHorizontal: 16, paddingHorizontal: 16,

View file

@ -277,13 +277,8 @@ const ContinueWatchingSection = React.forwardRef<ContinueWatchingRef>((props, re
<Animated.View entering={FadeIn.duration(400).delay(250)} style={styles.container}> <Animated.View entering={FadeIn.duration(400).delay(250)} style={styles.container}>
<View style={styles.header}> <View style={styles.header}>
<View style={styles.titleContainer}> <View style={styles.titleContainer}>
<Text style={[styles.title, { color: currentTheme.colors.highEmphasis }]}>Continue Watching</Text> <Text style={[styles.title, { color: currentTheme.colors.text }]}>Continue Watching</Text>
<LinearGradient <View style={[styles.titleUnderline, { backgroundColor: currentTheme.colors.primary }]} />
colors={[currentTheme.colors.primary, currentTheme.colors.secondary]}
start={{ x: 0, y: 0 }}
end={{ x: 1, y: 0 }}
style={styles.titleUnderline}
/>
</View> </View>
</View> </View>
@ -386,7 +381,7 @@ const ContinueWatchingSection = React.forwardRef<ContinueWatchingRef>((props, re
const styles = StyleSheet.create({ const styles = StyleSheet.create({
container: { container: {
marginBottom: 24, marginBottom: 28,
paddingTop: 0, paddingTop: 0,
marginTop: 12, marginTop: 12,
}, },
@ -395,15 +390,15 @@ const styles = StyleSheet.create({
justifyContent: 'space-between', justifyContent: 'space-between',
alignItems: 'center', alignItems: 'center',
paddingHorizontal: 16, paddingHorizontal: 16,
marginBottom: 12, marginBottom: 16,
}, },
titleContainer: { titleContainer: {
position: 'relative', position: 'relative',
}, },
title: { title: {
fontSize: 20, fontSize: 24,
fontWeight: '700', fontWeight: '800',
letterSpacing: 0.3, letterSpacing: 0.5,
marginBottom: 4, marginBottom: 4,
}, },
titleUnderline: { titleUnderline: {
@ -411,8 +406,8 @@ const styles = StyleSheet.create({
bottom: -2, bottom: -2,
left: 0, left: 0,
width: 40, width: 40,
height: 2, height: 3,
borderRadius: 1, borderRadius: 2,
opacity: 0.8, opacity: 0.8,
}, },
wideList: { wideList: {

View file

@ -22,8 +22,8 @@ import { parseISO, isThisWeek, format, isAfter, isBefore } from 'date-fns';
import Animated, { FadeIn, FadeInRight } from 'react-native-reanimated'; import Animated, { FadeIn, FadeInRight } from 'react-native-reanimated';
const { width } = Dimensions.get('window'); const { width } = Dimensions.get('window');
const ITEM_WIDTH = width * 0.85; const ITEM_WIDTH = width * 0.75; // Reduced width for better spacing
const ITEM_HEIGHT = 180; const ITEM_HEIGHT = 220; // Increased height for better proportions
interface ThisWeekEpisode { interface ThisWeekEpisode {
id: string; id: string;
@ -163,7 +163,10 @@ export const ThisWeekSection = () => {
if (loading) { if (loading) {
return ( return (
<View style={styles.loadingContainer}> <View style={styles.loadingContainer}>
<ActivityIndicator size="small" color={currentTheme.colors.primary} /> <ActivityIndicator size="large" color={currentTheme.colors.primary} />
<Text style={[styles.loadingText, { color: currentTheme.colors.textMuted }]}>
Loading this week's episodes...
</Text>
</View> </View>
); );
} }
@ -186,84 +189,134 @@ export const ThisWeekSection = () => {
return ( return (
<Animated.View <Animated.View
entering={FadeInRight.delay(index * 100).duration(400)} entering={FadeInRight.delay(index * 150).duration(600)}
style={styles.episodeItemContainer} style={styles.episodeItemContainer}
> >
<TouchableOpacity <TouchableOpacity
style={styles.episodeItem} style={[
styles.episodeItem,
{
shadowColor: currentTheme.colors.black,
backgroundColor: currentTheme.colors.background,
}
]}
onPress={() => handleEpisodePress(item)} onPress={() => handleEpisodePress(item)}
activeOpacity={0.7} activeOpacity={0.8}
> >
<Image <View style={styles.imageContainer}>
source={{ uri: imageUrl }} <Image
style={styles.poster} source={{ uri: imageUrl }}
contentFit="cover" style={styles.poster}
transition={300} contentFit="cover"
/> transition={400}
/>
<LinearGradient {/* Enhanced gradient overlay */}
colors={['transparent', 'rgba(0,0,0,0.8)', 'rgba(0,0,0,0.9)']} <LinearGradient
style={styles.gradient} colors={[
> 'transparent',
<View style={styles.badgeContainer}> 'rgba(0,0,0,0.3)',
<View style={[ 'rgba(0,0,0,0.7)',
styles.badge, 'rgba(0,0,0,0.9)'
isReleased ? styles.releasedBadge : styles.upcomingBadge, ]}
{ backgroundColor: isReleased ? currentTheme.colors.success + 'CC' : currentTheme.colors.primary + 'CC' } style={styles.gradient}
]}> locations={[0, 0.3, 0.7, 1]}
<MaterialIcons >
name={isReleased ? "check-circle" : "event"} {/* Top badges */}
size={12} <View style={styles.topBadgeContainer}>
color={currentTheme.colors.white} <View style={[
/> styles.statusBadge,
<Text style={[styles.badgeText, { color: currentTheme.colors.white }]}> isReleased ? styles.releasedBadge : styles.upcomingBadge,
{isReleased ? 'Released' : 'Coming Soon'} {
</Text> backgroundColor: isReleased
</View> ? currentTheme.colors.success + 'E6'
: currentTheme.colors.primary + 'E6',
{item.vote_average > 0 && ( borderColor: isReleased
<View style={[styles.ratingBadge, { backgroundColor: 'rgba(0,0,0,0.8)' }]}> ? currentTheme.colors.success
: currentTheme.colors.primary,
}
]}>
<MaterialIcons <MaterialIcons
name="star" name={isReleased ? "check-circle" : "schedule"}
size={12} size={14}
color={currentTheme.colors.primary} color={currentTheme.colors.white}
/> />
<Text style={[styles.ratingText, { color: currentTheme.colors.primary }]}> <Text style={styles.statusBadgeText}>
{item.vote_average.toFixed(1)} {isReleased ? 'Available' : 'Upcoming'}
</Text> </Text>
</View> </View>
)}
</View>
<View style={styles.content}> {item.vote_average > 0 && (
<Text style={[styles.seriesName, { color: currentTheme.colors.text }]} numberOfLines={1}> <View style={[
{item.seriesName} styles.ratingBadge,
</Text> {
<Text style={[styles.episodeTitle, { color: currentTheme.colors.lightGray }]} numberOfLines={2}> backgroundColor: 'rgba(255,193,7,0.9)',
S{item.season}:E{item.episode} - {item.title} borderColor: '#FFD700',
</Text> }
{item.overview ? ( ]}>
<Text style={[styles.overview, { color: currentTheme.colors.lightGray, opacity: 0.8 }]} numberOfLines={2}> <MaterialIcons
{item.overview} name="star"
size={14}
color="#FFF"
/>
<Text style={styles.ratingText}>
{item.vote_average.toFixed(1)}
</Text>
</View>
)}
</View>
{/* Content area */}
<View style={styles.contentArea}>
<View style={styles.seriesHeader}>
<Text style={[styles.seriesName, { color: currentTheme.colors.white }]} numberOfLines={1}>
{item.seriesName}
</Text>
<View style={[styles.episodeNumber, { backgroundColor: currentTheme.colors.primary + '40' }]}>
<Text style={[styles.episodeNumberText, { color: currentTheme.colors.primary }]}>
S{item.season}:E{item.episode}
</Text>
</View>
</View>
<Text style={[styles.episodeTitle, { color: currentTheme.colors.lightGray }]} numberOfLines={2}>
{item.title}
</Text> </Text>
) : null}
<Text style={[styles.releaseDate, { color: currentTheme.colors.primary }]}> {item.overview && (
{formattedDate} <Text style={[styles.overview, { color: currentTheme.colors.lightGray }]} numberOfLines={2}>
</Text> {item.overview}
</View> </Text>
</LinearGradient> )}
<View style={styles.dateContainer}>
<MaterialIcons
name="event"
size={14}
color={currentTheme.colors.primary}
/>
<Text style={[styles.releaseDate, { color: currentTheme.colors.primary }]}>
{formattedDate}
</Text>
</View>
</View>
</LinearGradient>
</View>
</TouchableOpacity> </TouchableOpacity>
</Animated.View> </Animated.View>
); );
}; };
return ( return (
<Animated.View entering={FadeIn.duration(300)} style={styles.container}> <Animated.View entering={FadeIn.duration(400)} style={styles.container}>
<View style={styles.header}> <View style={styles.header}>
<Text style={[styles.title, { color: currentTheme.colors.text }]}>This Week</Text> <View style={styles.titleContainer}>
<Text style={[styles.title, { color: currentTheme.colors.text }]}>This Week</Text>
<View style={[styles.titleUnderline, { backgroundColor: currentTheme.colors.primary }]} />
</View>
<TouchableOpacity onPress={handleViewAll} style={styles.viewAllButton}> <TouchableOpacity onPress={handleViewAll} style={styles.viewAllButton}>
<Text style={[styles.viewAllText, { color: currentTheme.colors.lightGray }]}>View All</Text> <Text style={[styles.viewAllText, { color: currentTheme.colors.textMuted }]}>View All</Text>
<MaterialIcons name="chevron-right" size={18} color={currentTheme.colors.lightGray} /> <MaterialIcons name="chevron-right" size={20} color={currentTheme.colors.textMuted} />
</TouchableOpacity> </TouchableOpacity>
</View> </View>
@ -274,8 +327,10 @@ export const ThisWeekSection = () => {
horizontal horizontal
showsHorizontalScrollIndicator={false} showsHorizontalScrollIndicator={false}
contentContainerStyle={styles.listContent} contentContainerStyle={styles.listContent}
snapToInterval={ITEM_WIDTH + 12} snapToInterval={ITEM_WIDTH + 16}
decelerationRate="fast" decelerationRate="fast"
snapToAlignment="start"
ItemSeparatorComponent={() => <View style={{ width: 16 }} />}
/> />
</Animated.View> </Animated.View>
); );
@ -283,109 +338,180 @@ export const ThisWeekSection = () => {
const styles = StyleSheet.create({ const styles = StyleSheet.create({
container: { container: {
marginVertical: 16, marginVertical: 20,
}, },
header: { header: {
flexDirection: 'row', flexDirection: 'row',
justifyContent: 'space-between', justifyContent: 'space-between',
alignItems: 'center', alignItems: 'center',
paddingHorizontal: 16, paddingHorizontal: 16,
marginBottom: 12, marginBottom: 16,
},
titleContainer: {
position: 'relative',
}, },
title: { title: {
fontSize: 19, fontSize: 24,
fontWeight: '700', fontWeight: '800',
letterSpacing: 0.2, letterSpacing: 0.5,
marginBottom: 4,
},
titleUnderline: {
position: 'absolute',
bottom: -2,
left: 0,
width: 40,
height: 3,
borderRadius: 2,
opacity: 0.8,
}, },
viewAllButton: { viewAllButton: {
flexDirection: 'row', flexDirection: 'row',
alignItems: 'center', alignItems: 'center',
paddingVertical: 8,
paddingHorizontal: 10,
borderRadius: 20,
backgroundColor: 'rgba(255,255,255,0.1)',
}, },
viewAllText: { viewAllText: {
fontSize: 14, fontSize: 14,
fontWeight: '600',
marginRight: 4, marginRight: 4,
}, },
listContent: { listContent: {
paddingHorizontal: 8, paddingHorizontal: 20,
paddingBottom: 8,
}, },
loadingContainer: { loadingContainer: {
padding: 20, padding: 32,
alignItems: 'center', alignItems: 'center',
}, },
loadingText: {
marginTop: 12,
fontSize: 16,
fontWeight: '500',
},
episodeItemContainer: { episodeItemContainer: {
width: ITEM_WIDTH, width: ITEM_WIDTH,
height: ITEM_HEIGHT, height: ITEM_HEIGHT,
marginHorizontal: 6,
}, },
episodeItem: { episodeItem: {
width: '100%', width: '100%',
height: '100%', height: '100%',
borderRadius: 8, borderRadius: 16,
overflow: 'hidden', overflow: 'hidden',
shadowOffset: { width: 0, height: 8 },
shadowOpacity: 0.3,
shadowRadius: 12,
elevation: 12,
},
imageContainer: {
width: '100%',
height: '100%',
position: 'relative',
}, },
poster: { poster: {
width: '100%', width: '100%',
height: '100%', height: '100%',
borderRadius: 16,
}, },
gradient: { gradient: {
position: 'absolute', position: 'absolute',
left: 0, left: 0,
right: 0, right: 0,
top: 0,
bottom: 0, bottom: 0,
height: '80%',
justifyContent: 'flex-end',
padding: 16,
},
badgeContainer: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between', justifyContent: 'space-between',
marginBottom: 12, padding: 16,
borderRadius: 16,
}, },
badge: { topBadgeContainer: {
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'flex-start',
},
statusBadge: {
flexDirection: 'row', flexDirection: 'row',
alignItems: 'center', alignItems: 'center',
paddingHorizontal: 8, paddingHorizontal: 10,
paddingVertical: 4, paddingVertical: 6,
borderRadius: 4, borderRadius: 20,
borderWidth: 1,
backgroundColor: 'rgba(0,0,0,0.3)',
}, },
releasedBadge: {}, releasedBadge: {},
upcomingBadge: {}, upcomingBadge: {},
badgeText: { statusBadgeText: {
fontSize: 10, fontSize: 11,
fontWeight: 'bold', fontWeight: '700',
marginLeft: 4, color: '#FFFFFF',
marginLeft: 6,
textTransform: 'uppercase',
letterSpacing: 0.5,
}, },
ratingBadge: { ratingBadge: {
flexDirection: 'row', flexDirection: 'row',
alignItems: 'center', alignItems: 'center',
paddingHorizontal: 8, paddingHorizontal: 8,
paddingVertical: 4, paddingVertical: 4,
borderRadius: 4, borderRadius: 16,
borderWidth: 1,
backgroundColor: 'rgba(0,0,0,0.3)',
}, },
ratingText: { ratingText: {
fontSize: 10, fontSize: 11,
fontWeight: 'bold', fontWeight: '700',
color: '#FFFFFF',
marginLeft: 4, marginLeft: 4,
}, },
content: { contentArea: {
width: '100%', justifyContent: 'flex-end',
},
seriesHeader: {
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
marginBottom: 8,
}, },
seriesName: { seriesName: {
fontSize: 16, fontSize: 18,
fontWeight: 'bold', fontWeight: '700',
marginBottom: 4, flex: 1,
marginRight: 8,
},
episodeNumber: {
paddingHorizontal: 8,
paddingVertical: 4,
borderRadius: 12,
borderWidth: 1,
borderColor: 'rgba(255,255,255,0.2)',
},
episodeNumberText: {
fontSize: 12,
fontWeight: '700',
letterSpacing: 0.5,
}, },
episodeTitle: { episodeTitle: {
fontSize: 14, fontSize: 15,
marginBottom: 4, fontWeight: '600',
marginBottom: 6,
lineHeight: 20,
}, },
overview: { overview: {
fontSize: 12, fontSize: 13,
marginBottom: 4, lineHeight: 18,
marginBottom: 8,
opacity: 0.9,
},
dateContainer: {
flexDirection: 'row',
alignItems: 'center',
marginTop: 4,
}, },
releaseDate: { releaseDate: {
fontSize: 12, fontSize: 13,
fontWeight: 'bold', fontWeight: '600',
marginLeft: 6,
letterSpacing: 0.3,
}, },
}); });