From 24b4f212fba214e8e090f844145f6c85e9d218f9 Mon Sep 17 00:00:00 2001 From: Uruk Date: Sun, 18 Jan 2026 13:56:49 +0100 Subject: [PATCH] feat: add useAdjacentEpisodes hook --- hooks/useAdjacentEpisodes.ts | 64 ++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 hooks/useAdjacentEpisodes.ts diff --git a/hooks/useAdjacentEpisodes.ts b/hooks/useAdjacentEpisodes.ts new file mode 100644 index 00000000..6fb32ac3 --- /dev/null +++ b/hooks/useAdjacentEpisodes.ts @@ -0,0 +1,64 @@ +import { apiAtom } from "@/providers/JellyfinProvider"; +import { BaseItemDto } from "@jellyfin/sdk/lib/generated-client"; +import { getTvShowsApi } from "@jellyfin/sdk/lib/utils/api"; +import { useQuery } from "@tanstack/react-query"; +import { useMemo } from "react"; +import { useAtomValue } from "jotai"; + +interface AdjacentEpisodesProps { + item?: BaseItemDto | null; +} + +export const useAdjacentItems = ({ item }: AdjacentEpisodesProps) => { + const api = useAtomValue(apiAtom); + + const { data: adjacentItems } = useQuery({ + queryKey: ["adjacentItems", item?.Id, item?.SeriesId], + queryFn: async (): Promise => { + if (!api || !item || !item.SeriesId) { + return null; + } + + const res = await getTvShowsApi(api).getEpisodes({ + seriesId: item.SeriesId, + adjacentTo: item.Id, + limit: 3, + fields: ["MediaSources", "MediaStreams", "ParentId"], + }); + + return res.data.Items || null; + }, + enabled: + !!api && + !!item?.Id && + !!item?.SeriesId && + (item?.Type === "Episode" || item?.Type === "Audio"), + staleTime: 0, + }); + + const previousItem = useMemo(() => { + if (!adjacentItems || adjacentItems.length <= 1) { + return null; + } + + if (adjacentItems.length === 2) { + return adjacentItems[0].Id === item?.Id ? null : adjacentItems[0]; + } + + return adjacentItems[0]; + }, [adjacentItems, item]); + + const nextItem = useMemo(() => { + if (!adjacentItems || adjacentItems.length <= 1) { + return null; + } + + if (adjacentItems.length === 2) { + return adjacentItems[1].Id === item?.Id ? null : adjacentItems[1]; + } + + return adjacentItems[2]; + }, [adjacentItems, item]); + + return { previousItem, nextItem }; +};