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;
}