diff --git a/app/(auth)/(tabs)/(home)/downloads/[seriesId].tsx b/app/(auth)/(tabs)/(home)/downloads/[seriesId].tsx index 97c73bdf..95baee58 100644 --- a/app/(auth)/(tabs)/(home)/downloads/[seriesId].tsx +++ b/app/(auth)/(tabs)/(home)/downloads/[seriesId].tsx @@ -23,12 +23,12 @@ export default function page() { const [seasonIndexState, setSeasonIndexState] = useState( {}, ); - const { getDownloadedItems, deleteItems } = useDownload(); + const { downloadedItems, deleteItems } = useDownload(); const series = useMemo(() => { try { return ( - getDownloadedItems() + downloadedItems ?.filter((f) => f.item.SeriesId === seriesId) ?.sort( (a, b) => a?.item.ParentIndexNumber! - b.item.ParentIndexNumber!, @@ -37,7 +37,7 @@ export default function page() { } catch { return []; } - }, [getDownloadedItems]); + }, [downloadedItems, seriesId]); // Group episodes by season in a single pass const seasonGroups = useMemo(() => { diff --git a/app/(auth)/(tabs)/(home)/downloads/index.tsx b/app/(auth)/(tabs)/(home)/downloads/index.tsx index 2c68ac01..1fbf4319 100644 --- a/app/(auth)/(tabs)/(home)/downloads/index.tsx +++ b/app/(auth)/(tabs)/(home)/downloads/index.tsx @@ -18,10 +18,7 @@ import ActiveDownloads from "@/components/downloads/ActiveDownloads"; import { DownloadSize } from "@/components/downloads/DownloadSize"; import { MovieCard } from "@/components/downloads/MovieCard"; import { SeriesCard } from "@/components/downloads/SeriesCard"; -import { - downloadsRefreshAtom, - useDownload, -} from "@/providers/DownloadProvider"; +import { useDownload } from "@/providers/DownloadProvider"; import { type DownloadedItem } from "@/providers/Downloads/types"; import { queueAtom } from "@/utils/atoms/queue"; import { writeToLog } from "@/utils/log"; @@ -30,13 +27,8 @@ export default function page() { const navigation = useNavigation(); const { t } = useTranslation(); const [queue, setQueue] = useAtom(queueAtom); - const [refreshKey] = useAtom(downloadsRefreshAtom); - const { - removeProcess, - getDownloadedItems, - deleteFileByType, - deleteAllFiles, - } = useDownload(); + const { removeProcess, downloadedItems, deleteFileByType, deleteAllFiles } = + useDownload(); const router = useRouter(); const bottomSheetModalRef = useRef(null); @@ -66,10 +58,7 @@ export default function page() { ); }; - const downloadedFiles = useMemo( - () => getDownloadedItems(), - [getDownloadedItems, refreshKey], - ); + const downloadedFiles = downloadedItems; const movies = useMemo(() => { try { diff --git a/components/DownloadItem.tsx b/components/DownloadItem.tsx index 9dd2f13b..99aa9ff9 100644 --- a/components/DownloadItem.tsx +++ b/components/DownloadItem.tsx @@ -64,12 +64,8 @@ export const DownloadItems: React.FC = ({ const { settings } = useSettings(); const [downloadUnwatchedOnly, setDownloadUnwatchedOnly] = useState(false); - const { processes, startBackgroundDownload, getDownloadedItems } = - useDownload(); - const downloadedFiles = useMemo( - () => getDownloadedItems(), - [getDownloadedItems], - ); + const { processes, startBackgroundDownload, downloadedItems } = useDownload(); + const downloadedFiles = downloadedItems; const [selectedOptions, setSelectedOptions] = useState< SelectedOptions | undefined diff --git a/components/downloads/DownloadCard.tsx b/components/downloads/DownloadCard.tsx index ded59848..6d0682a4 100644 --- a/components/downloads/DownloadCard.tsx +++ b/components/downloads/DownloadCard.tsx @@ -119,18 +119,24 @@ export const DownloadCard = ({ process, ...props }: DownloadCardProps) => { {/* Action buttons in bottom right corner */} {process.status === "downloading" && Platform.OS !== "ios" && ( - handlePause()} className='p-1'> + handlePause()} + className='p-2 bg-neutral-800 rounded-full' + > )} {process.status === "paused" && Platform.OS !== "ios" && ( - handleResume()} className='p-1'> + handleResume()} + className='p-2 bg-neutral-800 rounded-full' + > )} handleDelete(process.id)} - className='p-1' + className='p-2 bg-neutral-800 rounded-full' > diff --git a/components/downloads/DownloadSize.tsx b/components/downloads/DownloadSize.tsx index 56ddf1a5..32993f37 100644 --- a/components/downloads/DownloadSize.tsx +++ b/components/downloads/DownloadSize.tsx @@ -13,17 +13,13 @@ export const DownloadSize: React.FC = ({ items, ...props }) => { - const { getDownloadedItemSize, getDownloadedItems } = useDownload(); - const downloadedFiles = useMemo( - () => getDownloadedItems(), - [getDownloadedItems], - ); + const { getDownloadedItemSize, downloadedItems } = useDownload(); const [size, setSize] = useState(); const itemIds = useMemo(() => items.map((i) => i.Id), [items]); useEffect(() => { - if (!downloadedFiles) return; + if (!downloadedItems) return; let s = 0; @@ -35,7 +31,7 @@ export const DownloadSize: React.FC = ({ } } setSize(s.bytesToReadable()); - }, [itemIds]); + }, [itemIds, downloadedItems, getDownloadedItemSize]); const sizeText = useMemo(() => { if (!size) return "..."; diff --git a/components/home/HomeIndex.tsx b/components/home/HomeIndex.tsx index 3c74fd9f..60c08a23 100644 --- a/components/home/HomeIndex.tsx +++ b/components/home/HomeIndex.tsx @@ -72,7 +72,7 @@ export const HomeIndex = () => { const scrollViewRef = useRef(null); - const { getDownloadedItems, cleanCacheDirectory } = useDownload(); + const { downloadedItems, cleanCacheDirectory } = useDownload(); const prevIsConnected = useRef(false); const { isConnected, @@ -92,8 +92,8 @@ export const HomeIndex = () => { const hasDownloads = useMemo(() => { if (Platform.isTV) return false; - return getDownloadedItems().length > 0; - }, [getDownloadedItems]); + return downloadedItems.length > 0; + }, [downloadedItems]); useEffect(() => { if (Platform.isTV) { diff --git a/components/series/SeasonEpisodesCarousel.tsx b/components/series/SeasonEpisodesCarousel.tsx index 8e3051ee..5f69c47d 100644 --- a/components/series/SeasonEpisodesCarousel.tsx +++ b/components/series/SeasonEpisodesCarousel.tsx @@ -28,11 +28,7 @@ export const SeasonEpisodesCarousel: React.FC = ({ }) => { const [api] = useAtom(apiAtom); const [user] = useAtom(userAtom); - const { getDownloadedItems } = useDownload(); - const downloadedFiles = useMemo( - () => getDownloadedItems(), - [getDownloadedItems], - ); + const { downloadedItems } = useDownload(); const scrollRef = useRef(null); @@ -45,10 +41,10 @@ export const SeasonEpisodesCarousel: React.FC = ({ }, [item]); const { data: episodes, isPending } = useQuery({ - queryKey: ["episodes", seasonId, isOffline], + queryKey: ["episodes", seasonId, isOffline, downloadedItems], queryFn: async () => { if (isOffline) { - return downloadedFiles + return downloadedItems ?.filter( (f) => f.item.Type === "Episode" && f.item.SeasonId === seasonId, ) diff --git a/components/video-player/controls/EpisodeList.tsx b/components/video-player/controls/EpisodeList.tsx index 07770357..5dca0c50 100644 --- a/components/video-player/controls/EpisodeList.tsx +++ b/components/video-player/controls/EpisodeList.tsx @@ -55,11 +55,8 @@ export const EpisodeList: React.FC = ({ item, close, goToItem }) => { } }, []); - const { getDownloadedItems } = useDownload(); - const downloadedFiles = useMemo( - () => getDownloadedItems(), - [getDownloadedItems], - ); + const { downloadedItems } = useDownload(); + const downloadedFiles = downloadedItems; const seasonIndex = seasonIndexState[item.ParentId ?? ""]; diff --git a/hooks/usePlaybackManager.ts b/hooks/usePlaybackManager.ts index 5ea237cf..448ecaee 100644 --- a/hooks/usePlaybackManager.ts +++ b/hooks/usePlaybackManager.ts @@ -69,7 +69,7 @@ export const usePlaybackManager = ({ const api = useAtomValue(apiAtom); const user = useAtomValue(userAtom); const { isConnected } = useNetworkStatus(); - const { getDownloadedItemById, updateDownloadedItem, getDownloadedItems } = + const { getDownloadedItemById, updateDownloadedItem, downloadedItems } = useDownload(); /** Whether the device is online. actually it's connected to the internet. */ @@ -77,14 +77,20 @@ export const usePlaybackManager = ({ // Adjacent episodes logic const { data: adjacentItems } = useQuery({ - queryKey: ["adjacentItems", item?.Id, item?.SeriesId, isOffline], + queryKey: [ + "adjacentItems", + item?.Id, + item?.SeriesId, + isOffline, + downloadedItems, + ], queryFn: async (): Promise => { if (!item || !item.SeriesId) { return null; } if (isOffline) { - return getOfflineAdjacentItems(item, getDownloadedItems() || []); + return getOfflineAdjacentItems(item, downloadedItems || []); } if (!api) { diff --git a/providers/DownloadProvider.tsx b/providers/DownloadProvider.tsx index 491f28fd..a4d25667 100644 --- a/providers/DownloadProvider.tsx +++ b/providers/DownloadProvider.tsx @@ -25,12 +25,17 @@ const DownloadContext = createContext(processesAtom); - const [, setRefreshKey] = useAtom(downloadsRefreshAtom); + const [refreshKey, setRefreshKey] = useAtom(downloadsRefreshAtom); const successHapticFeedback = useHaptic("success"); // Track task ID to process ID mapping const taskMapRef = useRef>(new Map()); + // Reactive downloaded items that updates when refreshKey changes + const downloadedItems = useMemo(() => { + return getAllDownloadedItems(); + }, [refreshKey]); + // Trigger refresh of download lists const triggerRefresh = useCallback(() => { setRefreshKey((prev) => prev + 1); @@ -114,7 +119,8 @@ function useDownloadProvider() { return { processes, startBackgroundDownload, - getDownloadedItems: getAllDownloadedItems, + downloadedItems, // Reactive value that auto-updates + getDownloadedItems: getAllDownloadedItems, // Keep for backward compatibility getDownloadsDatabase, deleteAllFiles, deleteFile, @@ -144,6 +150,7 @@ export function useDownload() { return { processes: [], startBackgroundDownload: async () => {}, + downloadedItems: [], getDownloadedItems: () => [], getDownloadsDatabase: () => ({ movies: {}, series: {}, other: {} }), deleteAllFiles: async () => {},