diff --git a/src/global/selectors/ui.ts b/src/global/selectors/ui.ts index ee2d66bd2..a558b4091 100644 --- a/src/global/selectors/ui.ts +++ b/src/global/selectors/ui.ts @@ -134,3 +134,7 @@ export function selectCanAnimateInterface(global: T) { export function selectIsContextMenuTranslucent(global: T) { return selectPerformanceSettingsValue(global, 'contextMenuBlur'); } + +export function selectIsSynced(global: T) { + return global.isSynced; +} diff --git a/src/hooks/useMedia.ts b/src/hooks/useMedia.ts index e09051773..860943b40 100644 --- a/src/hooks/useMedia.ts +++ b/src/hooks/useMedia.ts @@ -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; }; diff --git a/src/hooks/useMediaWithLoadProgress.ts b/src/hooks/useMediaWithLoadProgress.ts index 215764e6d..ca9b0b40f 100644 --- a/src/hooks/useMediaWithLoadProgress.ts +++ b/src/hooks/useMediaWithLoadProgress.ts @@ -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(); @@ -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(() => { diff --git a/src/hooks/useSelector.ts b/src/hooks/useSelector.ts new file mode 100644 index 000000000..4bffa22dd --- /dev/null +++ b/src/hooks/useSelector.ts @@ -0,0 +1,11 @@ +import type { GlobalState } from '../global/types'; + +import useDerivedState from './useDerivedState'; +import useSelectorSignal from './useSelectorSignal'; + +type Selector = (global: GlobalState) => T; + +export default function useSelector(selector: Selector) { + const selectorSignal = useSelectorSignal(selector); + return useDerivedState(selectorSignal); +} diff --git a/src/hooks/useSelectorSignal.ts b/src/hooks/useSelectorSignal.ts index 58a692369..1f10d0a29 100644 --- a/src/hooks/useSelectorSignal.ts +++ b/src/hooks/useSelectorSignal.ts @@ -13,15 +13,15 @@ import useEffectOnce from './useEffectOnce'; b) Return a signal instead of forcing a component update right away. */ -type Selector = (global: GlobalState) => T; +type Selector = (global: GlobalState) => T; -interface State { +interface State { clientsCount: number; getter: Signal; setter: SignalSetter; } -const bySelector = new Map, State>(); +const bySelector = new Map, State>(); addCallback((global: GlobalState) => { for (const [selector, { setter }] of bySelector) { @@ -29,7 +29,7 @@ addCallback((global: GlobalState) => { } }); -function useSelectorSignal(selector: Selector): Signal { +function useSelectorSignal(selector: Selector): Signal { let state = bySelector.get(selector); if (!state) { @@ -50,7 +50,7 @@ function useSelectorSignal(selector: Selector): Signal { }; }); - return state.getter; + return state.getter as Signal; } export default useSelectorSignal;