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) {
|
export function selectIsContextMenuTranslucent<T extends GlobalState>(global: T) {
|
||||||
return selectPerformanceSettingsValue(global, 'contextMenuBlur');
|
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 { ApiMediaFormat } from '../api/types';
|
||||||
|
|
||||||
|
import { selectIsSynced } from '../global/selectors';
|
||||||
import * as mediaLoader from '../util/mediaLoader';
|
import * as mediaLoader from '../util/mediaLoader';
|
||||||
import useForceUpdate from './useForceUpdate';
|
import useForceUpdate from './useForceUpdate';
|
||||||
|
import useSelector from './useSelector';
|
||||||
|
|
||||||
const useMedia = (
|
const useMedia = (
|
||||||
mediaHash: string | false | undefined,
|
mediaHash: string | false | undefined,
|
||||||
@ -13,9 +15,10 @@ const useMedia = (
|
|||||||
) => {
|
) => {
|
||||||
const mediaData = mediaHash ? mediaLoader.getFromMemory(mediaHash) : undefined;
|
const mediaData = mediaHash ? mediaLoader.getFromMemory(mediaHash) : undefined;
|
||||||
const forceUpdate = useForceUpdate();
|
const forceUpdate = useForceUpdate();
|
||||||
|
const isSynced = useSelector(selectIsSynced);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!noLoad && mediaHash && !mediaData) {
|
if (isSynced && !noLoad && mediaHash && !mediaData) {
|
||||||
const startedAt = Date.now();
|
const startedAt = Date.now();
|
||||||
|
|
||||||
mediaLoader.fetch(mediaHash, mediaFormat).then(() => {
|
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;
|
return mediaData;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -4,10 +4,12 @@ import {
|
|||||||
|
|
||||||
import { ApiMediaFormat } from '../api/types';
|
import { ApiMediaFormat } from '../api/types';
|
||||||
|
|
||||||
|
import { selectIsSynced } from '../global/selectors';
|
||||||
import * as mediaLoader from '../util/mediaLoader';
|
import * as mediaLoader from '../util/mediaLoader';
|
||||||
import { throttle } from '../util/schedulers';
|
import { throttle } from '../util/schedulers';
|
||||||
import { IS_PROGRESSIVE_SUPPORTED } from '../util/windowEnvironment';
|
import { IS_PROGRESSIVE_SUPPORTED } from '../util/windowEnvironment';
|
||||||
import useForceUpdate from './useForceUpdate';
|
import useForceUpdate from './useForceUpdate';
|
||||||
|
import useSelector from './useSelector';
|
||||||
import useUniqueId from './useUniqueId';
|
import useUniqueId from './useUniqueId';
|
||||||
|
|
||||||
const STREAMING_PROGRESS = 0.75;
|
const STREAMING_PROGRESS = 0.75;
|
||||||
@ -24,6 +26,7 @@ export default function useMediaWithLoadProgress(
|
|||||||
const mediaData = mediaHash ? mediaLoader.getFromMemory(mediaHash) : undefined;
|
const mediaData = mediaHash ? mediaLoader.getFromMemory(mediaHash) : undefined;
|
||||||
const isStreaming = IS_PROGRESSIVE_SUPPORTED && mediaFormat === ApiMediaFormat.Progressive;
|
const isStreaming = IS_PROGRESSIVE_SUPPORTED && mediaFormat === ApiMediaFormat.Progressive;
|
||||||
const forceUpdate = useForceUpdate();
|
const forceUpdate = useForceUpdate();
|
||||||
|
const isSynced = useSelector(selectIsSynced);
|
||||||
const id = useUniqueId();
|
const id = useUniqueId();
|
||||||
const [loadProgress, setLoadProgress] = useState(mediaData && !isStreaming ? 1 : 0);
|
const [loadProgress, setLoadProgress] = useState(mediaData && !isStreaming ? 1 : 0);
|
||||||
const startedAtRef = useRef<number>();
|
const startedAtRef = useRef<number>();
|
||||||
@ -37,7 +40,7 @@ export default function useMediaWithLoadProgress(
|
|||||||
}, [delay]);
|
}, [delay]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!noLoad && mediaHash) {
|
if (isSynced && !noLoad && mediaHash) {
|
||||||
if (!mediaData) {
|
if (!mediaData) {
|
||||||
setLoadProgress(0);
|
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(() => {
|
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.
|
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;
|
clientsCount: number;
|
||||||
getter: Signal<T>;
|
getter: Signal<T>;
|
||||||
setter: SignalSetter;
|
setter: SignalSetter;
|
||||||
}
|
}
|
||||||
|
|
||||||
const bySelector = new Map<Selector<any>, State<any>>();
|
const bySelector = new Map<Selector<unknown>, State<unknown>>();
|
||||||
|
|
||||||
addCallback((global: GlobalState) => {
|
addCallback((global: GlobalState) => {
|
||||||
for (const [selector, { setter }] of bySelector) {
|
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);
|
let state = bySelector.get(selector);
|
||||||
|
|
||||||
if (!state) {
|
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;
|
export default useSelectorSignal;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user