Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01Cxwgnn2pbzQ7rXv3rq7fei
77 lines
2.5 KiB
TypeScript
77 lines
2.5 KiB
TypeScript
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<DiscoverPage> {
|
|
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<unknown>("/discover/tmdb-match", {
|
|
source: it.source,
|
|
id: it.id,
|
|
title: it.title,
|
|
aliases: it.aliases,
|
|
year: it.year,
|
|
kind: it.kind,
|
|
}),
|
|
"/discover/tmdb-match",
|
|
),
|
|
});
|
|
}
|