import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; import { useTranslation } from "react-i18next"; import { Clock, Database, History, Loader2, Pause, Play } from "lucide-react"; import { api } from "../lib/api"; import { formatViews } from "../lib/format"; import Tooltip from "./Tooltip"; // Per-user status (not the global catalog): shows the number of videos available to *this* // user, how many of *their* channels are still being fetched, and how many lack full // history (clickable -> channel manager filtered to those). The pause control is admin-only. export default function SyncStatus({ isAdmin, onGoToFullHistory, }: { isAdmin: boolean; onGoToFullHistory: () => void; }) { const { t } = useTranslation(); const qc = useQueryClient(); const { data } = useQuery({ queryKey: ["my-status"], queryFn: api.myStatus, // Track the scheduler near-real-time: poll even when the tab is backgrounded, and // refresh immediately on tab focus (the global default disables focus refetch), so the // "N without full history" count keeps ticking down without a manual reload. refetchInterval: 30_000, refetchIntervalInBackground: true, refetchOnWindowFocus: true, staleTime: 25_000, }); const toggle = useMutation({ mutationFn: () => (data?.paused ? api.resumeSync() : api.pauseSync()), onSuccess: () => qc.invalidateQueries({ queryKey: ["my-status"] }), }); if (!data) return null; const syncing = data.channels_recent_pending; const notFull = data.channels_deep_pending; // your channels without full history yet // Spin only while a sync job is actually running; otherwise pending work shows as a calm, // static state (or, for deep history, just the "N without full history" link below). const active = data.sync_active; const showMain = data.paused || active || syncing > 0 || notFull === 0; return (
{formatViews(data.my_videos)}{" "} {t("header.sync.yours")} / {formatViews(data.total_videos)} {t("header.sync.total")} {showMain && ( <> · {data.paused ? ( {t("header.sync.paused")} ) : active ? ( // A sync job is running right now — spin and name what it's doing. {syncing > 0 ? t("header.sync.syncing", { count: syncing }) : notFull > 0 ? t("header.sync.backfillingHistory") : t("header.sync.working")} ) : syncing > 0 ? ( // Recent uploads queued for the next run, but nothing running now — static. {t("header.sync.recentQueued", { count: syncing })} ) : ( {t("header.sync.allSynced")} )} )} {notFull > 0 && ( <> · )} {/* Pause only makes sense when there's work to pause (recent OR deep backfill); Resume must always show while paused so it can be lifted. Hidden entirely when idle and not paused. */} {isAdmin && (data.paused || syncing > 0 || notFull > 0) && ( )}
); }