diff --git a/frontend/src/components/ChannelPage.tsx b/frontend/src/components/ChannelPage.tsx index 2029f7e5..4241c3c4 100644 --- a/frontend/src/components/ChannelPage.tsx +++ b/frontend/src/components/ChannelPage.tsx @@ -1,6 +1,7 @@ import { useCallback, useEffect, useRef, useState } from "react"; import { useTranslation } from "react-i18next"; import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; +import { useLiveQuery } from "../lib/useLiveQuery"; import { qk } from "../lib/queryKeys"; import { useNavigationActions } from "./NavigationProvider"; import { PriorityStepper } from "./PriorityStepper"; @@ -79,9 +80,11 @@ export default function ChannelPage({ const MAX_BANNER_RETRIES = 3; const [bannerAttempt, setBannerAttempt] = useState(0); - const detail = useQuery({ - queryKey: qk.channel(channelId), - queryFn: () => api.channelDetail(channelId), + // A LIVE query: while THIS user's full-history backfill is running, poll so the stored count (and + // the N/S/L breakdown) climb on their own — the scheduler adds videos in ~2-min ticks — then stop + // polling once the back-catalogue is in. Same queryKey as before, so mutation invalidations still hit. + const detail = useLiveQuery(qk.channel(channelId), () => api.channelDetail(channelId), { + intervalMs: (d) => (d?.deep_requested && !d.backfill_done ? 4000 : false), }); const ch = detail.data; useEffect(() => setBannerAttempt(0), [ch?.banner_url]); // fresh channel/banner → try again diff --git a/frontend/src/lib/useLiveQuery.ts b/frontend/src/lib/useLiveQuery.ts index 69b96fbc..22af46c1 100644 --- a/frontend/src/lib/useLiveQuery.ts +++ b/frontend/src/lib/useLiveQuery.ts @@ -9,10 +9,13 @@ export function useLiveQuery( key: QueryKey, queryFn: () => Promise, // intervalMs may be a function of the latest data, so the poll cadence can adapt to it - // (e.g. poll faster while a job is running). react-query re-evaluates it after each fetch - // against fresh data — the right place for this, vs. a React state toggle that can lag or - // stall the live updates. - opts: { intervalMs?: number | ((data: T | undefined) => number); enabled?: boolean } = {}, + // (e.g. poll faster while a job is running, and return `false` to STOP once it's done). + // react-query re-evaluates it after each fetch against fresh data — the right place for this, + // vs. a React state toggle that can lag or stall the live updates. + opts: { + intervalMs?: number | false | ((data: T | undefined) => number | false); + enabled?: boolean; + } = {}, ) { const { intervalMs = 4000, enabled = true } = opts; return useQuery({