// Initial-sync progress UX (SPEC ยง12 M2). Shows a small floating card while any // account is importing its history; reads the accounts query, which the WS // `sync.progress` event invalidates so the bar advances live. import { useQuery } from "@tanstack/react-query"; import { useEffect, useState } from "react"; import { useT } from "../i18n"; import { api } from "../lib/api"; export function BackfillBanner() { const t = useT(); const accounts = useQuery({ queryKey: ["accounts"], queryFn: api.accounts }); const importing = (accounts.data ?? []).filter( (a) => a.state === "backfilling" && a.backfill_total > 0, ); const active = importing.length > 0; // Dissolve the card 10s after it appears; the sidebar ring keeps showing // progress until the sync finishes. const [dismissed, setDismissed] = useState(false); useEffect(() => { if (!active) { setDismissed(false); return; } const timer = window.setTimeout(() => setDismissed(true), 10000); return () => window.clearTimeout(timer); }, [active]); if (!active) return null; return (
{importing.map((a) => { const done = Math.min(a.backfill_done, a.backfill_total); const pct = Math.round((done / a.backfill_total) * 100); return (
{a.email}
{t("backfill.importing", { done: done.toLocaleString(), total: a.backfill_total.toLocaleString(), })}
); })}
); }