92 lines
2.8 KiB
TypeScript
92 lines
2.8 KiB
TypeScript
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<number>();
|
|
|
|
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 };
|
|
}
|