import { useInfiniteQuery, useMutation, useQuery } from "@tanstack/react-query"; import { DiscoverCalendar, type DiscoverItem, DiscoverMatchResult, DiscoverPage } from "@umt/contracts"; import type { ApiQuery } from "~/components/discover/discover-state.ts"; import { api } from "~/lib/api.ts"; import { getParsed, parseOrThrow } from "./library.ts"; // 发现:TMDB / 豆瓣 / bgm 列表(服务端走请求缓存);点豆瓣 / bgm 条目时匹配 TMDB 作品。 const STALE = 10 * 60_000; export const discoverKeys = { calendar: ["discover", "calendar"] as const, list: (q: ApiQuery) => ["discover", q] as const, }; async function fetchCalendar(signal?: AbortSignal) { return getParsed(DiscoverCalendar, "/discover/bangumi-calendar", {}, signal); } /** 一页;每日放送取那一天,不分页 */ export async function fetchDiscoverPage(q: ApiQuery, page: number, signal?: AbortSignal): Promise { if (q.kind === "calendar") { const cal = await fetchCalendar(signal); const items = cal.days.find((d) => String(d.weekday) === q.weekday)?.items ?? []; return { items, page: 1, hasMore: false }; } return getParsed(DiscoverPage, q.path, { ...q.params, page }, signal); } /** 推荐分区:只取第一页;enabled 由分区是否进入视口决定 */ export function useDiscoverSection(q: ApiQuery, enabled: boolean) { return useQuery({ queryKey: [...discoverKeys.list(q), 1], enabled, queryFn: ({ signal }) => fetchDiscoverPage(q, 1, signal), staleTime: STALE, }); } /** 探索:无限滚动 */ export function useDiscoverInfinite(q: ApiQuery) { return useInfiniteQuery({ queryKey: [...discoverKeys.list(q), "all"], initialPageParam: 1, queryFn: ({ pageParam, signal }) => fetchDiscoverPage(q, pageParam, signal), getNextPageParam: (last) => (last.hasMore ? last.page + 1 : undefined), staleTime: STALE, }); } export function useBangumiCalendar(enabled = true) { return useQuery({ queryKey: discoverKeys.calendar, enabled, queryFn: ({ signal }) => fetchCalendar(signal), staleTime: STALE, }); } export function useDiscoverMatch() { return useMutation({ mutationFn: async (it: DiscoverItem) => parseOrThrow( DiscoverMatchResult, await api.post("/discover/tmdb-match", { source: it.source, id: it.id, title: it.title, aliases: it.aliases, year: it.year, kind: it.kind, }), "/discover/tmdb-match", ), }); }