33import { Button } from "@/components/ui/button" ;
44import { useSyncMutation } from "@/lib/api/hooks" ;
55import { useAppToast } from "@/components/providers" ;
6- import { startSyncWatch } from "@/lib/sync-watch" ;
6+ import { isSyncWatchActive , startSyncWatch } from "@/lib/sync-watch" ;
77import { RefreshCw } from "lucide-react" ;
88import { useRouter } from "next/navigation" ;
9- import { useState } from "react" ;
9+ import { useEffect , useState } from "react" ;
1010
1111export 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