import { useEffect, useRef, useState, } from '../lib/teact/teact'; import { ApiMediaFormat } from '../api/types'; import { selectIsSynced } from '../global/selectors'; import { IS_PROGRESSIVE_SUPPORTED } from '../util/browser/windowEnvironment'; import * as mediaLoader from '../util/mediaLoader'; import useSelector from './data/useSelector'; import useForceUpdate from './useForceUpdate'; import useThrottledCallback from './useThrottledCallback'; import useUniqueId from './useUniqueId'; const STREAMING_PROGRESS = 0.75; const STREAMING_TIMEOUT = 1500; const PROGRESS_THROTTLE = 500; export default function useMediaWithLoadProgress( mediaHash: string | undefined, noLoad = false, mediaFormat = ApiMediaFormat.BlobUrl, delay?: number | false, isHtmlAllowed = false, ) { const isStreaming = IS_PROGRESSIVE_SUPPORTED && mediaFormat === ApiMediaFormat.Progressive; const mediaData = mediaHash ? (isStreaming && !noLoad ? mediaLoader.getProgressiveUrl(mediaHash) : mediaLoader.getFromMemory(mediaHash)) : undefined; const forceUpdate = useForceUpdate(); const isSynced = useSelector(selectIsSynced); const id = useUniqueId(); const [loadProgress, setLoadProgress] = useState(mediaData && !isStreaming ? 1 : 0); const startedAtRef = useRef(); const handleProgress = useThrottledCallback((progress: number) => { if (startedAtRef.current && id && (!delay || (Date.now() - startedAtRef.current > delay))) { setLoadProgress(progress); } }, [delay, id], PROGRESS_THROTTLE, true); useEffect(() => { if (!noLoad && mediaHash) { if (!mediaData) { setLoadProgress(0); if (startedAtRef.current) { mediaLoader.cancelProgress(handleProgress); } startedAtRef.current = Date.now(); mediaLoader.fetch(mediaHash, mediaFormat, isHtmlAllowed, handleProgress, id).then(() => { const spentTime = Date.now() - startedAtRef.current!; startedAtRef.current = undefined; if (!delay || spentTime >= delay) { forceUpdate(); } else { setTimeout(forceUpdate, delay - spentTime); } }); } else if (isStreaming) { setTimeout(() => { setLoadProgress(STREAMING_PROGRESS); }, STREAMING_TIMEOUT); } } }, [ noLoad, mediaHash, mediaData, mediaFormat, isStreaming, delay, handleProgress, isHtmlAllowed, id, isSynced, ]); useEffect(() => { if (noLoad && startedAtRef.current) { mediaLoader.cancelProgress(handleProgress); setLoadProgress(0); startedAtRef.current = undefined; } }, [handleProgress, noLoad]); useEffect(() => { return () => { if (mediaHash) { mediaLoader.removeCallback(mediaHash, id); } }; }, [id, mediaHash]); return { mediaData, loadProgress }; }