diff --git a/hooks/useIntroSkipper.ts b/hooks/useIntroSkipper.ts new file mode 100644 index 00000000..df05462e --- /dev/null +++ b/hooks/useIntroSkipper.ts @@ -0,0 +1,68 @@ +import { useCallback, useEffect, useState } from "react"; +import { useQuery } from "@tanstack/react-query"; +import { useAtom } from "jotai"; +import { apiAtom } from "@/providers/JellyfinProvider"; +import { getAuthHeaders } from "@/utils/jellyfin/jellyfin"; +import { writeToLog } from "@/utils/log"; + +interface IntroTimestamps { + EpisodeId: string; + HideSkipPromptAt: number; + IntroEnd: number; + IntroStart: number; + ShowSkipPromptAt: number; + Valid: boolean; +} + +export const useIntroSkipper = ( + itemId: string | undefined, + currentTime: number, + videoRef: React.RefObject +) => { + const [api] = useAtom(apiAtom); + const [showSkipButton, setShowSkipButton] = useState(false); + + const { data: introTimestamps } = useQuery({ + queryKey: ["introTimestamps", itemId], + queryFn: async () => { + if (!itemId) { + console.log("No item id"); + return null; + } + + const res = await api?.axiosInstance.get( + `${api.basePath}/Episode/${itemId}/IntroTimestamps`, + { + headers: getAuthHeaders(api), + } + ); + + if (res?.status !== 200) { + return null; + } + + return res?.data; + }, + enabled: !!itemId, + }); + + useEffect(() => { + if (introTimestamps) { + setShowSkipButton( + currentTime > introTimestamps.ShowSkipPromptAt && + currentTime < introTimestamps.HideSkipPromptAt + ); + } + }, [introTimestamps, currentTime]); + + const skipIntro = useCallback(() => { + if (!introTimestamps || !videoRef.current) return; + try { + videoRef.current.seek(introTimestamps.IntroEnd); + } catch (error) { + writeToLog("ERROR", "Error skipping intro", error); + } + }, [introTimestamps, videoRef]); + + return { showSkipButton, skipIntro }; +};