Skip to content

Commit 316efa2

Browse files
author
marcus
committed
feat(sync-ui): add live progress + disable Sync Now until background sync completes
1 parent 8c6ddc7 commit 316efa2

1 file changed

Lines changed: 24 additions & 5 deletions

File tree

src/components/sync-button.tsx

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,34 @@
33
import { Button } from "@/components/ui/button";
44
import { useSyncMutation } from "@/lib/api/hooks";
55
import { useAppToast } from "@/components/providers";
6-
import { startSyncWatch } from "@/lib/sync-watch";
6+
import { isSyncWatchActive, startSyncWatch } from "@/lib/sync-watch";
77
import { RefreshCw } from "lucide-react";
88
import { useRouter } from "next/navigation";
9-
import { useState } from "react";
9+
import { useEffect, useState } from "react";
1010

1111
export function SyncButton() {
1212
const router = useRouter();
1313
const { pushToast } = useAppToast();
1414
const syncMutation = useSyncMutation();
1515
const [state, setState] = useState<"idle" | "queueing" | "queued" | "failed">("idle");
16+
const [watchActive, setWatchActive] = useState(false);
17+
18+
useEffect(() => {
19+
setWatchActive(isSyncWatchActive());
20+
const timer = setInterval(() => {
21+
setWatchActive(isSyncWatchActive());
22+
}, 1000);
23+
return () => clearInterval(timer);
24+
}, []);
1625

1726
async function trigger() {
27+
if (watchActive || state === "queueing") return;
1828
setState("queueing");
1929
try {
2030
await syncMutation.mutateAsync();
2131
setState("queued");
2232
startSyncWatch();
33+
setWatchActive(true);
2334
pushToast(
2435
{
2536
title: "Sync queued",
@@ -34,11 +45,19 @@ export function SyncButton() {
3445
}
3546
}
3647

37-
const label = state === "idle" ? "Sync now" : state === "queueing" ? "Syncing..." : state === "queued" ? "Queued" : "Failed";
48+
const isBusy = state === "queueing" || watchActive;
49+
const label =
50+
isBusy
51+
? "Syncing..."
52+
: state === "idle"
53+
? "Sync now"
54+
: state === "queued"
55+
? "Queued"
56+
: "Failed";
3857

3958
return (
40-
<Button onClick={trigger} disabled={state === "queueing"} className="gap-2" size={"lg"}>
41-
<RefreshCw className={state === "queueing" ? "size-4 animate-spin" : "size-4"}/>
59+
<Button onClick={trigger} disabled={isBusy} className="gap-2" size={"lg"}>
60+
<RefreshCw className={isBusy ? "size-4 animate-spin" : "size-4"} />
4261
{label}
4362
</Button>
4463
);

0 commit comments

Comments
 (0)