109 lines
2.7 KiB
TypeScript
109 lines
2.7 KiB
TypeScript
/**
|
|
* Custom hook for monitoring sync progress
|
|
* Centralizes the pattern of polling syncProgressManager and updating state
|
|
*/
|
|
|
|
import { useState, useEffect, useRef } from 'react'
|
|
import type { SyncProgress } from '../helpers/syncProgressHelper'
|
|
|
|
export interface UseSyncProgressOptions {
|
|
onComplete?: () => void | Promise<void>
|
|
pollInterval?: number
|
|
maxDuration?: number
|
|
}
|
|
|
|
export interface UseSyncProgressResult {
|
|
syncProgress: SyncProgress | null
|
|
isSyncing: boolean
|
|
startMonitoring: () => void
|
|
stopMonitoring: () => void
|
|
}
|
|
|
|
/**
|
|
* Hook to monitor sync progress from syncProgressManager
|
|
*/
|
|
export function useSyncProgress(options: UseSyncProgressOptions = {}): UseSyncProgressResult {
|
|
const { onComplete, pollInterval = 500, maxDuration = 60000 } = options
|
|
|
|
const [syncProgress, setSyncProgress] = useState<SyncProgress | null>(null)
|
|
const [isSyncing, setIsSyncing] = useState(false)
|
|
const intervalRef = useRef<NodeJS.Timeout | null>(null)
|
|
const timeoutRef = useRef<NodeJS.Timeout | null>(null)
|
|
const onCompleteRef = useRef(onComplete)
|
|
const isMonitoringRef = useRef(false)
|
|
|
|
// Update onComplete ref when it changes
|
|
useEffect(() => {
|
|
onCompleteRef.current = onComplete
|
|
}, [onComplete])
|
|
|
|
const checkProgress = async (): Promise<void> => {
|
|
const { syncProgressManager } = await import('../syncProgressManager')
|
|
const currentProgress = syncProgressManager.getProgress()
|
|
if (currentProgress) {
|
|
setSyncProgress(currentProgress)
|
|
if (currentProgress.completed) {
|
|
setIsSyncing(false)
|
|
if (onCompleteRef.current) {
|
|
await onCompleteRef.current()
|
|
}
|
|
stopMonitoring()
|
|
}
|
|
}
|
|
}
|
|
|
|
const startMonitoring = (): void => {
|
|
if (isMonitoringRef.current) {
|
|
return
|
|
}
|
|
|
|
isMonitoringRef.current = true
|
|
setIsSyncing(true)
|
|
setSyncProgress({ currentStep: 0, totalSteps: 7, completed: false })
|
|
|
|
// Poll progress periodically
|
|
intervalRef.current = setInterval(() => {
|
|
void checkProgress()
|
|
}, pollInterval)
|
|
|
|
// Cleanup after max duration
|
|
timeoutRef.current = setTimeout(() => {
|
|
stopMonitoring()
|
|
}, maxDuration)
|
|
}
|
|
|
|
const stopMonitoring = (): void => {
|
|
if (!isMonitoringRef.current) {
|
|
return
|
|
}
|
|
|
|
isMonitoringRef.current = false
|
|
setIsSyncing(false)
|
|
|
|
if (intervalRef.current) {
|
|
clearInterval(intervalRef.current)
|
|
intervalRef.current = null
|
|
}
|
|
|
|
if (timeoutRef.current) {
|
|
clearTimeout(timeoutRef.current)
|
|
timeoutRef.current = null
|
|
}
|
|
}
|
|
|
|
// Cleanup on unmount
|
|
useEffect(() => {
|
|
return () => {
|
|
stopMonitoring()
|
|
}
|
|
}, [])
|
|
|
|
return {
|
|
syncProgress,
|
|
isSyncing,
|
|
startMonitoring,
|
|
stopMonitoring,
|
|
}
|
|
}
|
|
|