diff --git a/app/(auth)/(tabs)/(home,libraries,search)/collections/[collectionId].tsx b/app/(auth)/(tabs)/(home,libraries,search)/collections/[collectionId].tsx index b9a657be..311b3805 100644 --- a/app/(auth)/(tabs)/(home,libraries,search)/collections/[collectionId].tsx +++ b/app/(auth)/(tabs)/(home,libraries,search)/collections/[collectionId].tsx @@ -1,8 +1,10 @@ +import { ItemImage } from "@/components/common/ItemImage"; import { Text } from "@/components/common/Text"; import { TouchableItemRouter } from "@/components/common/TouchableItemRouter"; import { FilterButton } from "@/components/filters/FilterButton"; import { ResetFiltersButton } from "@/components/filters/ResetFiltersButton"; import { ItemCardText } from "@/components/ItemCardText"; +import { ItemPoster } from "@/components/posters/ItemPoster"; import MoviePoster from "@/components/posters/MoviePoster"; import { apiAtom, userAtom } from "@/providers/JellyfinProvider"; import { @@ -194,7 +196,8 @@ const page: React.FC = () => { width: "89%", }} > - + + {/* */} diff --git a/app/(auth)/(tabs)/(libraries)/[libraryId].tsx b/app/(auth)/(tabs)/(libraries)/[libraryId].tsx index 77b2e3ff..4932c86d 100644 --- a/app/(auth)/(tabs)/(libraries)/[libraryId].tsx +++ b/app/(auth)/(tabs)/(libraries)/[libraryId].tsx @@ -46,6 +46,7 @@ import { FlashList } from "@shopify/flash-list"; import { Loader } from "@/components/Loader"; import { useSafeAreaInsets } from "react-native-safe-area-context"; import { orientationAtom } from "@/utils/atoms/orientation"; +import { ItemPoster } from "@/components/posters/ItemPoster"; const MemoizedTouchableItemRouter = React.memo(TouchableItemRouter); @@ -208,7 +209,8 @@ const Page = () => { width: "89%", }} > - + {/* */} + diff --git a/components/common/ItemImage.tsx b/components/common/ItemImage.tsx index c3ad2ed6..d25850ee 100644 --- a/components/common/ItemImage.tsx +++ b/components/common/ItemImage.tsx @@ -1,20 +1,31 @@ import { useImageColors } from "@/hooks/useImageColors"; import { apiAtom } from "@/providers/JellyfinProvider"; +import { Ionicons } from "@expo/vector-icons"; import { BaseItemDto } from "@jellyfin/sdk/lib/generated-client/models"; import { Image, ImageProps, ImageSource } from "expo-image"; import { useAtom } from "jotai"; import { useMemo } from "react"; +import { View } from "react-native"; interface Props extends ImageProps { item: BaseItemDto; - variant?: "Backdrop" | "Primary" | "Thumb" | "Logo"; + variant?: + | "Primary" + | "Backdrop" + | "ParentBackdrop" + | "ParentLogo" + | "Logo" + | "AlbumPrimary" + | "SeriesPrimary" + | "Screenshot" + | "Thumb"; quality?: number; width?: number; } export const ItemImage: React.FC = ({ item, - variant, + variant = "Primary", quality = 90, width = 1000, ...props @@ -28,6 +39,8 @@ export const ItemImage: React.FC = ({ let blurhash: string | null | undefined; let src: ImageSource | null = null; + console.log("ImageItem ~ " + variant, item.Name, item.ImageTags); + switch (variant) { case "Backdrop": if (item.Type === "Episode") { @@ -35,7 +48,7 @@ export const ItemImage: React.FC = ({ if (!tag) break; blurhash = item.ImageBlurHashes?.Backdrop?.[tag]; src = { - uri: `${api.basePath}/Items/${item.ParentBackdropItemId}/Images/Backdrop/0?quality=${quality}&tag=${tag}`, + uri: `${api.basePath}/Items/${item.ParentBackdropItemId}/Images/Backdrop/0?quality=${quality}&tag=${tag}&width=${width}`, blurhash, }; break; @@ -45,7 +58,7 @@ export const ItemImage: React.FC = ({ if (!tag) break; blurhash = item.ImageBlurHashes?.Backdrop?.[tag]; src = { - uri: `${api.basePath}/Items/${item.Id}/Images/Backdrop/0?quality=${quality}&tag=${tag}`, + uri: `${api.basePath}/Items/${item.Id}/Images/Backdrop/0?quality=${quality}&tag=${tag}&width=${width}`, blurhash, }; break; @@ -55,7 +68,7 @@ export const ItemImage: React.FC = ({ blurhash = item.ImageBlurHashes?.Primary?.[tag]; src = { - uri: `${api.basePath}/Items/${item.Id}/Images/Primary?quality=${quality}&tag=${tag}`, + uri: `${api.basePath}/Items/${item.Id}/Images/Primary?quality=${quality}&tag=${tag}&width=${width}`, blurhash, }; break; @@ -65,29 +78,42 @@ export const ItemImage: React.FC = ({ blurhash = item.ImageBlurHashes?.Thumb?.[tag]; src = { - uri: `${api.basePath}/Items/${item.Id}/Images/Backdrop?quality=${quality}&tag=${tag}`, + uri: `${api.basePath}/Items/${item.Id}/Images/Backdrop?quality=${quality}&tag=${tag}&width=${width}`, blurhash, }; break; default: tag = item.ImageTags?.["Primary"]; src = { - uri: `${api.basePath}/Items/${item.Id}/Images/Primary?quality=${quality}&tag=${tag}`, + uri: `${api.basePath}/Items/${item.Id}/Images/Primary?quality=${quality}&tag=${tag}&width=${width}`, }; break; } + console.log("src: ", src?.uri?.slice(0, 30)); + return src; }, [item.ImageTags]); useImageColors(source?.uri); + // return placeholder icon if no source + if (!source?.uri) return; + + ; + ; + return ( > = ({ } if (item.Type === "UserView") { - Alert.alert("Not implemented"); + router.push(`/(auth)/(tabs)/${from}/collections/${item.Id}`); return; } diff --git a/components/posters/ItemPoster.tsx b/components/posters/ItemPoster.tsx new file mode 100644 index 00000000..97cbfd7f --- /dev/null +++ b/components/posters/ItemPoster.tsx @@ -0,0 +1,47 @@ +import { View, ViewProps } from "react-native"; +import { Text } from "@/components/common/Text"; +import { + BaseItemDto, + BaseItemKind, +} from "@jellyfin/sdk/lib/generated-client/models"; +import { ItemImage } from "../common/ItemImage"; +import { WatchedIndicator } from "../WatchedIndicator"; +import { useState } from "react"; + +interface Props extends ViewProps { + item: BaseItemDto; + showProgress?: boolean; +} + +export const ItemPoster: React.FC = ({ + item, + showProgress, + ...props +}) => { + const [progress, setProgress] = useState( + item.UserData?.PlayedPercentage || 0 + ); + + if (item.Type === "Movie" || item.Type === "Series" || item.Type === "BoxSet") + return ( + + + + {showProgress && progress > 0 && ( + + )} + + ); + + return ( + + + + ); +};