File size: 1,976 Bytes
f0743f4 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 | 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<typeof setTimeout>;
let timer: ReturnType<typeof setInterval>;
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;
}
|