import { Ionicons } from "@expo/vector-icons"; import { getLiveTvApi } from "@jellyfin/sdk/lib/utils/api"; import { useQuery } from "@tanstack/react-query"; import { useAtom } from "jotai"; import React, { useCallback, useState } from "react"; import { useTranslation } from "react-i18next"; import { Dimensions, ScrollView, TouchableOpacity, View } from "react-native"; import { useSafeAreaInsets } from "react-native-safe-area-context"; import { ItemImage } from "@/components/common/ItemImage"; import { Text } from "@/components/common/Text"; import { HourHeader } from "@/components/livetv/HourHeader"; import { LiveTVGuideRow } from "@/components/livetv/LiveTVGuideRow"; import { apiAtom, userAtom } from "@/providers/JellyfinProvider"; const HOUR_HEIGHT = 30; const ITEMS_PER_PAGE = 20; const MemoizedLiveTVGuideRow = React.memo(LiveTVGuideRow); export default function page() { const [api] = useAtom(apiAtom); const [user] = useAtom(userAtom); const insets = useSafeAreaInsets(); const [date, _setDate] = useState(new Date()); const [currentPage, setCurrentPage] = useState(1); const { data: channels } = useQuery({ queryKey: ["livetv", "channels", currentPage], queryFn: async () => { const res = await getLiveTvApi(api!).getLiveTvChannels({ startIndex: (currentPage - 1) * ITEMS_PER_PAGE, limit: ITEMS_PER_PAGE, enableFavoriteSorting: true, userId: user?.Id, addCurrentProgram: false, enableUserData: false, enableImageTypes: ["Primary"], }); return res.data; }, }); const { data: programs } = useQuery({ queryKey: ["livetv", "programs", date, currentPage], queryFn: async () => { const startOfDay = new Date(date); startOfDay.setHours(0, 0, 0, 0); const endOfDay = new Date(date); endOfDay.setHours(23, 59, 59, 999); const now = new Date(); const isToday = startOfDay.toDateString() === now.toDateString(); const res = await getLiveTvApi(api!).getPrograms({ getProgramsDto: { MaxStartDate: endOfDay.toISOString(), MinEndDate: isToday ? now.toISOString() : startOfDay.toISOString(), ChannelIds: channels?.Items?.map((c) => c.Id).filter( Boolean, ) as string[], ImageTypeLimit: 1, EnableImages: false, SortBy: ["StartDate"], EnableTotalRecordCount: false, EnableUserData: false, }, }); return res.data; }, enabled: !!channels, }); const screenWidth = Dimensions.get("window").width; const [scrollX, setScrollX] = useState(0); const handleNextPage = useCallback(() => { setCurrentPage((prev) => prev + 1); }, []); const handlePrevPage = useCallback(() => { setCurrentPage((prev) => Math.max(1, prev - 1)); }, []); return ( {channels?.Items?.map((c, i) => ( ))} { setScrollX(e.nativeEvent.contentOffset.x); }} > {channels?.Items?.map((c, _i) => ( ))} ); } interface PageButtonsProps { currentPage: number; onPrevPage: () => void; onNextPage: () => void; isNextDisabled: boolean; } const PageButtons: React.FC = ({ currentPage, onPrevPage, onNextPage, isNextDisabled, }) => { const { t } = useTranslation(); return ( {t("live_tv.previous")} Page {currentPage} {t("live_tv.next")} ); };