From 49e9b213bc7bc919056feb0c70ebd42cfe1c8ba6 Mon Sep 17 00:00:00 2001 From: tapframe Date: Sun, 27 Jul 2025 19:10:22 +0530 Subject: [PATCH] ffixes --- src/screens/CatalogScreen.tsx | 87 +++++++++++++++++++++++++---------- src/screens/StreamsScreen.tsx | 10 +++- 2 files changed, 71 insertions(+), 26 deletions(-) diff --git a/src/screens/CatalogScreen.tsx b/src/screens/CatalogScreen.tsx index 3612aa4e..4e20a6a0 100644 --- a/src/screens/CatalogScreen.tsx +++ b/src/screens/CatalogScreen.tsx @@ -39,29 +39,39 @@ const SPACING = { const ANDROID_STATUSBAR_HEIGHT = StatusBar.currentHeight || 0; -// Screen dimensions and grid layout -const { width } = Dimensions.get('window'); - // Dynamic column calculation based on screen width const calculateCatalogLayout = (screenWidth: number) => { - const MIN_ITEM_WIDTH = 120; // Increased minimum for better readability - const MAX_ITEM_WIDTH = 160; // Adjusted maximum - const HORIZONTAL_PADDING = SPACING.lg * 2; // Total horizontal padding - const ITEM_SPACING = SPACING.sm; // Space between items + const MIN_ITEM_WIDTH = 120; + const MAX_ITEM_WIDTH = 180; // Increased for tablets + const HORIZONTAL_PADDING = SPACING.lg * 2; + const ITEM_SPACING = SPACING.sm; // Calculate how many columns can fit const availableWidth = screenWidth - HORIZONTAL_PADDING; const maxColumns = Math.floor(availableWidth / (MIN_ITEM_WIDTH + ITEM_SPACING)); - // Limit to reasonable number of columns (2-4 for better UX) - const numColumns = Math.min(Math.max(maxColumns, 2), 4); + // More flexible column limits for different screen sizes + let numColumns; + if (screenWidth < 600) { + // Phone: 2-3 columns + numColumns = Math.min(Math.max(maxColumns, 2), 3); + } else if (screenWidth < 900) { + // Small tablet: 3-5 columns + numColumns = Math.min(Math.max(maxColumns, 3), 5); + } else if (screenWidth < 1200) { + // Large tablet: 4-6 columns + numColumns = Math.min(Math.max(maxColumns, 4), 6); + } else { + // Very large screens: 5-8 columns + numColumns = Math.min(Math.max(maxColumns, 5), 8); + } // Calculate actual item width with proper spacing const totalSpacing = ITEM_SPACING * (numColumns - 1); const itemWidth = (availableWidth - totalSpacing) / numColumns; - // For 2 columns, ensure we use the full available width - const finalItemWidth = numColumns === 2 ? itemWidth : Math.min(itemWidth, MAX_ITEM_WIDTH); + // Ensure item width doesn't exceed maximum + const finalItemWidth = Math.min(itemWidth, MAX_ITEM_WIDTH); return { numColumns, @@ -69,11 +79,6 @@ const calculateCatalogLayout = (screenWidth: number) => { }; }; -const catalogLayout = calculateCatalogLayout(width); -const NUM_COLUMNS = catalogLayout.numColumns; -const ITEM_MARGIN = SPACING.sm; -const ITEM_WIDTH = catalogLayout.itemWidth; - // Create a styles creator function that accepts the theme colors const createStyles = (colors: any) => StyleSheet.create({ container: { @@ -85,6 +90,10 @@ const createStyles = (colors: any) => StyleSheet.create({ alignItems: 'center', paddingHorizontal: 16, paddingTop: Platform.OS === 'android' ? ANDROID_STATUSBAR_HEIGHT + 8 : 8, + // Center header on very wide screens + alignSelf: 'center', + maxWidth: 1400, + width: '100%', }, backButton: { flexDirection: 'row', @@ -103,10 +112,18 @@ const createStyles = (colors: any) => StyleSheet.create({ paddingHorizontal: 16, paddingBottom: 16, paddingTop: 8, + // Center title on very wide screens + alignSelf: 'center', + maxWidth: 1400, + width: '100%', }, list: { padding: SPACING.lg, paddingTop: SPACING.sm, + // Center content on very wide screens + alignSelf: 'center', + maxWidth: 1400, // Prevent content from being too wide on large screens + width: '100%', }, item: { marginBottom: SPACING.lg, @@ -162,6 +179,10 @@ const createStyles = (colors: any) => StyleSheet.create({ justifyContent: 'center', alignItems: 'center', padding: SPACING.xl, + // Center content on very wide screens + alignSelf: 'center', + maxWidth: 600, // Narrower max width for centered content + width: '100%', }, emptyText: { color: colors.white, @@ -195,12 +216,31 @@ const CatalogScreen: React.FC = ({ route, navigation }) => { const [error, setError] = useState(null); const [dataSource, setDataSource] = useState(DataSource.STREMIO_ADDONS); const [actualCatalogName, setActualCatalogName] = useState(null); + const [screenData, setScreenData] = useState(() => { + const { width } = Dimensions.get('window'); + return { + width, + ...calculateCatalogLayout(width) + }; + }); const { currentTheme } = useTheme(); const colors = currentTheme.colors; const styles = createStyles(colors); const isDarkMode = true; const isInitialRender = React.useRef(true); + // Handle screen dimension changes + useEffect(() => { + const subscription = Dimensions.addEventListener('change', ({ window }) => { + setScreenData({ + width: window.width, + ...calculateCatalogLayout(window.width) + }); + }); + + return () => subscription?.remove(); + }, []); + const { getCustomName, isLoadingCustomNames } = useCustomCatalogNames(); // Create display name with proper type suffix @@ -504,8 +544,8 @@ const CatalogScreen: React.FC = ({ route, navigation }) => { const renderItem = useCallback(({ item, index }: { item: Meta; index: number }) => { // Calculate if this is the last item in a row - const isLastInRow = (index + 1) % NUM_COLUMNS === 0; - // For 2-column layout, ensure proper spacing + const isLastInRow = (index + 1) % screenData.numColumns === 0; + // For proper spacing const rightMargin = isLastInRow ? 0 : SPACING.sm; return ( @@ -514,8 +554,7 @@ const CatalogScreen: React.FC = ({ route, navigation }) => { styles.item, { marginRight: rightMargin, - // For 2 columns, ensure items fill the available space properly - width: NUM_COLUMNS === 2 ? ITEM_WIDTH : ITEM_WIDTH + width: screenData.itemWidth } ]} onPress={() => navigation.navigate('Metadata', { id: item.id, type: item.type, addonId })} @@ -542,7 +581,7 @@ const CatalogScreen: React.FC = ({ route, navigation }) => { ); - }, [navigation, styles, NUM_COLUMNS, ITEM_WIDTH]); + }, [navigation, styles, screenData.numColumns, screenData.itemWidth]); const renderEmptyState = () => ( @@ -640,8 +679,8 @@ const CatalogScreen: React.FC = ({ route, navigation }) => { data={items} renderItem={renderItem} keyExtractor={(item) => `${item.id}-${item.type}`} - numColumns={NUM_COLUMNS} - key={NUM_COLUMNS} + numColumns={screenData.numColumns} + key={screenData.numColumns} refreshControl={ = ({ route, navigation }) => { ); }; -export default CatalogScreen; \ No newline at end of file +export default CatalogScreen; \ No newline at end of file diff --git a/src/screens/StreamsScreen.tsx b/src/screens/StreamsScreen.tsx index 8ddbc767..01bb587e 100644 --- a/src/screens/StreamsScreen.tsx +++ b/src/screens/StreamsScreen.tsx @@ -29,6 +29,7 @@ import { useTheme } from '../contexts/ThemeContext'; import { Stream } from '../types/metadata'; import { tmdbService } from '../services/tmdbService'; import { stremioService } from '../services/stremioService'; +import { localScraperService } from '../services/localScraperService'; import { VideoPlayerService } from '../services/videoPlayerService'; import { useSettings } from '../hooks/useSettings'; import QualityBadge from '../components/metadata/QualityBadge'; @@ -365,7 +366,12 @@ export const StreamsScreen = () => { const checkProviders = async () => { // Check for Stremio addons const hasStremioProviders = await stremioService.hasStreamProviders(); - const hasProviders = hasStremioProviders; + + // Check for local scrapers (only if enabled in settings) + const hasLocalScrapers = settings.enableLocalScrapers && await localScraperService.hasScrapers(); + + // We have providers if we have either Stremio addons OR enabled local scrapers + const hasProviders = hasStremioProviders || hasLocalScrapers; if (!isMounted.current) return; @@ -1648,4 +1654,4 @@ const createStyles = (colors: any) => StyleSheet.create({ }, }); -export default memo(StreamsScreen); \ No newline at end of file +export default memo(StreamsScreen); \ No newline at end of file