import { ItemFields } from "@jellyfin/sdk/lib/generated-client/models"; import { useLocalSearchParams } from "expo-router"; import type React from "react"; import { useEffect } from "react"; import { useTranslation } from "react-i18next"; import { View } from "react-native"; import Animated, { runOnJS, useAnimatedStyle, useSharedValue, withTiming, } from "react-native-reanimated"; import { Text } from "@/components/common/Text"; import { ItemContent } from "@/components/ItemContent"; import { useItemQuery } from "@/hooks/useItemQuery"; const Page: React.FC = () => { const { id } = useLocalSearchParams() as { id: string }; const { t } = useTranslation(); const { offline } = useLocalSearchParams() as { offline?: string }; const isOffline = offline === "true"; // Exclude MediaSources/MediaStreams from initial fetch for faster loading // (especially important for plugins like Gelato) const { data: item, isError } = useItemQuery(id, isOffline, undefined, [ ItemFields.MediaSources, ItemFields.MediaSourceCount, ItemFields.MediaStreams, ]); // Lazily preload item with full media sources in background const { data: itemWithSources } = useItemQuery(id, isOffline, undefined, []); const opacity = useSharedValue(1); const animatedStyle = useAnimatedStyle(() => { return { opacity: opacity.value, }; }); const fadeOut = (callback: any) => { setTimeout(() => { opacity.value = withTiming(0, { duration: 500 }, (finished) => { if (finished) { runOnJS(callback)(); } }); }, 100); }; const fadeIn = (callback: any) => { setTimeout(() => { opacity.value = withTiming(1, { duration: 500 }, (finished) => { if (finished) { runOnJS(callback)(); } }); }, 100); }; useEffect(() => { if (item) { fadeOut(() => {}); } else { fadeIn(() => {}); } }, [item]); if (isError) return ( {t("item_card.could_not_load_item")} ); return ( {item && ( )} ); }; export default Page;