mirror of
https://github.com/tapframe/NuvioStreaming.git
synced 2026-03-11 17:45:38 +00:00
ffixes
This commit is contained in:
parent
2180453a16
commit
49e9b213bc
2 changed files with 71 additions and 26 deletions
|
|
@ -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<CatalogScreenProps> = ({ route, navigation }) => {
|
|||
const [error, setError] = useState<string | null>(null);
|
||||
const [dataSource, setDataSource] = useState<DataSource>(DataSource.STREMIO_ADDONS);
|
||||
const [actualCatalogName, setActualCatalogName] = useState<string | null>(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<CatalogScreenProps> = ({ 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<CatalogScreenProps> = ({ 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<CatalogScreenProps> = ({ route, navigation }) => {
|
|||
</View>
|
||||
</TouchableOpacity>
|
||||
);
|
||||
}, [navigation, styles, NUM_COLUMNS, ITEM_WIDTH]);
|
||||
}, [navigation, styles, screenData.numColumns, screenData.itemWidth]);
|
||||
|
||||
const renderEmptyState = () => (
|
||||
<View style={styles.centered}>
|
||||
|
|
@ -640,8 +679,8 @@ const CatalogScreen: React.FC<CatalogScreenProps> = ({ 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={
|
||||
<RefreshControl
|
||||
refreshing={refreshing}
|
||||
|
|
@ -667,4 +706,4 @@ const CatalogScreen: React.FC<CatalogScreenProps> = ({ route, navigation }) => {
|
|||
);
|
||||
};
|
||||
|
||||
export default CatalogScreen;
|
||||
export default CatalogScreen;
|
||||
|
|
@ -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);
|
||||
export default memo(StreamsScreen);
|
||||
Loading…
Reference in a new issue