import type { BaseItemDto, MediaSourceInfo, } from "@jellyfin/sdk/lib/generated-client/models"; import { useCallback, useMemo, useState } from "react"; import { useTranslation } from "react-i18next"; import { Platform, TouchableOpacity, View } from "react-native"; import { Text } from "./common/Text"; import { FilterSheet } from "./filters/FilterSheet"; interface Props extends React.ComponentProps { item: BaseItemDto; onChange: (value: MediaSourceInfo) => void; selected?: MediaSourceInfo | null; } export const MediaSourceSheet: React.FC = ({ item, onChange, selected, ...props }) => { const isTv = Platform.isTV; const { t } = useTranslation(); const [open, setOpen] = useState(false); const getDisplayName = useCallback((source: MediaSourceInfo) => { const videoStream = source.MediaStreams?.find((x) => x.Type === "Video"); if (source.Name) return source.Name; if (videoStream?.DisplayTitle) return videoStream.DisplayTitle; return `Source ${source.Id}`; }, []); const selectedName = useMemo(() => { if (!selected) return ""; return getDisplayName(selected); }, [selected, getDisplayName]); if (isTv || (item.MediaSources && item.MediaSources.length <= 1)) return null; return ( {t("item_card.video")} setOpen(true)} > {selectedName} getDisplayName(src as MediaSourceInfo) .toLowerCase() .includes(query.toLowerCase()) } renderItemLabel={(src) => ( {getDisplayName(src as MediaSourceInfo)} )} set={(vals) => { const chosen = vals[0] as MediaSourceInfo | undefined; if (chosen) onChange(chosen); }} /> ); };