diff --git a/app/(auth)/(tabs)/(home,libraries,search,favorites)/items/page.tsx b/app/(auth)/(tabs)/(home,libraries,search,favorites)/items/page.tsx index f0bb2a46..b3d905fa 100644 --- a/app/(auth)/(tabs)/(home,libraries,search,favorites)/items/page.tsx +++ b/app/(auth)/(tabs)/(home,libraries,search,favorites)/items/page.tsx @@ -27,8 +27,8 @@ const Page: React.FC = () => { ItemFields.MediaStreams, ]); - // preload media sources in background - useItemQuery(id, false, undefined, []); + // preload media sources + const { data: itemWithSources } = useItemQuery(id, false, undefined, []); const opacity = useSharedValue(1); const animatedStyle = useAnimatedStyle(() => { @@ -98,7 +98,13 @@ const Page: React.FC = () => { - {item && } + {item && ( + + )} ); }; diff --git a/components/ItemContent.tsx b/components/ItemContent.tsx index 783371ec..6b8f1bba 100644 --- a/components/ItemContent.tsx +++ b/components/ItemContent.tsx @@ -46,10 +46,11 @@ export type SelectedOptions = { interface ItemContentProps { item: BaseItemDto; isOffline: boolean; + itemWithSources?: BaseItemDto | null; } export const ItemContent: React.FC = React.memo( - ({ item, isOffline }) => { + ({ item, isOffline, itemWithSources }) => { const [api] = useAtom(apiAtom); const { settings } = useSettings(); const { orientation } = useOrientation(); @@ -98,7 +99,7 @@ export const ItemContent: React.FC = React.memo( ]); useEffect(() => { - if (!Platform.isTV) { + if (!Platform.isTV && itemWithSources) { navigation.setOptions({ headerRight: () => item && @@ -108,7 +109,7 @@ export const ItemContent: React.FC = React.memo( {item.Type !== "Program" && ( {!Platform.isTV && ( - + )} {user?.Policy?.IsAdministrator && ( @@ -125,7 +126,7 @@ export const ItemContent: React.FC = React.memo( {item.Type !== "Program" && ( {!Platform.isTV && ( - + )} {user?.Policy?.IsAdministrator && ( @@ -139,7 +140,7 @@ export const ItemContent: React.FC = React.memo( )), }); } - }, [item, navigation, user]); + }, [item, navigation, user, itemWithSources]); useEffect(() => { if (item) { @@ -212,7 +213,7 @@ export const ItemContent: React.FC = React.memo( )} diff --git a/components/MediaSourceButton.tsx b/components/MediaSourceButton.tsx index fcef6b8f..05847f35 100644 --- a/components/MediaSourceButton.tsx +++ b/components/MediaSourceButton.tsx @@ -7,13 +7,12 @@ import { useCallback, useEffect, useMemo, useState } from "react"; import { useTranslation } from "react-i18next"; import { ActivityIndicator, TouchableOpacity, View } from "react-native"; import type { ThemeColors } from "@/hooks/useImageColorsReturn"; -import { useItemQuery } from "@/hooks/useItemQuery"; import { BITRATES } from "./BitRateSheet"; import type { SelectedOptions } from "./ItemContent"; import { type OptionGroup, PlatformDropdown } from "./PlatformDropdown"; interface Props extends React.ComponentProps { - item: BaseItemDto; + item?: BaseItemDto | null; selectedOptions: SelectedOptions; setSelectedOptions: React.Dispatch< React.SetStateAction @@ -29,12 +28,6 @@ export const MediaSourceButton: React.FC = ({ }: Props) => { const { t } = useTranslation(); const [open, setOpen] = useState(false); - const { data: itemWithSources, isLoading } = useItemQuery( - item.Id, - false, - undefined, - [], - ); const effectiveColors = colors || { primary: "#7c3aed", @@ -42,7 +35,7 @@ export const MediaSourceButton: React.FC = ({ }; useEffect(() => { - const firstMediaSource = itemWithSources?.MediaSources?.[0]; + const firstMediaSource = item?.MediaSources?.[0]; if (!firstMediaSource) return; setSelectedOptions((prev) => { if (!prev) return prev; @@ -51,7 +44,7 @@ export const MediaSourceButton: React.FC = ({ mediaSource: firstMediaSource, }; }); - }, [itemWithSources, setSelectedOptions]); + }, [item, setSelectedOptions]); const getMediaSourceDisplayName = useCallback((source: MediaSourceInfo) => { const videoStream = source.MediaStreams?.find((x) => x.Type === "Video"); @@ -93,13 +86,10 @@ export const MediaSourceButton: React.FC = ({ }); // Media Source group (only if multiple sources) - if ( - itemWithSources?.MediaSources && - itemWithSources.MediaSources.length > 1 - ) { + if (item?.MediaSources && item.MediaSources.length > 1) { groups.push({ title: t("item_card.video"), - options: itemWithSources.MediaSources.map((source) => ({ + options: item.MediaSources.map((source) => ({ type: "radio" as const, label: getMediaSourceDisplayName(source), value: source, @@ -159,7 +149,7 @@ export const MediaSourceButton: React.FC = ({ return groups; }, [ - itemWithSources, + item, selectedOptions, audioStreams, subtitleStreams, @@ -170,7 +160,7 @@ export const MediaSourceButton: React.FC = ({ const trigger = ( setOpen(true)} className='relative' > @@ -179,7 +169,7 @@ export const MediaSourceButton: React.FC = ({ className='absolute w-12 h-12 rounded-full' /> - {isLoading ? ( + {!item ? ( ) : (