Media: Fix stuck loading after page refresh (#4575)
This commit is contained in:
parent
c15c8a0eed
commit
c610c5ca73
@ -134,3 +134,7 @@ export function selectCanAnimateInterface<T extends GlobalState>(global: T) {
|
||||
export function selectIsContextMenuTranslucent<T extends GlobalState>(global: T) {
|
||||
return selectPerformanceSettingsValue(global, 'contextMenuBlur');
|
||||
}
|
||||
|
||||
export function selectIsSynced<T extends GlobalState>(global: T) {
|
||||
return global.isSynced;
|
||||
}
|
||||
|
||||
@ -2,8 +2,10 @@ import { useEffect } from '../lib/teact/teact';
|
||||
|
||||
import { ApiMediaFormat } from '../api/types';
|
||||
|
||||
import { selectIsSynced } from '../global/selectors';
|
||||
import * as mediaLoader from '../util/mediaLoader';
|
||||
import useForceUpdate from './useForceUpdate';
|
||||
import useSelector from './useSelector';
|
||||
|
||||
const useMedia = (
|
||||
mediaHash: string | false | undefined,
|
||||
@ -13,9 +15,10 @@ const useMedia = (
|
||||
) => {
|
||||
const mediaData = mediaHash ? mediaLoader.getFromMemory(mediaHash) : undefined;
|
||||
const forceUpdate = useForceUpdate();
|
||||
const isSynced = useSelector(selectIsSynced);
|
||||
|
||||
useEffect(() => {
|
||||
if (!noLoad && mediaHash && !mediaData) {
|
||||
if (isSynced && !noLoad && mediaHash && !mediaData) {
|
||||
const startedAt = Date.now();
|
||||
|
||||
mediaLoader.fetch(mediaHash, mediaFormat).then(() => {
|
||||
@ -27,7 +30,7 @@ const useMedia = (
|
||||
}
|
||||
});
|
||||
}
|
||||
}, [noLoad, mediaHash, mediaData, mediaFormat, forceUpdate, delay]);
|
||||
}, [noLoad, mediaHash, mediaData, mediaFormat, delay, isSynced]);
|
||||
|
||||
return mediaData;
|
||||
};
|
||||
|
||||
@ -4,10 +4,12 @@ import {
|
||||
|
||||
import { ApiMediaFormat } from '../api/types';
|
||||
|
||||
import { selectIsSynced } from '../global/selectors';
|
||||
import * as mediaLoader from '../util/mediaLoader';
|
||||
import { throttle } from '../util/schedulers';
|
||||
import { IS_PROGRESSIVE_SUPPORTED } from '../util/windowEnvironment';
|
||||
import useForceUpdate from './useForceUpdate';
|
||||
import useSelector from './useSelector';
|
||||
import useUniqueId from './useUniqueId';
|
||||
|
||||
const STREAMING_PROGRESS = 0.75;
|
||||
@ -24,6 +26,7 @@ export default function useMediaWithLoadProgress(
|
||||
const mediaData = mediaHash ? mediaLoader.getFromMemory(mediaHash) : undefined;
|
||||
const isStreaming = IS_PROGRESSIVE_SUPPORTED && mediaFormat === ApiMediaFormat.Progressive;
|
||||
const forceUpdate = useForceUpdate();
|
||||
const isSynced = useSelector(selectIsSynced);
|
||||
const id = useUniqueId();
|
||||
const [loadProgress, setLoadProgress] = useState(mediaData && !isStreaming ? 1 : 0);
|
||||
const startedAtRef = useRef<number>();
|
||||
@ -37,7 +40,7 @@ export default function useMediaWithLoadProgress(
|
||||
}, [delay]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!noLoad && mediaHash) {
|
||||
if (isSynced && !noLoad && mediaHash) {
|
||||
if (!mediaData) {
|
||||
setLoadProgress(0);
|
||||
|
||||
@ -64,7 +67,7 @@ export default function useMediaWithLoadProgress(
|
||||
}
|
||||
}
|
||||
}, [
|
||||
noLoad, mediaHash, mediaData, mediaFormat, forceUpdate, isStreaming, delay, handleProgress, isHtmlAllowed, id,
|
||||
noLoad, mediaHash, mediaData, mediaFormat, isStreaming, delay, handleProgress, isHtmlAllowed, id, isSynced,
|
||||
]);
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
11
src/hooks/useSelector.ts
Normal file
11
src/hooks/useSelector.ts
Normal file
@ -0,0 +1,11 @@
|
||||
import type { GlobalState } from '../global/types';
|
||||
|
||||
import useDerivedState from './useDerivedState';
|
||||
import useSelectorSignal from './useSelectorSignal';
|
||||
|
||||
type Selector<T extends unknown> = (global: GlobalState) => T;
|
||||
|
||||
export default function useSelector<T extends unknown>(selector: Selector<T>) {
|
||||
const selectorSignal = useSelectorSignal(selector);
|
||||
return useDerivedState(selectorSignal);
|
||||
}
|
||||
@ -13,15 +13,15 @@ import useEffectOnce from './useEffectOnce';
|
||||
b) Return a signal instead of forcing a component update right away.
|
||||
*/
|
||||
|
||||
type Selector<T extends any> = (global: GlobalState) => T;
|
||||
type Selector<T extends unknown> = (global: GlobalState) => T;
|
||||
|
||||
interface State<T extends any> {
|
||||
interface State<T extends unknown> {
|
||||
clientsCount: number;
|
||||
getter: Signal<T>;
|
||||
setter: SignalSetter;
|
||||
}
|
||||
|
||||
const bySelector = new Map<Selector<any>, State<any>>();
|
||||
const bySelector = new Map<Selector<unknown>, State<unknown>>();
|
||||
|
||||
addCallback((global: GlobalState) => {
|
||||
for (const [selector, { setter }] of bySelector) {
|
||||
@ -29,7 +29,7 @@ addCallback((global: GlobalState) => {
|
||||
}
|
||||
});
|
||||
|
||||
function useSelectorSignal<T extends any>(selector: Selector<T>): Signal<T> {
|
||||
function useSelectorSignal<T extends unknown>(selector: Selector<T>): Signal<T> {
|
||||
let state = bySelector.get(selector);
|
||||
|
||||
if (!state) {
|
||||
@ -50,7 +50,7 @@ function useSelectorSignal<T extends any>(selector: Selector<T>): Signal<T> {
|
||||
};
|
||||
});
|
||||
|
||||
return state.getter;
|
||||
return state.getter as Signal<T>;
|
||||
}
|
||||
|
||||
export default useSelectorSignal;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user