mirror of
https://github.com/tapframe/NuvioStreaming.git
synced 2026-04-20 16:22:04 +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;
|
const ANDROID_STATUSBAR_HEIGHT = StatusBar.currentHeight || 0;
|
||||||
|
|
||||||
// Screen dimensions and grid layout
|
|
||||||
const { width } = Dimensions.get('window');
|
|
||||||
|
|
||||||
// Dynamic column calculation based on screen width
|
// Dynamic column calculation based on screen width
|
||||||
const calculateCatalogLayout = (screenWidth: number) => {
|
const calculateCatalogLayout = (screenWidth: number) => {
|
||||||
const MIN_ITEM_WIDTH = 120; // Increased minimum for better readability
|
const MIN_ITEM_WIDTH = 120;
|
||||||
const MAX_ITEM_WIDTH = 160; // Adjusted maximum
|
const MAX_ITEM_WIDTH = 180; // Increased for tablets
|
||||||
const HORIZONTAL_PADDING = SPACING.lg * 2; // Total horizontal padding
|
const HORIZONTAL_PADDING = SPACING.lg * 2;
|
||||||
const ITEM_SPACING = SPACING.sm; // Space between items
|
const ITEM_SPACING = SPACING.sm;
|
||||||
|
|
||||||
// Calculate how many columns can fit
|
// Calculate how many columns can fit
|
||||||
const availableWidth = screenWidth - HORIZONTAL_PADDING;
|
const availableWidth = screenWidth - HORIZONTAL_PADDING;
|
||||||
const maxColumns = Math.floor(availableWidth / (MIN_ITEM_WIDTH + ITEM_SPACING));
|
const maxColumns = Math.floor(availableWidth / (MIN_ITEM_WIDTH + ITEM_SPACING));
|
||||||
|
|
||||||
// Limit to reasonable number of columns (2-4 for better UX)
|
// More flexible column limits for different screen sizes
|
||||||
const numColumns = Math.min(Math.max(maxColumns, 2), 4);
|
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
|
// Calculate actual item width with proper spacing
|
||||||
const totalSpacing = ITEM_SPACING * (numColumns - 1);
|
const totalSpacing = ITEM_SPACING * (numColumns - 1);
|
||||||
const itemWidth = (availableWidth - totalSpacing) / numColumns;
|
const itemWidth = (availableWidth - totalSpacing) / numColumns;
|
||||||
|
|
||||||
// For 2 columns, ensure we use the full available width
|
// Ensure item width doesn't exceed maximum
|
||||||
const finalItemWidth = numColumns === 2 ? itemWidth : Math.min(itemWidth, MAX_ITEM_WIDTH);
|
const finalItemWidth = Math.min(itemWidth, MAX_ITEM_WIDTH);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
numColumns,
|
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
|
// Create a styles creator function that accepts the theme colors
|
||||||
const createStyles = (colors: any) => StyleSheet.create({
|
const createStyles = (colors: any) => StyleSheet.create({
|
||||||
container: {
|
container: {
|
||||||
|
|
@ -85,6 +90,10 @@ const createStyles = (colors: any) => StyleSheet.create({
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
paddingHorizontal: 16,
|
paddingHorizontal: 16,
|
||||||
paddingTop: Platform.OS === 'android' ? ANDROID_STATUSBAR_HEIGHT + 8 : 8,
|
paddingTop: Platform.OS === 'android' ? ANDROID_STATUSBAR_HEIGHT + 8 : 8,
|
||||||
|
// Center header on very wide screens
|
||||||
|
alignSelf: 'center',
|
||||||
|
maxWidth: 1400,
|
||||||
|
width: '100%',
|
||||||
},
|
},
|
||||||
backButton: {
|
backButton: {
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
|
|
@ -103,10 +112,18 @@ const createStyles = (colors: any) => StyleSheet.create({
|
||||||
paddingHorizontal: 16,
|
paddingHorizontal: 16,
|
||||||
paddingBottom: 16,
|
paddingBottom: 16,
|
||||||
paddingTop: 8,
|
paddingTop: 8,
|
||||||
|
// Center title on very wide screens
|
||||||
|
alignSelf: 'center',
|
||||||
|
maxWidth: 1400,
|
||||||
|
width: '100%',
|
||||||
},
|
},
|
||||||
list: {
|
list: {
|
||||||
padding: SPACING.lg,
|
padding: SPACING.lg,
|
||||||
paddingTop: SPACING.sm,
|
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: {
|
item: {
|
||||||
marginBottom: SPACING.lg,
|
marginBottom: SPACING.lg,
|
||||||
|
|
@ -162,6 +179,10 @@ const createStyles = (colors: any) => StyleSheet.create({
|
||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
padding: SPACING.xl,
|
padding: SPACING.xl,
|
||||||
|
// Center content on very wide screens
|
||||||
|
alignSelf: 'center',
|
||||||
|
maxWidth: 600, // Narrower max width for centered content
|
||||||
|
width: '100%',
|
||||||
},
|
},
|
||||||
emptyText: {
|
emptyText: {
|
||||||
color: colors.white,
|
color: colors.white,
|
||||||
|
|
@ -195,12 +216,31 @@ const CatalogScreen: React.FC<CatalogScreenProps> = ({ route, navigation }) => {
|
||||||
const [error, setError] = useState<string | null>(null);
|
const [error, setError] = useState<string | null>(null);
|
||||||
const [dataSource, setDataSource] = useState<DataSource>(DataSource.STREMIO_ADDONS);
|
const [dataSource, setDataSource] = useState<DataSource>(DataSource.STREMIO_ADDONS);
|
||||||
const [actualCatalogName, setActualCatalogName] = useState<string | null>(null);
|
const [actualCatalogName, setActualCatalogName] = useState<string | null>(null);
|
||||||
|
const [screenData, setScreenData] = useState(() => {
|
||||||
|
const { width } = Dimensions.get('window');
|
||||||
|
return {
|
||||||
|
width,
|
||||||
|
...calculateCatalogLayout(width)
|
||||||
|
};
|
||||||
|
});
|
||||||
const { currentTheme } = useTheme();
|
const { currentTheme } = useTheme();
|
||||||
const colors = currentTheme.colors;
|
const colors = currentTheme.colors;
|
||||||
const styles = createStyles(colors);
|
const styles = createStyles(colors);
|
||||||
const isDarkMode = true;
|
const isDarkMode = true;
|
||||||
const isInitialRender = React.useRef(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();
|
const { getCustomName, isLoadingCustomNames } = useCustomCatalogNames();
|
||||||
|
|
||||||
// Create display name with proper type suffix
|
// 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 }) => {
|
const renderItem = useCallback(({ item, index }: { item: Meta; index: number }) => {
|
||||||
// Calculate if this is the last item in a row
|
// Calculate if this is the last item in a row
|
||||||
const isLastInRow = (index + 1) % NUM_COLUMNS === 0;
|
const isLastInRow = (index + 1) % screenData.numColumns === 0;
|
||||||
// For 2-column layout, ensure proper spacing
|
// For proper spacing
|
||||||
const rightMargin = isLastInRow ? 0 : SPACING.sm;
|
const rightMargin = isLastInRow ? 0 : SPACING.sm;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
@ -514,8 +554,7 @@ const CatalogScreen: React.FC<CatalogScreenProps> = ({ route, navigation }) => {
|
||||||
styles.item,
|
styles.item,
|
||||||
{
|
{
|
||||||
marginRight: rightMargin,
|
marginRight: rightMargin,
|
||||||
// For 2 columns, ensure items fill the available space properly
|
width: screenData.itemWidth
|
||||||
width: NUM_COLUMNS === 2 ? ITEM_WIDTH : ITEM_WIDTH
|
|
||||||
}
|
}
|
||||||
]}
|
]}
|
||||||
onPress={() => navigation.navigate('Metadata', { id: item.id, type: item.type, addonId })}
|
onPress={() => navigation.navigate('Metadata', { id: item.id, type: item.type, addonId })}
|
||||||
|
|
@ -542,7 +581,7 @@ const CatalogScreen: React.FC<CatalogScreenProps> = ({ route, navigation }) => {
|
||||||
</View>
|
</View>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
);
|
);
|
||||||
}, [navigation, styles, NUM_COLUMNS, ITEM_WIDTH]);
|
}, [navigation, styles, screenData.numColumns, screenData.itemWidth]);
|
||||||
|
|
||||||
const renderEmptyState = () => (
|
const renderEmptyState = () => (
|
||||||
<View style={styles.centered}>
|
<View style={styles.centered}>
|
||||||
|
|
@ -640,8 +679,8 @@ const CatalogScreen: React.FC<CatalogScreenProps> = ({ route, navigation }) => {
|
||||||
data={items}
|
data={items}
|
||||||
renderItem={renderItem}
|
renderItem={renderItem}
|
||||||
keyExtractor={(item) => `${item.id}-${item.type}`}
|
keyExtractor={(item) => `${item.id}-${item.type}`}
|
||||||
numColumns={NUM_COLUMNS}
|
numColumns={screenData.numColumns}
|
||||||
key={NUM_COLUMNS}
|
key={screenData.numColumns}
|
||||||
refreshControl={
|
refreshControl={
|
||||||
<RefreshControl
|
<RefreshControl
|
||||||
refreshing={refreshing}
|
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 { Stream } from '../types/metadata';
|
||||||
import { tmdbService } from '../services/tmdbService';
|
import { tmdbService } from '../services/tmdbService';
|
||||||
import { stremioService } from '../services/stremioService';
|
import { stremioService } from '../services/stremioService';
|
||||||
|
import { localScraperService } from '../services/localScraperService';
|
||||||
import { VideoPlayerService } from '../services/videoPlayerService';
|
import { VideoPlayerService } from '../services/videoPlayerService';
|
||||||
import { useSettings } from '../hooks/useSettings';
|
import { useSettings } from '../hooks/useSettings';
|
||||||
import QualityBadge from '../components/metadata/QualityBadge';
|
import QualityBadge from '../components/metadata/QualityBadge';
|
||||||
|
|
@ -365,7 +366,12 @@ export const StreamsScreen = () => {
|
||||||
const checkProviders = async () => {
|
const checkProviders = async () => {
|
||||||
// Check for Stremio addons
|
// Check for Stremio addons
|
||||||
const hasStremioProviders = await stremioService.hasStreamProviders();
|
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;
|
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