import { useState } from 'react'; import { Loader2, RefreshCw } from 'lucide-react'; import { Button } from '@/components/ui/button'; import { SyncModal } from './SyncModal'; import { useMediaSync, useMediaSyncFeed } from './useMediaSync'; import { useReady } from './useReady'; /** * Sync, in the panel's bar beside Build and Publish. * * ── Why it left the card ── * * It sat under the two folders it acts on, which was the right place while it was a detail of setting * fofos up. It is not one: `derived/` being stale is the reason a picture is missing from a page * somebody is looking at, and the fix was three sections away, in a card about where the site lives. * Beside Build and Publish it reads as what it is — the third thing you do to a site. * * The card keeps everything there is no room for up here: the progress bar, the failures, and the run * history. Both read one slot, so they cannot disagree about what is true. * * ── It owns the fetching ── * * `useMediaSyncFeed` has exactly one caller and this is it, because the bar is mounted whenever * anything in this plugin is open and the Administration card is mounted only sometimes. The thing * that is always there should be the thing that asks. * * ── Pressing it OPENS rather than starts ── * * A sync is minutes of work on a folder somebody may not have looked at in a while, and starting it * from a bar gave no way to see what it was doing — the counters said how much and never which file. * So the button opens the transcript and the transcript has the verb in it. One press to look, one to * commit, and the second one is next to the thing it will fill. * * ── The label is the state ── * * `Sync 3` rather than a badge or a dot: the number IS the reason to press it, and a button that says * "Sync now" when there is nothing to sync invites a press that does nothing. Idle and current, it * still says "Sync" — the action stays available, because a file changed outside the watcher's notice * is exactly the case somebody needs it for. */ export const SyncButton = () => { const { running, percent, outstanding } = useMediaSync(); const { rootSet } = useReady(); const [open, setOpen] = useState(false); useMediaSyncFeed(); /* Gated on the ROOT, not on `ready`. Sync reads a folder on this machine and never speaks to fofos, so a broken connection is no reason to withhold it — that distinction is the one `useReady` records as the bug that made `rootSet` a separate answer in the first place. */ if (!rootSet) return null; return ( <> setOpen(false)} /> ); };