some minor UI fixes
This commit is contained in:
parent
9fcb6a34b7
commit
213fbbbb4e
3 changed files with 53 additions and 14 deletions
|
|
@ -19,7 +19,7 @@ interface HeroCarouselProps {
|
||||||
const { width } = Dimensions.get('window');
|
const { width } = Dimensions.get('window');
|
||||||
|
|
||||||
const CARD_WIDTH = Math.min(width * 0.8, 480);
|
const CARD_WIDTH = Math.min(width * 0.8, 480);
|
||||||
const CARD_HEIGHT = Math.round(CARD_WIDTH * 9 / 16) + 290; // slight increase for text/actions
|
const CARD_HEIGHT = Math.round(CARD_WIDTH * 9 / 16) + 310; // increased for more vertical space
|
||||||
|
|
||||||
const HeroCarousel: React.FC<HeroCarouselProps> = ({ items, loading = false }) => {
|
const HeroCarousel: React.FC<HeroCarouselProps> = ({ items, loading = false }) => {
|
||||||
const navigation = useNavigation<NavigationProp<RootStackParamList>>();
|
const navigation = useNavigation<NavigationProp<RootStackParamList>>();
|
||||||
|
|
@ -80,9 +80,39 @@ const HeroCarousel: React.FC<HeroCarouselProps> = ({ items, loading = false }) =
|
||||||
if (clamped !== activeIndex) setActiveIndex(clamped);
|
if (clamped !== activeIndex) setActiveIndex(clamped);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleScroll = (event: any) => {
|
||||||
|
const offsetX = event?.nativeEvent?.contentOffset?.x ?? 0;
|
||||||
|
const interval = CARD_WIDTH + 16;
|
||||||
|
const idx = Math.round(offsetX / interval);
|
||||||
|
const clamped = Math.max(0, Math.min(idx, data.length - 1));
|
||||||
|
if (clamped !== activeIndex) setActiveIndex(clamped);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Animated.View entering={FadeIn.duration(350).easing(Easing.out(Easing.cubic))}>
|
<Animated.View entering={FadeIn.duration(350).easing(Easing.out(Easing.cubic))}>
|
||||||
<View style={styles.container as ViewStyle}>
|
<View style={styles.container as ViewStyle}>
|
||||||
|
{data.length > 0 && (
|
||||||
|
<View style={{ height: 0, width: 0, overflow: 'hidden' }}>
|
||||||
|
{data[activeIndex + 1] && (
|
||||||
|
<ExpoImage
|
||||||
|
source={{ uri: data[activeIndex + 1].banner || data[activeIndex + 1].poster }}
|
||||||
|
style={{ width: 1, height: 1 }}
|
||||||
|
contentFit="cover"
|
||||||
|
cachePolicy="memory-disk"
|
||||||
|
transition={0}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{activeIndex > 0 && data[activeIndex - 1] && (
|
||||||
|
<ExpoImage
|
||||||
|
source={{ uri: data[activeIndex - 1].banner || data[activeIndex - 1].poster }}
|
||||||
|
style={{ width: 1, height: 1 }}
|
||||||
|
contentFit="cover"
|
||||||
|
cachePolicy="memory-disk"
|
||||||
|
transition={0}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</View>
|
||||||
|
)}
|
||||||
{data[activeIndex] && (
|
{data[activeIndex] && (
|
||||||
<View
|
<View
|
||||||
style={[
|
style={[
|
||||||
|
|
@ -103,9 +133,10 @@ const HeroCarousel: React.FC<HeroCarouselProps> = ({ items, loading = false }) =
|
||||||
contentFit="cover"
|
contentFit="cover"
|
||||||
blurRadius={36}
|
blurRadius={36}
|
||||||
cachePolicy="memory-disk"
|
cachePolicy="memory-disk"
|
||||||
|
transition={220}
|
||||||
/>
|
/>
|
||||||
<LinearGradient
|
<LinearGradient
|
||||||
colors={["rgba(0,0,0,0.65)", "rgba(0,0,0,0.85)"]}
|
colors={["rgba(0,0,0,0.45)", "rgba(0,0,0,0.75)"]}
|
||||||
locations={[0.4, 1]}
|
locations={[0.4, 1]}
|
||||||
style={styles.backgroundOverlay as ViewStyle}
|
style={styles.backgroundOverlay as ViewStyle}
|
||||||
/>
|
/>
|
||||||
|
|
@ -127,6 +158,7 @@ const HeroCarousel: React.FC<HeroCarouselProps> = ({ items, loading = false }) =
|
||||||
snapToInterval={CARD_WIDTH + 16}
|
snapToInterval={CARD_WIDTH + 16}
|
||||||
decelerationRate="fast"
|
decelerationRate="fast"
|
||||||
contentContainerStyle={{ paddingHorizontal: (width - CARD_WIDTH) / 2 }}
|
contentContainerStyle={{ paddingHorizontal: (width - CARD_WIDTH) / 2 }}
|
||||||
|
onScroll={handleScroll}
|
||||||
onMomentumScrollEnd={handleMomentumEnd}
|
onMomentumScrollEnd={handleMomentumEnd}
|
||||||
renderItem={({ item }) => (
|
renderItem={({ item }) => (
|
||||||
<View style={{ width: CARD_WIDTH + 16 }}>
|
<View style={{ width: CARD_WIDTH + 16 }}>
|
||||||
|
|
@ -144,8 +176,8 @@ const HeroCarousel: React.FC<HeroCarouselProps> = ({ items, loading = false }) =
|
||||||
cachePolicy="memory-disk"
|
cachePolicy="memory-disk"
|
||||||
/>
|
/>
|
||||||
<LinearGradient
|
<LinearGradient
|
||||||
colors={["transparent", "rgba(0,0,0,0.35)"]}
|
colors={["transparent", "rgba(0,0,0,0.2)", "rgba(0,0,0,0.6)"]}
|
||||||
locations={[0.6, 1]}
|
locations={[0.4, 0.7, 1]}
|
||||||
style={styles.bannerGradient as ViewStyle}
|
style={styles.bannerGradient as ViewStyle}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
|
|
|
||||||
|
|
@ -369,13 +369,14 @@ const HomeScreen = () => {
|
||||||
StatusBar.setTranslucent(true);
|
StatusBar.setTranslucent(true);
|
||||||
StatusBar.setBackgroundColor('transparent');
|
StatusBar.setBackgroundColor('transparent');
|
||||||
|
|
||||||
|
// Ensure portrait when coming back to Home on all platforms
|
||||||
|
try {
|
||||||
|
ScreenOrientation.lockAsync(ScreenOrientation.OrientationLock.PORTRAIT_UP);
|
||||||
|
} catch {}
|
||||||
|
|
||||||
// For iOS specifically
|
// For iOS specifically
|
||||||
if (Platform.OS === 'ios') {
|
if (Platform.OS === 'ios') {
|
||||||
StatusBar.setHidden(false);
|
StatusBar.setHidden(false);
|
||||||
// Ensure portrait when coming back to Home on iOS
|
|
||||||
try {
|
|
||||||
ScreenOrientation.lockAsync(ScreenOrientation.OrientationLock.PORTRAIT_UP);
|
|
||||||
} catch {}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -607,8 +608,11 @@ const HomeScreen = () => {
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
// Memoize individual section components to prevent re-renders
|
// Memoize individual section components to prevent re-renders
|
||||||
const memoizedFeaturedContent = useMemo(() => (
|
const memoizedFeaturedContent = useMemo(() => {
|
||||||
settings.heroStyle === 'carousel' ? (
|
const deviceWidth = Dimensions.get('window').width;
|
||||||
|
const isTablet = deviceWidth >= 768;
|
||||||
|
const heroStyleToUse = isTablet ? 'legacy' : settings.heroStyle;
|
||||||
|
return heroStyleToUse === 'carousel' ? (
|
||||||
<HeroCarousel
|
<HeroCarousel
|
||||||
key={`carousel-${featuredContentSource}`}
|
key={`carousel-${featuredContentSource}`}
|
||||||
items={allFeaturedContent || (featuredContent ? [featuredContent] : [])}
|
items={allFeaturedContent || (featuredContent ? [featuredContent] : [])}
|
||||||
|
|
@ -622,8 +626,8 @@ const HomeScreen = () => {
|
||||||
handleSaveToLibrary={handleSaveToLibrary}
|
handleSaveToLibrary={handleSaveToLibrary}
|
||||||
loading={featuredLoading}
|
loading={featuredLoading}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
), [settings.heroStyle, showHeroSection, featuredContentSource, featuredContent, allFeaturedContent, isSaved, handleSaveToLibrary]);
|
}, [settings.heroStyle, showHeroSection, featuredContentSource, featuredContent, allFeaturedContent, isSaved, handleSaveToLibrary]);
|
||||||
|
|
||||||
const memoizedThisWeekSection = useMemo(() => <ThisWeekSection />, []);
|
const memoizedThisWeekSection = useMemo(() => <ThisWeekSection />, []);
|
||||||
const memoizedContinueWatchingSection = useMemo(() => <ContinueWatchingSection ref={continueWatchingRef} />, []);
|
const memoizedContinueWatchingSection = useMemo(() => <ContinueWatchingSection ref={continueWatchingRef} />, []);
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,8 @@ import {
|
||||||
StatusBar,
|
StatusBar,
|
||||||
Platform,
|
Platform,
|
||||||
useColorScheme,
|
useColorScheme,
|
||||||
Animated
|
Animated,
|
||||||
|
Dimensions
|
||||||
} from 'react-native';
|
} from 'react-native';
|
||||||
import { useSettings } from '../hooks/useSettings';
|
import { useSettings } from '../hooks/useSettings';
|
||||||
import { useNavigation } from '@react-navigation/native';
|
import { useNavigation } from '@react-navigation/native';
|
||||||
|
|
@ -60,6 +61,8 @@ const SettingItem: React.FC<SettingItemProps> = ({
|
||||||
isDarkMode,
|
isDarkMode,
|
||||||
colors
|
colors
|
||||||
}) => {
|
}) => {
|
||||||
|
const isTabletDevice = Platform.OS !== 'web' && (Dimensions.get('window').width >= 768);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TouchableOpacity
|
<TouchableOpacity
|
||||||
activeOpacity={onPress ? 0.7 : 1}
|
activeOpacity={onPress ? 0.7 : 1}
|
||||||
|
|
@ -310,7 +313,7 @@ const HomeScreenSettings: React.FC = () => {
|
||||||
)}
|
)}
|
||||||
</SettingsCard>
|
</SettingsCard>
|
||||||
|
|
||||||
{settings.showHeroSection && (
|
{settings.showHeroSection && !(Dimensions.get('window').width >= 768) && (
|
||||||
<>
|
<>
|
||||||
<View style={styles.segmentCard}>
|
<View style={styles.segmentCard}>
|
||||||
<Text style={[styles.segmentTitle, { color: isDarkMode ? colors.mediumEmphasis : colors.textMutedDark }]}>Hero Layout</Text>
|
<Text style={[styles.segmentTitle, { color: isDarkMode ? colors.mediumEmphasis : colors.textMutedDark }]}>Hero Layout</Text>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue