mirror of
https://github.com/tapframe/NuvioStreaming.git
synced 2026-04-13 13:10:56 +00:00
UI fixes
This commit is contained in:
parent
213fbbbb4e
commit
e3b86bcc90
3 changed files with 84 additions and 8 deletions
|
|
@ -3,6 +3,7 @@ import { View, TouchableOpacity, ActivityIndicator, StyleSheet, Dimensions, Plat
|
|||
import { Image as ExpoImage } from 'expo-image';
|
||||
import { MaterialIcons } from '@expo/vector-icons';
|
||||
import { useTheme } from '../../contexts/ThemeContext';
|
||||
import { useSettings } from '../../hooks/useSettings';
|
||||
import { catalogService, StreamingContent } from '../../services/catalogService';
|
||||
import { DropUpMenu } from './DropUpMenu';
|
||||
|
||||
|
|
@ -63,6 +64,18 @@ const ContentItem = ({ item, onPress }: ContentItemProps) => {
|
|||
const [shouldLoadImage, setShouldLoadImage] = useState(false);
|
||||
const [retryCount, setRetryCount] = useState(0);
|
||||
const { currentTheme } = useTheme();
|
||||
const { settings } = useSettings();
|
||||
const posterRadius = typeof settings.posterBorderRadius === 'number' ? settings.posterBorderRadius : 12;
|
||||
const posterWidth = React.useMemo(() => {
|
||||
switch (settings.posterSize) {
|
||||
case 'small':
|
||||
return Math.max(100, Math.min(POSTER_WIDTH - 10, POSTER_WIDTH));
|
||||
case 'large':
|
||||
return Math.min(POSTER_WIDTH + 20, POSTER_WIDTH + 30);
|
||||
default:
|
||||
return POSTER_WIDTH;
|
||||
}
|
||||
}, [settings.posterSize]);
|
||||
|
||||
// Intersection observer simulation for lazy loading
|
||||
const itemRef = useRef<View>(null);
|
||||
|
|
@ -135,20 +148,20 @@ const ContentItem = ({ item, onPress }: ContentItemProps) => {
|
|||
|
||||
return (
|
||||
<>
|
||||
<View style={styles.itemContainer}>
|
||||
<View style={[styles.itemContainer, { width: posterWidth }]}>
|
||||
<TouchableOpacity
|
||||
style={styles.contentItem}
|
||||
style={[styles.contentItem, { width: posterWidth, borderRadius: posterRadius }]}
|
||||
activeOpacity={0.7}
|
||||
onPress={handlePress}
|
||||
onLongPress={handleLongPress}
|
||||
delayLongPress={300}
|
||||
>
|
||||
<View ref={itemRef} style={styles.contentItemContainer}>
|
||||
<View ref={itemRef} style={[styles.contentItemContainer, { borderRadius: posterRadius }] }>
|
||||
{/* Only load image when shouldLoadImage is true (lazy loading) */}
|
||||
{shouldLoadImage && item.poster ? (
|
||||
<ExpoImage
|
||||
source={{ uri: getOptimizedPosterUrl(item.poster) }}
|
||||
style={[styles.poster, { backgroundColor: currentTheme.colors.elevation1 }]}
|
||||
style={[styles.poster, { backgroundColor: currentTheme.colors.elevation1, borderRadius: posterRadius }]}
|
||||
contentFit="cover"
|
||||
cachePolicy="memory-disk" // Use both memory and disk cache
|
||||
transition={200} // Add smooth transition
|
||||
|
|
@ -175,7 +188,7 @@ const ContentItem = ({ item, onPress }: ContentItemProps) => {
|
|||
/>
|
||||
) : (
|
||||
// Show placeholder until lazy load triggers
|
||||
<View style={[styles.poster, { backgroundColor: currentTheme.colors.elevation1, justifyContent: 'center', alignItems: 'center' }]}>
|
||||
<View style={[styles.poster, { backgroundColor: currentTheme.colors.elevation1, justifyContent: 'center', alignItems: 'center', borderRadius: posterRadius }] }>
|
||||
<Text style={{ color: currentTheme.colors.textMuted, fontSize: 10, textAlign: 'center' }}>
|
||||
{item.name.substring(0, 20)}...
|
||||
</Text>
|
||||
|
|
@ -198,9 +211,11 @@ const ContentItem = ({ item, onPress }: ContentItemProps) => {
|
|||
)}
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
<Text style={[styles.title, { color: currentTheme.colors.text }]} numberOfLines={2}>
|
||||
{item.name}
|
||||
</Text>
|
||||
{settings.showPosterTitles && (
|
||||
<Text style={[styles.title, { color: currentTheme.colors.text }]} numberOfLines={2}>
|
||||
{item.name}
|
||||
</Text>
|
||||
)}
|
||||
</View>
|
||||
|
||||
<DropUpMenu
|
||||
|
|
|
|||
|
|
@ -65,6 +65,8 @@ export interface AppSettings {
|
|||
posterSize: 'small' | 'medium' | 'large'; // Predefined sizes
|
||||
posterBorderRadius: number; // 0-20 range for border radius
|
||||
postersPerRow: number; // 3-6 range for number of posters per row
|
||||
// Home screen content item
|
||||
showPosterTitles: boolean; // Show text titles under posters
|
||||
// Trailer settings
|
||||
showTrailers: boolean; // Enable/disable trailer playback in hero section
|
||||
trailerMuted: boolean; // Default to muted for better user experience
|
||||
|
|
@ -107,6 +109,7 @@ export const DEFAULT_SETTINGS: AppSettings = {
|
|||
posterSize: 'medium',
|
||||
posterBorderRadius: 12,
|
||||
postersPerRow: 4,
|
||||
showPosterTitles: true,
|
||||
// Trailer settings
|
||||
showTrailers: true, // Enable trailers by default
|
||||
trailerMuted: true, // Default to muted for better user experience
|
||||
|
|
|
|||
|
|
@ -346,6 +346,34 @@ const HomeScreenSettings: React.FC = () => {
|
|||
</>
|
||||
)}
|
||||
|
||||
<SettingsCard isDarkMode={isDarkMode} colors={colors}>
|
||||
<Text style={[styles.cardHeader, { color: isDarkMode ? colors.mediumEmphasis : colors.textMutedDark }]}>Posters</Text>
|
||||
<View style={styles.settingsRowInline}>
|
||||
<Text style={[styles.rowLabel, { color: isDarkMode ? colors.highEmphasis : colors.textDark }]}>Show Titles</Text>
|
||||
<CustomSwitch
|
||||
value={settings.showPosterTitles}
|
||||
onValueChange={(value) => handleUpdateSetting('showPosterTitles', value)}
|
||||
/>
|
||||
</View>
|
||||
<View style={styles.settingsRow}>
|
||||
<Text style={[styles.rowLabel, { color: isDarkMode ? colors.highEmphasis : colors.textDark }]}>Poster Size</Text>
|
||||
<SegmentedControl
|
||||
options={[{ label: 'Small', value: 'small' }, { label: 'Medium', value: 'medium' }, { label: 'Large', value: 'large' }]}
|
||||
value={settings.posterSize}
|
||||
onChange={(val) => handleUpdateSetting('posterSize', val as any)}
|
||||
/>
|
||||
</View>
|
||||
|
||||
<View style={styles.settingsRow}>
|
||||
<Text style={[styles.rowLabel, { color: isDarkMode ? colors.highEmphasis : colors.textDark }]}>Poster Corners</Text>
|
||||
<SegmentedControl
|
||||
options={[{ label: 'Square', value: '0' }, { label: 'Rounded', value: '12' }, { label: 'Pill', value: '20' }]}
|
||||
value={String(settings.posterBorderRadius)}
|
||||
onChange={(val) => handleUpdateSetting('posterBorderRadius', Number(val) as any)}
|
||||
/>
|
||||
</View>
|
||||
</SettingsCard>
|
||||
|
||||
<SectionHeader title="ABOUT THESE SETTINGS" isDarkMode={isDarkMode} colors={colors} />
|
||||
<View style={[styles.infoCard, { backgroundColor: isDarkMode ? colors.elevation1 : 'rgba(0,0,0,0.03)' }]}>
|
||||
<Text style={[styles.infoText, { color: isDarkMode ? colors.mediumEmphasis : colors.textMutedDark }]}>
|
||||
|
|
@ -385,6 +413,7 @@ const styles = StyleSheet.create({
|
|||
},
|
||||
sectionHeader: {
|
||||
paddingHorizontal: 16,
|
||||
marginHorizontal: 16,
|
||||
paddingTop: 20,
|
||||
paddingBottom: 8,
|
||||
},
|
||||
|
|
@ -395,6 +424,8 @@ const styles = StyleSheet.create({
|
|||
},
|
||||
card: {
|
||||
marginHorizontal: 16,
|
||||
marginTop: 12,
|
||||
marginBottom: 12,
|
||||
borderRadius: 12,
|
||||
overflow: 'hidden',
|
||||
shadowColor: '#000',
|
||||
|
|
@ -515,6 +546,7 @@ const styles = StyleSheet.create({
|
|||
segmentCard: {
|
||||
marginHorizontal: 16,
|
||||
marginTop: 12,
|
||||
marginBottom: 12,
|
||||
padding: 16,
|
||||
borderRadius: 12,
|
||||
backgroundColor: 'rgba(255,255,255,0.05)'
|
||||
|
|
@ -539,6 +571,32 @@ const styles = StyleSheet.create({
|
|||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
},
|
||||
settingsRow: {
|
||||
paddingHorizontal: 16,
|
||||
paddingVertical: 12,
|
||||
gap: 8,
|
||||
},
|
||||
settingsRowInline: {
|
||||
paddingHorizontal: 16,
|
||||
paddingVertical: 12,
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
},
|
||||
rowLabel: {
|
||||
fontSize: 14,
|
||||
fontWeight: '600',
|
||||
marginBottom: 4,
|
||||
opacity: 0.9,
|
||||
},
|
||||
cardHeader: {
|
||||
fontSize: 12,
|
||||
fontWeight: '700',
|
||||
letterSpacing: 0.6,
|
||||
paddingHorizontal: 16,
|
||||
paddingTop: 12,
|
||||
opacity: 0.9,
|
||||
},
|
||||
savedIndicator: {
|
||||
position: 'absolute',
|
||||
top: Platform.OS === 'android' ? (StatusBar.currentHeight || 0) + 60 : 90,
|
||||
|
|
|
|||
Loading…
Reference in a new issue