import { lazy, Suspense, useState } from "react"; import { qk } from "../lib/queryKeys"; import { useTranslation } from "react-i18next"; import { useQuery } from "@tanstack/react-query"; import { Download } from "lucide-react"; import clsx from "clsx"; // Lazy: the download dialog (+ its profile editor) loads only when a card's download button is // clicked, so it never ships in the feed chunk for the majority who just browse. const DownloadDialog = lazy(() => import("./DownloadDialog")); import { api } from "../lib/api"; import { IconButton } from "./ui/IconButton"; // Self-contained download affordance for a video card / the player. Reflects the video's current state from // the shared per-user download index (one polled query shared across every card). export default function DownloadButton({ videoId, title, variant = "ghost", size = "sm", }: { videoId: string; title?: string | null; variant?: "ghost" | "outline" | "overlay"; size?: "sm" | "md"; }) { const { t } = useTranslation(); const indexQ = useQuery({ queryKey: qk.downloadIndex(), queryFn: api.downloadIndex, staleTime: 10000, }); const [open, setOpen] = useState(false); const status = indexQ.data?.[videoId]; const downloaded = status === "done"; const inQueue = status === "queued" || status === "running" || status === "paused"; const label = downloaded ? t("downloads.button.downloaded") : inQueue ? t("downloads.button.queued") : t("downloads.button.label"); return ( <> { e.preventDefault(); e.stopPropagation(); setOpen(true); }} label={label} > {/* The state is in the glyph: downloaded or queued is the accent, a running one pulses. */} {open && ( setOpen(false)} /> )} ); }