import { useState, useEffect, useMemo, useCallback } from 'react'; export default function useProgress(initialProgress = 0.01, increment = 0.007, fileSize?: number) { const calculateIncrement = useCallback( (size?: number) => { const baseRate = 0.05; const minRate = 0.002; const sizeMB = size ? size / (1024 * 1024) : 0; if (!size) { return increment; } if (sizeMB <= 1) { return baseRate * 2; } else { return Math.max(baseRate / Math.sqrt(sizeMB), minRate); } }, [increment], ); const incrementValue = useMemo( () => calculateIncrement(fileSize), [fileSize, calculateIncrement], ); const [progress, setProgress] = useState(initialProgress); const getDynamicIncrement = useCallback( (currentProgress: number) => { if (!fileSize) { return incrementValue; } if (currentProgress < 0.7) { return incrementValue; } else { return Math.max(0.0005, incrementValue * (1 - currentProgress)); } }, [incrementValue, fileSize], ); useEffect(() => { let timeout: ReturnType; let timer: ReturnType; if (initialProgress >= 1 && progress >= 1) { return; } else if (initialProgress >= 1 && progress < 1) { setProgress(0.99); timeout = setTimeout(() => { setProgress(1); }, 200); } else { timer = setInterval(() => { setProgress((prevProgress) => { if (prevProgress >= 1) { clearInterval(timer); return 1; } const currentIncrement = getDynamicIncrement(prevProgress); return Math.min(prevProgress + currentIncrement, 0.95); }); }, 200); } return () => { clearInterval(timer); clearTimeout(timeout); }; }, [progress, initialProgress, incrementValue, fileSize, getDynamicIncrement]); return progress; }