diff --git a/app/(auth)/(tabs)/(home,libraries,search)/series/[id].tsx b/app/(auth)/(tabs)/(home,libraries,search)/series/[id].tsx index e9c9fdea..9b7db729 100644 --- a/app/(auth)/(tabs)/(home,libraries,search)/series/[id].tsx +++ b/app/(auth)/(tabs)/(home,libraries,search)/series/[id].tsx @@ -4,7 +4,7 @@ import { ParallaxScrollView } from "@/components/ParallaxPage"; import { Ratings } from "@/components/Ratings"; import { NextUp } from "@/components/series/NextUp"; import { SeasonPicker } from "@/components/series/SeasonPicker"; -import { SeriesActions } from "@/components/series/SeriesActions"; +import { ItemActions } from "@/components/series/SeriesActions"; import { SeriesHeader } from "@/components/series/SeriesHeader"; import { apiAtom, userAtom } from "@/providers/JellyfinProvider"; import { getBackdropUrl } from "@/utils/jellyfin/image/getBackdropUrl"; diff --git a/app/(auth)/trailer/page.tsx b/app/(auth)/trailer/page.tsx index c2a84809..abcf6352 100644 --- a/app/(auth)/trailer/page.tsx +++ b/app/(auth)/trailer/page.tsx @@ -1,12 +1,10 @@ -import { useGlobalSearchParams, useNavigation } from "expo-router"; -import { useState, useCallback, useEffect, useMemo } from "react"; -import { Button, Dimensions } from "react-native"; -import { Alert, View } from "react-native"; +import { useGlobalSearchParams } from "expo-router"; +import { useCallback, useEffect, useMemo, useState } from "react"; +import { Alert, Dimensions, View } from "react-native"; import YoutubePlayer, { PLAYER_STATES } from "react-native-youtube-iframe"; export default function page() { const searchParams = useGlobalSearchParams(); - const navigation = useNavigation(); console.log(searchParams); const { url } = searchParams as { url: string }; @@ -29,15 +27,10 @@ export default function page() { }, []); useEffect(() => { - navigation.setOptions({ - headerShown: false, - }); - togglePlaying(); }, []); const screenWidth = Dimensions.get("screen").width; - const screenHeight = Dimensions.get("screen").height; return ( diff --git a/app/_layout.tsx b/app/_layout.tsx index 444ec7da..8c9da2f7 100644 --- a/app/_layout.tsx +++ b/app/_layout.tsx @@ -338,6 +338,7 @@ function Layout() { = ({ item, ...props }) => { return ( - + + + + {item.Type === "Episode" && ( <> diff --git a/components/series/SeriesActions.tsx b/components/series/SeriesActions.tsx index 7e87247f..80d219f5 100644 --- a/components/series/SeriesActions.tsx +++ b/components/series/SeriesActions.tsx @@ -2,13 +2,13 @@ import { Ionicons } from "@expo/vector-icons"; import { BaseItemDto } from "@jellyfin/sdk/lib/generated-client"; import { useRouter } from "expo-router"; import { useCallback, useMemo } from "react"; -import { View, TouchableOpacity, ViewProps } from "react-native"; +import { TouchableOpacity, View, ViewProps } from "react-native"; interface Props extends ViewProps { item: BaseItemDto; } -export const SeriesActions = ({ item, ...props }: Props) => { +export const ItemActions = ({ item, ...props }: Props) => { const router = useRouter(); const trailerLink = useMemo(() => item.RemoteTrailers?.[0]?.Url, [item]); diff --git a/components/series/SeriesHeader.tsx b/components/series/SeriesHeader.tsx index 3fa5ca67..78230c89 100644 --- a/components/series/SeriesHeader.tsx +++ b/components/series/SeriesHeader.tsx @@ -3,7 +3,7 @@ import { Text } from "../common/Text"; import { Ratings } from "../Ratings"; import { BaseItemDto } from "@jellyfin/sdk/lib/generated-client"; import { useMemo } from "react"; -import { SeriesActions } from "./SeriesActions"; +import { ItemActions } from "./SeriesActions"; interface Props { item: BaseItemDto; @@ -56,7 +56,7 @@ export const SeriesHeader = ({ item }: Props) => { {yearString} - + {item?.Overview} diff --git a/providers/DownloadProvider.tsx b/providers/DownloadProvider.tsx index 706f96f5..78fbbe6f 100644 --- a/providers/DownloadProvider.tsx +++ b/providers/DownloadProvider.tsx @@ -39,7 +39,7 @@ import React, { useMemo, useState, } from "react"; -import {AppState, AppStateStatus, Platform} from "react-native"; +import { AppState, AppStateStatus, Platform } from "react-native"; import { toast } from "sonner-native"; import { apiAtom } from "./JellyfinProvider"; import * as Notifications from "expo-notifications"; @@ -195,7 +195,7 @@ function useDownloadProvider() { [settings?.optimizedVersionsServerUrl, authHeader] ); - const APP_CACHE_DOWNLOAD_DIRECTORY = `${FileSystem.cacheDirectory}${Application.applicationId}/Downloads/` + const APP_CACHE_DOWNLOAD_DIRECTORY = `${FileSystem.cacheDirectory}${Application.applicationId}/Downloads/`; const startDownload = useCallback( async (process: JobStatus) => { @@ -423,32 +423,25 @@ function useDownloadProvider() { throw new Error("Base directory not found"); } - console.log(`ignoreList length: ${ignoreList?.length}`); - const dirContents = await FileSystem.readDirectoryAsync(baseDirectory); for (const item of dirContents) { // Exclude mmkv directory. // Deleting this deletes all user information as well. Logout should handle this. if ( (item == "mmkv" && !includeMMKV) || - ignoreList.some(i => item.includes(i)) + ignoreList.some((i) => item.includes(i)) ) { - console.log("Skipping read for item", item) continue; } await FileSystem.getInfoAsync(`${baseDirectory}${item}`) .then((itemInfo) => { - console.log("Loading itemInfo", itemInfo); - if (itemInfo.exists && !itemInfo.isDirectory) { callback(itemInfo); } }) - .catch(e => - console.error(e) - ) + .catch((e) => console.error(e)); } - } + }; const deleteLocalFiles = async (): Promise => { await forEveryDocumentDirFile(false, [], (file) => { @@ -545,28 +538,36 @@ function useDownloadProvider() { }; const cleanCacheDirectory = async () => { - const cacheDir = await FileSystem.getInfoAsync(APP_CACHE_DOWNLOAD_DIRECTORY); + const cacheDir = await FileSystem.getInfoAsync( + APP_CACHE_DOWNLOAD_DIRECTORY + ); if (cacheDir.exists) { - const cachedFiles = await FileSystem.readDirectoryAsync(APP_CACHE_DOWNLOAD_DIRECTORY) - let position = 0 - const batchSize = 3 + const cachedFiles = await FileSystem.readDirectoryAsync( + APP_CACHE_DOWNLOAD_DIRECTORY + ); + let position = 0; + const batchSize = 3; // batching promise.all to avoid OOM while (position < cachedFiles.length) { - const itemsForBatch = cachedFiles.slice(position, position + batchSize) - await Promise.all(itemsForBatch.map(async file => { - const info = await FileSystem.getInfoAsync(`${APP_CACHE_DOWNLOAD_DIRECTORY}${file}`) - if (info.exists) { - await FileSystem.deleteAsync(info.uri, { idempotent: true }) - return Promise.resolve(file) - } - return Promise.reject() - })) + const itemsForBatch = cachedFiles.slice(position, position + batchSize); + await Promise.all( + itemsForBatch.map(async (file) => { + const info = await FileSystem.getInfoAsync( + `${APP_CACHE_DOWNLOAD_DIRECTORY}${file}` + ); + if (info.exists) { + await FileSystem.deleteAsync(info.uri, { idempotent: true }); + return Promise.resolve(file); + } + return Promise.reject(); + }) + ); - position += batchSize + position += batchSize; } } - } + }; const deleteFileByType = async (type: BaseItemDto["Type"]) => { await Promise.all( @@ -583,20 +584,22 @@ function useDownloadProvider() { }; const appSizeUsage = useMemo(async () => { - const sizes: number[] = downloadedFiles?.map(d => { - return getDownloadedItemSize(d.item.Id!!) - }) || []; + const sizes: number[] = + downloadedFiles?.map((d) => { + return getDownloadedItemSize(d.item.Id!!); + }) || []; await forEveryDocumentDirFile( true, - getAllDownloadedItems().map(d => d.item.Id!!), + getAllDownloadedItems().map((d) => d.item.Id!!), (file) => { if (file.exists) { sizes.push(file.size); } - }).catch(e => { - console.error(e) - }) + } + ).catch((e) => { + console.error(e); + }); return sizes.reduce((sum, size) => sum + size, 0); }, [logs, downloadedFiles, forEveryDocumentDirFile]); @@ -690,7 +693,7 @@ function useDownloadProvider() { appSizeUsage, getDownloadedItemSize, APP_CACHE_DOWNLOAD_DIRECTORY, - cleanCacheDirectory + cleanCacheDirectory, }; }