diff --git a/src/components/home/ContentItem.tsx b/src/components/home/ContentItem.tsx index b222903..8c1ea5e 100644 --- a/src/components/home/ContentItem.tsx +++ b/src/components/home/ContentItem.tsx @@ -1,5 +1,5 @@ import React, { useState, useEffect, useCallback } from 'react'; -import { View, TouchableOpacity, ActivityIndicator, StyleSheet, Dimensions, Platform } from 'react-native'; +import { View, TouchableOpacity, ActivityIndicator, StyleSheet, Dimensions, Platform, Text } from 'react-native'; import { Image as ExpoImage } from 'expo-image'; import { MaterialIcons } from '@expo/vector-icons'; import { useTheme } from '../../contexts/ThemeContext'; @@ -90,54 +90,59 @@ const ContentItem = React.memo(({ item, onPress }: ContentItemProps) => { return ( <> - - - { - setImageLoaded(false); - setImageError(false); - }} - onLoadEnd={() => setImageLoaded(true)} - onError={() => { - setImageError(true); - setImageLoaded(true); - }} - /> - {(!imageLoaded || imageError) && ( - - {!imageError ? ( - - ) : ( - - )} - - )} - {isWatched && ( - - - - )} - {item.inLibrary && ( - - - - )} - - + + + + { + setImageLoaded(false); + setImageError(false); + }} + onLoadEnd={() => setImageLoaded(true)} + onError={() => { + setImageError(true); + setImageLoaded(true); + }} + /> + {(!imageLoaded || imageError) && ( + + {!imageError ? ( + + ) : ( + + )} + + )} + {isWatched && ( + + + + )} + {item.inLibrary && ( + + + + )} + + + + {item.name} + + { }); const styles = StyleSheet.create({ + itemContainer: { + width: POSTER_WIDTH, + }, contentItem: { width: POSTER_WIDTH, aspectRatio: 2/3, @@ -164,6 +172,7 @@ const styles = StyleSheet.create({ shadowRadius: 6, borderWidth: 0.5, borderColor: 'rgba(255,255,255,0.12)', + marginBottom: 8, }, contentItemContainer: { width: '100%', @@ -201,6 +210,13 @@ const styles = StyleSheet.create({ borderRadius: 8, padding: 4, }, + title: { + fontSize: 14, + fontWeight: '500', + marginTop: 4, + textAlign: 'center', + fontFamily: 'SpaceMono-Regular', + } }); export default ContentItem; \ No newline at end of file diff --git a/src/screens/CatalogScreen.tsx b/src/screens/CatalogScreen.tsx index e80afcc..3612aa4 100644 --- a/src/screens/CatalogScreen.tsx +++ b/src/screens/CatalogScreen.tsx @@ -188,6 +188,7 @@ const CatalogScreen: React.FC = ({ route, navigation }) => { const { addonId, type, id, name: originalName, genreFilter } = route.params; const [items, setItems] = useState([]); const [loading, setLoading] = useState(true); + const [paginating, setPaginating] = useState(false); const [refreshing, setRefreshing] = useState(false); const [page, setPage] = useState(1); const [hasMore, setHasMore] = useState(true); @@ -198,6 +199,7 @@ const CatalogScreen: React.FC = ({ route, navigation }) => { const colors = currentTheme.colors; const styles = createStyles(colors); const isDarkMode = true; + const isInitialRender = React.useRef(true); const { getCustomName, isLoadingCustomNames } = useCustomCatalogNames(); @@ -262,7 +264,10 @@ const CatalogScreen: React.FC = ({ route, navigation }) => { try { if (shouldRefresh) { setRefreshing(true); - } else if (pageNum === 1) { + setHasMore(true); // Reset hasMore on refresh + } else if (pageNum > 1) { + setPaginating(true); + } else { setLoading(true); } @@ -360,6 +365,7 @@ const CatalogScreen: React.FC = ({ route, navigation }) => { setHasMore(false); } else { foundItems = true; + setHasMore(true); // Ensure hasMore is true if we found items } if (shouldRefresh || pageNum === 1) { @@ -442,8 +448,11 @@ const CatalogScreen: React.FC = ({ route, navigation }) => { index === self.findIndex((t) => t.id === item.id) ); - if (uniqueItems.length === 0) { + if (uniqueItems.length === 0 && allItems.length === 0) { setHasMore(false); + } else { + foundItems = true; + setHasMore(true); // Ensure hasMore is true if we found items } if (shouldRefresh || pageNum === 1) { @@ -467,25 +476,31 @@ const CatalogScreen: React.FC = ({ route, navigation }) => { } finally { setLoading(false); setRefreshing(false); + setPaginating(false); } }, [addonId, type, id, genreFilter, dataSource]); useEffect(() => { - loadItems(1); + loadItems(1, true); }, [loadItems]); const handleRefresh = useCallback(() => { setPage(1); + setItems([]); // Clear items on refresh loadItems(1, true); }, [loadItems]); const handleLoadMore = useCallback(() => { - if (!loading && hasMore) { + if (isInitialRender.current) { + isInitialRender.current = false; + return; + } + if (!loading && !paginating && hasMore && !refreshing) { const nextPage = page + 1; setPage(nextPage); loadItems(nextPage); } - }, [loading, hasMore, page, loadItems]); + }, [loading, paginating, hasMore, page, loadItems, refreshing]); const renderItem = useCallback(({ item, index }: { item: Meta; index: number }) => { // Calculate if this is the last item in a row @@ -638,7 +653,7 @@ const CatalogScreen: React.FC = ({ route, navigation }) => { onEndReached={handleLoadMore} onEndReachedThreshold={0.5} ListFooterComponent={ - loading && items.length > 0 ? ( + paginating ? (