Fix DPR update when switching monitors (#4155)
This commit is contained in:
parent
16c2fdbc04
commit
e9dacf35f3
@ -24,10 +24,10 @@ import { compact } from '../../../util/iteratees';
|
|||||||
|
|
||||||
import useAppLayout from '../../../hooks/useAppLayout';
|
import useAppLayout from '../../../hooks/useAppLayout';
|
||||||
import useFlag from '../../../hooks/useFlag';
|
import useFlag from '../../../hooks/useFlag';
|
||||||
import { useFullscreenStatus } from '../../../hooks/useFullscreen';
|
|
||||||
import { useIntersectionObserver, useIsIntersecting } from '../../../hooks/useIntersectionObserver';
|
import { useIntersectionObserver, useIsIntersecting } from '../../../hooks/useIntersectionObserver';
|
||||||
import useLang from '../../../hooks/useLang';
|
import useLang from '../../../hooks/useLang';
|
||||||
import useLastCallback from '../../../hooks/useLastCallback';
|
import useLastCallback from '../../../hooks/useLastCallback';
|
||||||
|
import { useFullscreenStatus } from '../../../hooks/window/useFullscreen';
|
||||||
import useGroupCallVideoLayout from './hooks/useGroupCallVideoLayout';
|
import useGroupCallVideoLayout from './hooks/useGroupCallVideoLayout';
|
||||||
|
|
||||||
import Button from '../../ui/Button';
|
import Button from '../../ui/Button';
|
||||||
|
|||||||
@ -15,7 +15,6 @@ import { hexToRgb } from '../../util/switchTheme';
|
|||||||
import { IS_ELECTRON } from '../../util/windowEnvironment';
|
import { IS_ELECTRON } from '../../util/windowEnvironment';
|
||||||
|
|
||||||
import useColorFilter from '../../hooks/stickers/useColorFilter';
|
import useColorFilter from '../../hooks/stickers/useColorFilter';
|
||||||
import useBackgroundMode, { isBackgroundModeActive } from '../../hooks/useBackgroundMode';
|
|
||||||
import useEffectWithPrevDeps from '../../hooks/useEffectWithPrevDeps';
|
import useEffectWithPrevDeps from '../../hooks/useEffectWithPrevDeps';
|
||||||
import useHeavyAnimationCheck, { isHeavyAnimating } from '../../hooks/useHeavyAnimationCheck';
|
import useHeavyAnimationCheck, { isHeavyAnimating } from '../../hooks/useHeavyAnimationCheck';
|
||||||
import useLastCallback from '../../hooks/useLastCallback';
|
import useLastCallback from '../../hooks/useLastCallback';
|
||||||
@ -25,6 +24,7 @@ import { useStateRef } from '../../hooks/useStateRef';
|
|||||||
import useSyncEffect from '../../hooks/useSyncEffect';
|
import useSyncEffect from '../../hooks/useSyncEffect';
|
||||||
import useThrottledCallback from '../../hooks/useThrottledCallback';
|
import useThrottledCallback from '../../hooks/useThrottledCallback';
|
||||||
import useUniqueId from '../../hooks/useUniqueId';
|
import useUniqueId from '../../hooks/useUniqueId';
|
||||||
|
import useBackgroundMode, { isBackgroundModeActive } from '../../hooks/window/useBackgroundMode';
|
||||||
|
|
||||||
export type OwnProps = {
|
export type OwnProps = {
|
||||||
ref?: RefObject<HTMLDivElement>;
|
ref?: RefObject<HTMLDivElement>;
|
||||||
|
|||||||
@ -8,9 +8,10 @@ import type { AvatarSize } from './Avatar';
|
|||||||
|
|
||||||
import { selectPeerStories, selectTheme, selectUser } from '../../global/selectors';
|
import { selectPeerStories, selectTheme, selectUser } from '../../global/selectors';
|
||||||
import buildClassName from '../../util/buildClassName';
|
import buildClassName from '../../util/buildClassName';
|
||||||
import { DPR } from '../../util/windowEnvironment';
|
|
||||||
import { REM } from './helpers/mediaDimensions';
|
import { REM } from './helpers/mediaDimensions';
|
||||||
|
|
||||||
|
import useDevicePixelRatio from '../../hooks/window/useDevicePixelRatio';
|
||||||
|
|
||||||
interface OwnProps {
|
interface OwnProps {
|
||||||
// eslint-disable-next-line react/no-unused-prop-types
|
// eslint-disable-next-line react/no-unused-prop-types
|
||||||
peerId: string;
|
peerId: string;
|
||||||
@ -27,15 +28,15 @@ interface StateProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const SIZES: Record<AvatarSize, number> = {
|
const SIZES: Record<AvatarSize, number> = {
|
||||||
micro: 1.125 * DPR * REM,
|
micro: 1.125 * REM,
|
||||||
tiny: 2.125 * DPR * REM,
|
tiny: 2.125 * REM,
|
||||||
mini: 1.625 * DPR * REM,
|
mini: 1.625 * REM,
|
||||||
small: 2.25 * DPR * REM,
|
small: 2.25 * REM,
|
||||||
'small-mobile': 2.625 * DPR * REM,
|
'small-mobile': 2.625 * REM,
|
||||||
medium: 2.875 * DPR * REM,
|
medium: 2.875 * REM,
|
||||||
large: 3.5 * DPR * REM,
|
large: 3.5 * REM,
|
||||||
giant: 5.125 * DPR * REM,
|
giant: 5.125 * REM,
|
||||||
jumbo: 7.625 * DPR * REM,
|
jumbo: 7.625 * REM,
|
||||||
};
|
};
|
||||||
|
|
||||||
const BLUE = ['#34C578', '#3CA3F3'];
|
const BLUE = ['#34C578', '#3CA3F3'];
|
||||||
@ -43,8 +44,8 @@ const GREEN = ['#C9EB38', '#09C167'];
|
|||||||
const PURPLE = ['#A667FF', '#55A5FF'];
|
const PURPLE = ['#A667FF', '#55A5FF'];
|
||||||
const GRAY = '#C4C9CC';
|
const GRAY = '#C4C9CC';
|
||||||
const DARK_GRAY = '#737373';
|
const DARK_GRAY = '#737373';
|
||||||
const STROKE_WIDTH = 0.125 * DPR * REM;
|
const STROKE_WIDTH = 0.125 * REM;
|
||||||
const STROKE_WIDTH_READ = 0.0625 * DPR * REM;
|
const STROKE_WIDTH_READ = 0.0625 * REM;
|
||||||
const GAP_PERCENT = 2;
|
const GAP_PERCENT = 2;
|
||||||
const SEGMENTS_MAX = 45; // More than this breaks rendering in Safari and Chrome
|
const SEGMENTS_MAX = 45; // More than this breaks rendering in Safari and Chrome
|
||||||
|
|
||||||
@ -66,6 +67,8 @@ function AvatarStoryCircle({
|
|||||||
// eslint-disable-next-line no-null/no-null
|
// eslint-disable-next-line no-null/no-null
|
||||||
const ref = useRef<HTMLCanvasElement>(null);
|
const ref = useRef<HTMLCanvasElement>(null);
|
||||||
|
|
||||||
|
const dpr = useDevicePixelRatio();
|
||||||
|
|
||||||
const values = useMemo(() => {
|
const values = useMemo(() => {
|
||||||
return (storyIds || []).reduce((acc, id) => {
|
return (storyIds || []).reduce((acc, id) => {
|
||||||
acc.total += 1;
|
acc.total += 1;
|
||||||
@ -84,20 +87,21 @@ function AvatarStoryCircle({
|
|||||||
|
|
||||||
drawGradientCircle({
|
drawGradientCircle({
|
||||||
canvas: ref.current,
|
canvas: ref.current,
|
||||||
size: SIZES[size],
|
size: SIZES[size] * dpr,
|
||||||
segmentsCount: values.total,
|
segmentsCount: values.total,
|
||||||
color: isCloseFriend ? 'green' : 'blue',
|
color: isCloseFriend ? 'green' : 'blue',
|
||||||
readSegmentsCount: values.read,
|
readSegmentsCount: values.read,
|
||||||
withExtraGap,
|
withExtraGap,
|
||||||
readSegmentColor: appTheme === 'dark' ? DARK_GRAY : GRAY,
|
readSegmentColor: appTheme === 'dark' ? DARK_GRAY : GRAY,
|
||||||
|
dpr,
|
||||||
});
|
});
|
||||||
}, [appTheme, isCloseFriend, size, values.read, values.total, withExtraGap]);
|
}, [appTheme, isCloseFriend, size, values.read, values.total, withExtraGap, dpr]);
|
||||||
|
|
||||||
if (!values.total) {
|
if (!values.total) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
const maxSize = SIZES[size] / DPR;
|
const maxSize = SIZES[size];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<canvas
|
<canvas
|
||||||
@ -129,6 +133,7 @@ export function drawGradientCircle({
|
|||||||
readSegmentsCount = 0,
|
readSegmentsCount = 0,
|
||||||
withExtraGap = false,
|
withExtraGap = false,
|
||||||
readSegmentColor,
|
readSegmentColor,
|
||||||
|
dpr,
|
||||||
}: {
|
}: {
|
||||||
canvas: HTMLCanvasElement;
|
canvas: HTMLCanvasElement;
|
||||||
size: number;
|
size: number;
|
||||||
@ -137,6 +142,7 @@ export function drawGradientCircle({
|
|||||||
readSegmentsCount?: number;
|
readSegmentsCount?: number;
|
||||||
withExtraGap?: boolean;
|
withExtraGap?: boolean;
|
||||||
readSegmentColor: string;
|
readSegmentColor: string;
|
||||||
|
dpr: number;
|
||||||
}) {
|
}) {
|
||||||
if (segmentsCount > SEGMENTS_MAX) {
|
if (segmentsCount > SEGMENTS_MAX) {
|
||||||
readSegmentsCount = Math.round(readSegmentsCount * (SEGMENTS_MAX / segmentsCount));
|
readSegmentsCount = Math.round(readSegmentsCount * (SEGMENTS_MAX / segmentsCount));
|
||||||
@ -144,7 +150,7 @@ export function drawGradientCircle({
|
|||||||
segmentsCount = SEGMENTS_MAX;
|
segmentsCount = SEGMENTS_MAX;
|
||||||
}
|
}
|
||||||
|
|
||||||
const strokeModifier = Math.max(Math.max(size - SIZES.large, 0) / DPR / REM / 1.5, 1);
|
const strokeModifier = Math.max(Math.max(size - SIZES.large * dpr, 0) / REM / 1.5, 1);
|
||||||
|
|
||||||
const ctx = canvas.getContext('2d');
|
const ctx = canvas.getContext('2d');
|
||||||
if (!ctx) {
|
if (!ctx) {
|
||||||
|
|||||||
@ -28,7 +28,7 @@ import useLang from '../../hooks/useLang';
|
|||||||
import useLastCallback from '../../hooks/useLastCallback';
|
import useLastCallback from '../../hooks/useLastCallback';
|
||||||
import useMediaTransition from '../../hooks/useMediaTransition';
|
import useMediaTransition from '../../hooks/useMediaTransition';
|
||||||
import useResizeObserver from '../../hooks/useResizeObserver';
|
import useResizeObserver from '../../hooks/useResizeObserver';
|
||||||
import useWindowSize from '../../hooks/useWindowSize';
|
import useWindowSize from '../../hooks/window/useWindowSize';
|
||||||
|
|
||||||
import Button from '../ui/Button';
|
import Button from '../ui/Button';
|
||||||
import ConfirmDialog from '../ui/ConfirmDialog';
|
import ConfirmDialog from '../ui/ConfirmDialog';
|
||||||
|
|||||||
@ -20,6 +20,7 @@ import useMedia from '../../hooks/useMedia';
|
|||||||
import useMediaTransition from '../../hooks/useMediaTransition';
|
import useMediaTransition from '../../hooks/useMediaTransition';
|
||||||
import useThumbnail from '../../hooks/useThumbnail';
|
import useThumbnail from '../../hooks/useThumbnail';
|
||||||
import useUniqueId from '../../hooks/useUniqueId';
|
import useUniqueId from '../../hooks/useUniqueId';
|
||||||
|
import useDevicePixelRatio from '../../hooks/window/useDevicePixelRatio';
|
||||||
|
|
||||||
import OptimizedVideo from '../ui/OptimizedVideo';
|
import OptimizedVideo from '../ui/OptimizedVideo';
|
||||||
import AnimatedSticker from './AnimatedSticker';
|
import AnimatedSticker from './AnimatedSticker';
|
||||||
@ -87,6 +88,8 @@ const StickerView: FC<OwnProps> = ({
|
|||||||
const isStatic = !isLottie && !isVideo;
|
const isStatic = !isLottie && !isVideo;
|
||||||
const previewMediaHash = getStickerPreviewHash(sticker.id);
|
const previewMediaHash = getStickerPreviewHash(sticker.id);
|
||||||
|
|
||||||
|
const dpr = useDevicePixelRatio();
|
||||||
|
|
||||||
const filterStyle = useColorFilter(customColor);
|
const filterStyle = useColorFilter(customColor);
|
||||||
|
|
||||||
const isIntersectingForLoading = useIsIntersecting(containerRef, observeIntersectionForLoading);
|
const isIntersectingForLoading = useIsIntersecting(containerRef, observeIntersectionForLoading);
|
||||||
@ -133,6 +136,7 @@ const StickerView: FC<OwnProps> = ({
|
|||||||
id,
|
id,
|
||||||
size,
|
size,
|
||||||
(withSharedAnimation ? customColor : undefined),
|
(withSharedAnimation ? customColor : undefined),
|
||||||
|
dpr,
|
||||||
].filter(Boolean).join('_');
|
].filter(Boolean).join('_');
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@ -9,7 +9,7 @@ import { copyTextToClipboard } from '../../../util/clipboard';
|
|||||||
import { areLinesWrapping } from '../helpers/renderText';
|
import { areLinesWrapping } from '../helpers/renderText';
|
||||||
|
|
||||||
import useLang from '../../../hooks/useLang';
|
import useLang from '../../../hooks/useLang';
|
||||||
import useWindowSize from '../../../hooks/useWindowSize';
|
import useWindowSize from '../../../hooks/window/useWindowSize';
|
||||||
|
|
||||||
import styles from './CodeOverlay.module.scss';
|
import styles from './CodeOverlay.module.scss';
|
||||||
|
|
||||||
|
|||||||
@ -29,10 +29,10 @@ import useAppLayout from '../../../hooks/useAppLayout';
|
|||||||
import useConnectionStatus from '../../../hooks/useConnectionStatus';
|
import useConnectionStatus from '../../../hooks/useConnectionStatus';
|
||||||
import useElectronDrag from '../../../hooks/useElectronDrag';
|
import useElectronDrag from '../../../hooks/useElectronDrag';
|
||||||
import useFlag from '../../../hooks/useFlag';
|
import useFlag from '../../../hooks/useFlag';
|
||||||
import { useFullscreenStatus } from '../../../hooks/useFullscreen';
|
|
||||||
import { useHotkeys } from '../../../hooks/useHotkeys';
|
import { useHotkeys } from '../../../hooks/useHotkeys';
|
||||||
import useLang from '../../../hooks/useLang';
|
import useLang from '../../../hooks/useLang';
|
||||||
import useLastCallback from '../../../hooks/useLastCallback';
|
import useLastCallback from '../../../hooks/useLastCallback';
|
||||||
|
import { useFullscreenStatus } from '../../../hooks/window/useFullscreen';
|
||||||
import useLeftHeaderButtonRtlForumTransition from './hooks/useLeftHeaderButtonRtlForumTransition';
|
import useLeftHeaderButtonRtlForumTransition from './hooks/useLeftHeaderButtonRtlForumTransition';
|
||||||
|
|
||||||
import PickerSelectedItem from '../../common/PickerSelectedItem';
|
import PickerSelectedItem from '../../common/PickerSelectedItem';
|
||||||
|
|||||||
@ -12,7 +12,7 @@ import { pick } from '../../util/iteratees';
|
|||||||
import useAppLayout from '../../hooks/useAppLayout';
|
import useAppLayout from '../../hooks/useAppLayout';
|
||||||
import useForceUpdate from '../../hooks/useForceUpdate';
|
import useForceUpdate from '../../hooks/useForceUpdate';
|
||||||
import useSyncEffect from '../../hooks/useSyncEffect';
|
import useSyncEffect from '../../hooks/useSyncEffect';
|
||||||
import useWindowSize from '../../hooks/useWindowSize';
|
import useWindowSize from '../../hooks/window/useWindowSize';
|
||||||
|
|
||||||
import styles from './ConfettiContainer.module.scss';
|
import styles from './ConfettiContainer.module.scss';
|
||||||
|
|
||||||
|
|||||||
@ -50,10 +50,7 @@ import updateIcon from '../../util/updateIcon';
|
|||||||
import { IS_ANDROID, IS_ELECTRON } from '../../util/windowEnvironment';
|
import { IS_ANDROID, IS_ELECTRON } from '../../util/windowEnvironment';
|
||||||
|
|
||||||
import useAppLayout from '../../hooks/useAppLayout';
|
import useAppLayout from '../../hooks/useAppLayout';
|
||||||
import useBackgroundMode from '../../hooks/useBackgroundMode';
|
|
||||||
import useBeforeUnload from '../../hooks/useBeforeUnload';
|
|
||||||
import useForceUpdate from '../../hooks/useForceUpdate';
|
import useForceUpdate from '../../hooks/useForceUpdate';
|
||||||
import { useFullscreenStatus } from '../../hooks/useFullscreen';
|
|
||||||
import { dispatchHeavyAnimationEvent } from '../../hooks/useHeavyAnimationCheck';
|
import { dispatchHeavyAnimationEvent } from '../../hooks/useHeavyAnimationCheck';
|
||||||
import useInterval from '../../hooks/useInterval';
|
import useInterval from '../../hooks/useInterval';
|
||||||
import useLastCallback from '../../hooks/useLastCallback';
|
import useLastCallback from '../../hooks/useLastCallback';
|
||||||
@ -61,6 +58,9 @@ import usePreventPinchZoomGesture from '../../hooks/usePreventPinchZoomGesture';
|
|||||||
import useShowTransition from '../../hooks/useShowTransition';
|
import useShowTransition from '../../hooks/useShowTransition';
|
||||||
import useSyncEffect from '../../hooks/useSyncEffect';
|
import useSyncEffect from '../../hooks/useSyncEffect';
|
||||||
import useTimeout from '../../hooks/useTimeout';
|
import useTimeout from '../../hooks/useTimeout';
|
||||||
|
import useBackgroundMode from '../../hooks/window/useBackgroundMode';
|
||||||
|
import useBeforeUnload from '../../hooks/window/useBeforeUnload';
|
||||||
|
import { useFullscreenStatus } from '../../hooks/window/useFullscreen';
|
||||||
|
|
||||||
import ActiveCallHeader from '../calls/ActiveCallHeader.async';
|
import ActiveCallHeader from '../calls/ActiveCallHeader.async';
|
||||||
import GroupCall from '../calls/group/GroupCall.async';
|
import GroupCall from '../calls/group/GroupCall.async';
|
||||||
|
|||||||
@ -5,11 +5,11 @@ import type { ApiUser } from '../../../../api/types';
|
|||||||
|
|
||||||
import { selectUser } from '../../../../global/selectors';
|
import { selectUser } from '../../../../global/selectors';
|
||||||
import buildClassName from '../../../../util/buildClassName';
|
import buildClassName from '../../../../util/buildClassName';
|
||||||
import { DPR } from '../../../../util/windowEnvironment';
|
|
||||||
import { REM } from '../../../common/helpers/mediaDimensions';
|
import { REM } from '../../../common/helpers/mediaDimensions';
|
||||||
|
|
||||||
import useLang from '../../../../hooks/useLang';
|
import useLang from '../../../../hooks/useLang';
|
||||||
import useScrolledState from '../../../../hooks/useScrolledState';
|
import useScrolledState from '../../../../hooks/useScrolledState';
|
||||||
|
import useDevicePixelRatio from '../../../../hooks/window/useDevicePixelRatio';
|
||||||
|
|
||||||
import Avatar from '../../../common/Avatar';
|
import Avatar from '../../../common/Avatar';
|
||||||
import { drawGradientCircle } from '../../../common/AvatarStoryCircle';
|
import { drawGradientCircle } from '../../../common/AvatarStoryCircle';
|
||||||
@ -53,7 +53,7 @@ const STORY_FEATURE_ICONS = {
|
|||||||
|
|
||||||
const STORY_FEATURE_ORDER = Object.keys(STORY_FEATURE_TITLES) as (keyof typeof STORY_FEATURE_TITLES)[];
|
const STORY_FEATURE_ORDER = Object.keys(STORY_FEATURE_TITLES) as (keyof typeof STORY_FEATURE_TITLES)[];
|
||||||
|
|
||||||
const CIRCLE_SIZE = 5.25 * DPR * REM;
|
const CIRCLE_SIZE = 5.25 * REM;
|
||||||
const CIRCLE_SEGMENTS = 8;
|
const CIRCLE_SEGMENTS = 8;
|
||||||
const CIRCLE_READ_SEGMENTS = 0;
|
const CIRCLE_READ_SEGMENTS = 0;
|
||||||
|
|
||||||
@ -65,6 +65,8 @@ const PremiumFeaturePreviewVideo = ({
|
|||||||
|
|
||||||
const lang = useLang();
|
const lang = useLang();
|
||||||
|
|
||||||
|
const dpr = useDevicePixelRatio();
|
||||||
|
|
||||||
useLayoutEffect(() => {
|
useLayoutEffect(() => {
|
||||||
if (!circleRef.current) {
|
if (!circleRef.current) {
|
||||||
return;
|
return;
|
||||||
@ -72,17 +74,18 @@ const PremiumFeaturePreviewVideo = ({
|
|||||||
|
|
||||||
drawGradientCircle({
|
drawGradientCircle({
|
||||||
canvas: circleRef.current,
|
canvas: circleRef.current,
|
||||||
size: CIRCLE_SIZE,
|
size: CIRCLE_SIZE * dpr,
|
||||||
segmentsCount: CIRCLE_SEGMENTS,
|
segmentsCount: CIRCLE_SEGMENTS,
|
||||||
color: 'purple',
|
color: 'purple',
|
||||||
readSegmentsCount: CIRCLE_READ_SEGMENTS,
|
readSegmentsCount: CIRCLE_READ_SEGMENTS,
|
||||||
readSegmentColor: 'transparent',
|
readSegmentColor: 'transparent',
|
||||||
|
dpr,
|
||||||
});
|
});
|
||||||
}, []);
|
}, [dpr]);
|
||||||
|
|
||||||
const { handleScroll, isAtBeginning } = useScrolledState();
|
const { handleScroll, isAtBeginning } = useScrolledState();
|
||||||
|
|
||||||
const maxSize = CIRCLE_SIZE / DPR;
|
const maxSize = CIRCLE_SIZE;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.root}>
|
<div className={styles.root}>
|
||||||
|
|||||||
@ -186,18 +186,10 @@ const MediaViewer: FC<StateProps> = ({
|
|||||||
const forceUpdate = useForceUpdate();
|
const forceUpdate = useForceUpdate();
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const mql = window.matchMedia(MEDIA_VIEWER_MEDIA_QUERY);
|
const mql = window.matchMedia(MEDIA_VIEWER_MEDIA_QUERY);
|
||||||
if (typeof mql.addEventListener === 'function') {
|
mql.addEventListener('change', forceUpdate);
|
||||||
mql.addEventListener('change', forceUpdate);
|
|
||||||
} else if (typeof mql.addListener === 'function') {
|
|
||||||
mql.addListener(forceUpdate);
|
|
||||||
}
|
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
if (typeof mql.removeEventListener === 'function') {
|
mql.removeEventListener('change', forceUpdate);
|
||||||
mql.removeEventListener('change', forceUpdate);
|
|
||||||
} else if (typeof mql.removeListener === 'function') {
|
|
||||||
mql.removeListener(forceUpdate);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}, [forceUpdate]);
|
}, [forceUpdate]);
|
||||||
|
|
||||||
|
|||||||
@ -20,14 +20,14 @@ import { IS_IOS, IS_TOUCH_ENV } from '../../util/windowEnvironment';
|
|||||||
|
|
||||||
import useDebouncedCallback from '../../hooks/useDebouncedCallback';
|
import useDebouncedCallback from '../../hooks/useDebouncedCallback';
|
||||||
import useDerivedState from '../../hooks/useDerivedState';
|
import useDerivedState from '../../hooks/useDerivedState';
|
||||||
import { useFullscreenStatus } from '../../hooks/useFullscreen';
|
|
||||||
import useHistoryBack from '../../hooks/useHistoryBack';
|
import useHistoryBack from '../../hooks/useHistoryBack';
|
||||||
import useLang from '../../hooks/useLang';
|
import useLang from '../../hooks/useLang';
|
||||||
import useLastCallback from '../../hooks/useLastCallback';
|
import useLastCallback from '../../hooks/useLastCallback';
|
||||||
import useSignal from '../../hooks/useSignal';
|
import useSignal from '../../hooks/useSignal';
|
||||||
import { useSignalRef } from '../../hooks/useSignalRef';
|
import { useSignalRef } from '../../hooks/useSignalRef';
|
||||||
import useTimeout from '../../hooks/useTimeout';
|
import useTimeout from '../../hooks/useTimeout';
|
||||||
import useWindowSize from '../../hooks/useWindowSize';
|
import { useFullscreenStatus } from '../../hooks/window/useFullscreen';
|
||||||
|
import useWindowSize from '../../hooks/window/useWindowSize';
|
||||||
import useControlsSignal from './hooks/useControlsSignal';
|
import useControlsSignal from './hooks/useControlsSignal';
|
||||||
import useZoomChange from './hooks/useZoomChangeSignal';
|
import useZoomChange from './hooks/useZoomChangeSignal';
|
||||||
|
|
||||||
|
|||||||
@ -15,11 +15,11 @@ import useUnsupportedMedia from '../../hooks/media/useUnsupportedMedia';
|
|||||||
import useAppLayout from '../../hooks/useAppLayout';
|
import useAppLayout from '../../hooks/useAppLayout';
|
||||||
import useBuffering from '../../hooks/useBuffering';
|
import useBuffering from '../../hooks/useBuffering';
|
||||||
import useCurrentTimeSignal from '../../hooks/useCurrentTimeSignal';
|
import useCurrentTimeSignal from '../../hooks/useCurrentTimeSignal';
|
||||||
import useFullscreen from '../../hooks/useFullscreen';
|
|
||||||
import useLastCallback from '../../hooks/useLastCallback';
|
import useLastCallback from '../../hooks/useLastCallback';
|
||||||
import usePictureInPicture from '../../hooks/usePictureInPicture';
|
import usePictureInPicture from '../../hooks/usePictureInPicture';
|
||||||
import useShowTransition from '../../hooks/useShowTransition';
|
import useShowTransition from '../../hooks/useShowTransition';
|
||||||
import useVideoCleanup from '../../hooks/useVideoCleanup';
|
import useVideoCleanup from '../../hooks/useVideoCleanup';
|
||||||
|
import useFullscreen from '../../hooks/window/useFullscreen';
|
||||||
import useControlsSignal from './hooks/useControlsSignal';
|
import useControlsSignal from './hooks/useControlsSignal';
|
||||||
import useVideoWaitingSignal from './hooks/useVideoWaitingSignal';
|
import useVideoWaitingSignal from './hooks/useVideoWaitingSignal';
|
||||||
|
|
||||||
|
|||||||
@ -58,7 +58,6 @@ import { debounce, onTickEnd } from '../../util/schedulers';
|
|||||||
import { groupMessages } from './helpers/groupMessages';
|
import { groupMessages } from './helpers/groupMessages';
|
||||||
import { preventMessageInputBlur } from './helpers/preventMessageInputBlur';
|
import { preventMessageInputBlur } from './helpers/preventMessageInputBlur';
|
||||||
|
|
||||||
import { isBackgroundModeActive } from '../../hooks/useBackgroundMode';
|
|
||||||
import useEffectWithPrevDeps from '../../hooks/useEffectWithPrevDeps';
|
import useEffectWithPrevDeps from '../../hooks/useEffectWithPrevDeps';
|
||||||
import { dispatchHeavyAnimationEvent } from '../../hooks/useHeavyAnimationCheck';
|
import { dispatchHeavyAnimationEvent } from '../../hooks/useHeavyAnimationCheck';
|
||||||
import useInterval from '../../hooks/useInterval';
|
import useInterval from '../../hooks/useInterval';
|
||||||
@ -67,6 +66,7 @@ import useLayoutEffectWithPrevDeps from '../../hooks/useLayoutEffectWithPrevDeps
|
|||||||
import useNativeCopySelectedMessages from '../../hooks/useNativeCopySelectedMessages';
|
import useNativeCopySelectedMessages from '../../hooks/useNativeCopySelectedMessages';
|
||||||
import { useStateRef } from '../../hooks/useStateRef';
|
import { useStateRef } from '../../hooks/useStateRef';
|
||||||
import useSyncEffect from '../../hooks/useSyncEffect';
|
import useSyncEffect from '../../hooks/useSyncEffect';
|
||||||
|
import { isBackgroundModeActive } from '../../hooks/window/useBackgroundMode';
|
||||||
import useContainerHeight from './hooks/useContainerHeight';
|
import useContainerHeight from './hooks/useContainerHeight';
|
||||||
import useStickyDates from './hooks/useStickyDates';
|
import useStickyDates from './hooks/useStickyDates';
|
||||||
|
|
||||||
|
|||||||
@ -13,11 +13,11 @@ import {
|
|||||||
import { selectBot, selectUserFullInfo } from '../../global/selectors';
|
import { selectBot, selectUserFullInfo } from '../../global/selectors';
|
||||||
import buildClassName from '../../util/buildClassName';
|
import buildClassName from '../../util/buildClassName';
|
||||||
import buildStyle from '../../util/buildStyle';
|
import buildStyle from '../../util/buildStyle';
|
||||||
import { DPR } from '../../util/windowEnvironment';
|
|
||||||
import renderText from '../common/helpers/renderText';
|
import renderText from '../common/helpers/renderText';
|
||||||
|
|
||||||
import useLang from '../../hooks/useLang';
|
import useLang from '../../hooks/useLang';
|
||||||
import useMedia from '../../hooks/useMedia';
|
import useMedia from '../../hooks/useMedia';
|
||||||
|
import useDevicePixelRatio from '../../hooks/window/useDevicePixelRatio';
|
||||||
|
|
||||||
import OptimizedVideo from '../ui/OptimizedVideo';
|
import OptimizedVideo from '../ui/OptimizedVideo';
|
||||||
import Skeleton from '../ui/placeholder/Skeleton';
|
import Skeleton from '../ui/placeholder/Skeleton';
|
||||||
@ -40,14 +40,15 @@ const MessageListBotInfo: FC<OwnProps & StateProps> = ({
|
|||||||
isInMessageList,
|
isInMessageList,
|
||||||
}) => {
|
}) => {
|
||||||
const lang = useLang();
|
const lang = useLang();
|
||||||
|
const dpr = useDevicePixelRatio();
|
||||||
|
|
||||||
const botInfoPhotoUrl = useMedia(botInfo?.photo ? getBotCoverMediaHash(botInfo.photo) : undefined);
|
const botInfoPhotoUrl = useMedia(botInfo?.photo ? getBotCoverMediaHash(botInfo.photo) : undefined);
|
||||||
const botInfoGifUrl = useMedia(botInfo?.gif ? getDocumentMediaHash(botInfo.gif) : undefined);
|
const botInfoGifUrl = useMedia(botInfo?.gif ? getDocumentMediaHash(botInfo.gif) : undefined);
|
||||||
const botInfoDimensions = botInfo?.photo ? getPhotoFullDimensions(botInfo.photo) : botInfo?.gif
|
const botInfoDimensions = botInfo?.photo ? getPhotoFullDimensions(botInfo.photo) : botInfo?.gif
|
||||||
? getVideoDimensions(botInfo.gif) : undefined;
|
? getVideoDimensions(botInfo.gif) : undefined;
|
||||||
const botInfoRealDimensions = botInfoDimensions && {
|
const botInfoRealDimensions = botInfoDimensions && {
|
||||||
width: botInfoDimensions.width / DPR,
|
width: botInfoDimensions.width / dpr,
|
||||||
height: botInfoDimensions.height / DPR,
|
height: botInfoDimensions.height / dpr,
|
||||||
};
|
};
|
||||||
const isBotInfoEmpty = botInfo && !botInfo.description && !botInfo.gif && !botInfo.photo;
|
const isBotInfoEmpty = botInfo && !botInfo.description && !botInfo.gif && !botInfo.photo;
|
||||||
|
|
||||||
|
|||||||
@ -72,7 +72,7 @@ import usePrevDuringAnimation from '../../hooks/usePrevDuringAnimation';
|
|||||||
import usePrevious from '../../hooks/usePrevious';
|
import usePrevious from '../../hooks/usePrevious';
|
||||||
import { useResize } from '../../hooks/useResize';
|
import { useResize } from '../../hooks/useResize';
|
||||||
import useSyncEffect from '../../hooks/useSyncEffect';
|
import useSyncEffect from '../../hooks/useSyncEffect';
|
||||||
import useWindowSize from '../../hooks/useWindowSize';
|
import useWindowSize from '../../hooks/window/useWindowSize';
|
||||||
import usePinnedMessage from './hooks/usePinnedMessage';
|
import usePinnedMessage from './hooks/usePinnedMessage';
|
||||||
|
|
||||||
import Composer from '../common/Composer';
|
import Composer from '../common/Composer';
|
||||||
|
|||||||
@ -62,7 +62,7 @@ import useLang from '../../hooks/useLang';
|
|||||||
import useLastCallback from '../../hooks/useLastCallback';
|
import useLastCallback from '../../hooks/useLastCallback';
|
||||||
import usePrevious from '../../hooks/usePrevious';
|
import usePrevious from '../../hooks/usePrevious';
|
||||||
import useShowTransition from '../../hooks/useShowTransition';
|
import useShowTransition from '../../hooks/useShowTransition';
|
||||||
import useWindowSize from '../../hooks/useWindowSize';
|
import useWindowSize from '../../hooks/window/useWindowSize';
|
||||||
|
|
||||||
import GroupCallTopPane from '../calls/group/GroupCallTopPane';
|
import GroupCallTopPane from '../calls/group/GroupCallTopPane';
|
||||||
import GroupChatInfo from '../common/GroupChatInfo';
|
import GroupChatInfo from '../common/GroupChatInfo';
|
||||||
|
|||||||
@ -15,12 +15,12 @@ import parseHtmlAsFormattedText from '../../../../util/parseHtmlAsFormattedText'
|
|||||||
import { IS_TOUCH_ENV } from '../../../../util/windowEnvironment';
|
import { IS_TOUCH_ENV } from '../../../../util/windowEnvironment';
|
||||||
import { getTextWithEntitiesAsHtml } from '../../../common/helpers/renderTextWithEntities';
|
import { getTextWithEntitiesAsHtml } from '../../../common/helpers/renderTextWithEntities';
|
||||||
|
|
||||||
import useBackgroundMode from '../../../../hooks/useBackgroundMode';
|
|
||||||
import useBeforeUnload from '../../../../hooks/useBeforeUnload';
|
|
||||||
import useLastCallback from '../../../../hooks/useLastCallback';
|
import useLastCallback from '../../../../hooks/useLastCallback';
|
||||||
import useLayoutEffectWithPrevDeps from '../../../../hooks/useLayoutEffectWithPrevDeps';
|
import useLayoutEffectWithPrevDeps from '../../../../hooks/useLayoutEffectWithPrevDeps';
|
||||||
import useRunDebounced from '../../../../hooks/useRunDebounced';
|
import useRunDebounced from '../../../../hooks/useRunDebounced';
|
||||||
import { useStateRef } from '../../../../hooks/useStateRef';
|
import { useStateRef } from '../../../../hooks/useStateRef';
|
||||||
|
import useBackgroundMode from '../../../../hooks/window/useBackgroundMode';
|
||||||
|
import useBeforeUnload from '../../../../hooks/window/useBeforeUnload';
|
||||||
|
|
||||||
let isFrozen = false;
|
let isFrozen = false;
|
||||||
|
|
||||||
|
|||||||
@ -14,11 +14,11 @@ import parseHtmlAsFormattedText from '../../../../util/parseHtmlAsFormattedText'
|
|||||||
import { getTextWithEntitiesAsHtml } from '../../../common/helpers/renderTextWithEntities';
|
import { getTextWithEntitiesAsHtml } from '../../../common/helpers/renderTextWithEntities';
|
||||||
|
|
||||||
import { useDebouncedResolver } from '../../../../hooks/useAsyncResolvers';
|
import { useDebouncedResolver } from '../../../../hooks/useAsyncResolvers';
|
||||||
import useBackgroundMode from '../../../../hooks/useBackgroundMode';
|
|
||||||
import useBeforeUnload from '../../../../hooks/useBeforeUnload';
|
|
||||||
import useDerivedSignal from '../../../../hooks/useDerivedSignal';
|
import useDerivedSignal from '../../../../hooks/useDerivedSignal';
|
||||||
import useEffectWithPrevDeps from '../../../../hooks/useEffectWithPrevDeps';
|
import useEffectWithPrevDeps from '../../../../hooks/useEffectWithPrevDeps';
|
||||||
import useLastCallback from '../../../../hooks/useLastCallback';
|
import useLastCallback from '../../../../hooks/useLastCallback';
|
||||||
|
import useBackgroundMode from '../../../../hooks/window/useBackgroundMode';
|
||||||
|
import useBeforeUnload from '../../../../hooks/window/useBeforeUnload';
|
||||||
|
|
||||||
const URL_ENTITIES = new Set<string>([ApiMessageEntityTypes.TextUrl, ApiMessageEntityTypes.Url]);
|
const URL_ENTITIES = new Set<string>([ApiMessageEntityTypes.TextUrl, ApiMessageEntityTypes.Url]);
|
||||||
const DEBOUNCE_MS = 300;
|
const DEBOUNCE_MS = 300;
|
||||||
|
|||||||
@ -20,11 +20,12 @@ import { REM } from '../../../common/helpers/mediaDimensions';
|
|||||||
|
|
||||||
import useColorFilter from '../../../../hooks/stickers/useColorFilter';
|
import useColorFilter from '../../../../hooks/stickers/useColorFilter';
|
||||||
import useDynamicColorListener from '../../../../hooks/stickers/useDynamicColorListener';
|
import useDynamicColorListener from '../../../../hooks/stickers/useDynamicColorListener';
|
||||||
import useBackgroundMode from '../../../../hooks/useBackgroundMode';
|
|
||||||
import useEffectWithPrevDeps from '../../../../hooks/useEffectWithPrevDeps';
|
import useEffectWithPrevDeps from '../../../../hooks/useEffectWithPrevDeps';
|
||||||
import useLastCallback from '../../../../hooks/useLastCallback';
|
import useLastCallback from '../../../../hooks/useLastCallback';
|
||||||
import useResizeObserver from '../../../../hooks/useResizeObserver';
|
import useResizeObserver from '../../../../hooks/useResizeObserver';
|
||||||
import useThrottledCallback from '../../../../hooks/useThrottledCallback';
|
import useThrottledCallback from '../../../../hooks/useThrottledCallback';
|
||||||
|
import useBackgroundMode from '../../../../hooks/window/useBackgroundMode';
|
||||||
|
import useDevicePixelRatio from '../../../../hooks/window/useDevicePixelRatio';
|
||||||
|
|
||||||
const SIZE = 1.25 * REM;
|
const SIZE = 1.25 * REM;
|
||||||
const THROTTLE_MS = 300;
|
const THROTTLE_MS = 300;
|
||||||
@ -49,6 +50,7 @@ export default function useInputCustomEmojis(
|
|||||||
) {
|
) {
|
||||||
const customColor = useDynamicColorListener(inputRef, !isReady);
|
const customColor = useDynamicColorListener(inputRef, !isReady);
|
||||||
const colorFilter = useColorFilter(customColor, true);
|
const colorFilter = useColorFilter(customColor, true);
|
||||||
|
const dpr = useDevicePixelRatio();
|
||||||
const playersById = useRef<Map<string, CustomEmojiPlayer>>(new Map());
|
const playersById = useRef<Map<string, CustomEmojiPlayer>>(new Map());
|
||||||
|
|
||||||
const clearPlayers = useLastCallback((ids: string[]) => {
|
const clearPlayers = useLastCallback((ids: string[]) => {
|
||||||
@ -99,7 +101,7 @@ export default function useInputCustomEmojis(
|
|||||||
}
|
}
|
||||||
const isHq = customEmoji?.stickerSetInfo && selectIsAlwaysHighPriorityEmoji(global, customEmoji.stickerSetInfo);
|
const isHq = customEmoji?.stickerSetInfo && selectIsAlwaysHighPriorityEmoji(global, customEmoji.stickerSetInfo);
|
||||||
const renderId = [
|
const renderId = [
|
||||||
prefixId, documentId, customColor,
|
prefixId, documentId, customColor, dpr,
|
||||||
].filter(Boolean).join('_');
|
].filter(Boolean).join('_');
|
||||||
|
|
||||||
createPlayer({
|
createPlayer({
|
||||||
@ -159,6 +161,12 @@ export default function useInputCustomEmojis(
|
|||||||
false,
|
false,
|
||||||
);
|
);
|
||||||
useResizeObserver(sharedCanvasRef, throttledSynchronizeElements);
|
useResizeObserver(sharedCanvasRef, throttledSynchronizeElements);
|
||||||
|
useEffectWithPrevDeps(([prevDpr]) => {
|
||||||
|
if (dpr !== prevDpr) {
|
||||||
|
clearPlayers(Array.from(playersById.current.keys()));
|
||||||
|
synchronizeElements();
|
||||||
|
}
|
||||||
|
}, [dpr, synchronizeElements]);
|
||||||
|
|
||||||
const freezeAnimation = useLastCallback(() => {
|
const freezeAnimation = useLastCallback(() => {
|
||||||
playersById.current.forEach((player) => {
|
playersById.current.forEach((player) => {
|
||||||
|
|||||||
@ -7,8 +7,8 @@ import type { PinnedIntersectionChangedCallback } from './usePinnedMessage';
|
|||||||
import { IS_ANDROID } from '../../../util/windowEnvironment';
|
import { IS_ANDROID } from '../../../util/windowEnvironment';
|
||||||
|
|
||||||
import useAppLayout from '../../../hooks/useAppLayout';
|
import useAppLayout from '../../../hooks/useAppLayout';
|
||||||
import useBackgroundMode, { isBackgroundModeActive } from '../../../hooks/useBackgroundMode';
|
|
||||||
import { useIntersectionObserver } from '../../../hooks/useIntersectionObserver';
|
import { useIntersectionObserver } from '../../../hooks/useIntersectionObserver';
|
||||||
|
import useBackgroundMode, { isBackgroundModeActive } from '../../../hooks/window/useBackgroundMode';
|
||||||
|
|
||||||
const INTERSECTION_THROTTLE_FOR_READING = 150;
|
const INTERSECTION_THROTTLE_FOR_READING = 150;
|
||||||
const INTERSECTION_THROTTLE_FOR_MEDIA = IS_ANDROID ? 1000 : 350;
|
const INTERSECTION_THROTTLE_FOR_MEDIA = IS_ANDROID ? 1000 : 350;
|
||||||
|
|||||||
@ -10,7 +10,7 @@ import buildClassName from '../../../util/buildClassName';
|
|||||||
import { REM } from '../../common/helpers/mediaDimensions';
|
import { REM } from '../../common/helpers/mediaDimensions';
|
||||||
|
|
||||||
import useAppLayout from '../../../hooks/useAppLayout';
|
import useAppLayout from '../../../hooks/useAppLayout';
|
||||||
import useWindowSize from '../../../hooks/useWindowSize';
|
import useWindowSize from '../../../hooks/window/useWindowSize';
|
||||||
|
|
||||||
import ReactionEmoji from '../../common/ReactionEmoji';
|
import ReactionEmoji from '../../common/ReactionEmoji';
|
||||||
|
|
||||||
|
|||||||
@ -2,10 +2,10 @@ import { useEffect, useRef } from '../../../../lib/teact/teact';
|
|||||||
|
|
||||||
import { requestMeasure } from '../../../../lib/fasterdom/fasterdom';
|
import { requestMeasure } from '../../../../lib/fasterdom/fasterdom';
|
||||||
|
|
||||||
import useBackgroundMode, { isBackgroundModeActive } from '../../../../hooks/useBackgroundMode';
|
|
||||||
import useHeavyAnimationCheck, { isHeavyAnimating } from '../../../../hooks/useHeavyAnimationCheck';
|
import useHeavyAnimationCheck, { isHeavyAnimating } from '../../../../hooks/useHeavyAnimationCheck';
|
||||||
import useLastCallback from '../../../../hooks/useLastCallback';
|
import useLastCallback from '../../../../hooks/useLastCallback';
|
||||||
import usePriorityPlaybackCheck, { isPriorityPlaybackActive } from '../../../../hooks/usePriorityPlaybackCheck';
|
import usePriorityPlaybackCheck, { isPriorityPlaybackActive } from '../../../../hooks/usePriorityPlaybackCheck';
|
||||||
|
import useBackgroundMode, { isBackgroundModeActive } from '../../../../hooks/window/useBackgroundMode';
|
||||||
|
|
||||||
export default function useVideoAutoPause(
|
export default function useVideoAutoPause(
|
||||||
playerRef: { current: HTMLVideoElement | null }, canPlay: boolean, isPriority?: boolean,
|
playerRef: { current: HTMLVideoElement | null }, canPlay: boolean, isPriority?: boolean,
|
||||||
|
|||||||
@ -6,7 +6,7 @@ import type { WebAppInboundEvent, WebAppOutboundEvent } from '../../../../types/
|
|||||||
import { extractCurrentThemeParams } from '../../../../util/themeStyle';
|
import { extractCurrentThemeParams } from '../../../../util/themeStyle';
|
||||||
|
|
||||||
import useLastCallback from '../../../../hooks/useLastCallback';
|
import useLastCallback from '../../../../hooks/useLastCallback';
|
||||||
import useWindowSize from '../../../../hooks/useWindowSize';
|
import useWindowSize from '../../../../hooks/window/useWindowSize';
|
||||||
|
|
||||||
const SCROLLBAR_STYLE = `* {
|
const SCROLLBAR_STYLE = `* {
|
||||||
scrollbar-width: thin;
|
scrollbar-width: thin;
|
||||||
|
|||||||
@ -18,7 +18,7 @@ import useCurrentOrPrev from '../../hooks/useCurrentOrPrev';
|
|||||||
import useHistoryBack from '../../hooks/useHistoryBack';
|
import useHistoryBack from '../../hooks/useHistoryBack';
|
||||||
import useLastCallback from '../../hooks/useLastCallback';
|
import useLastCallback from '../../hooks/useLastCallback';
|
||||||
import useLayoutEffectWithPrevDeps from '../../hooks/useLayoutEffectWithPrevDeps';
|
import useLayoutEffectWithPrevDeps from '../../hooks/useLayoutEffectWithPrevDeps';
|
||||||
import useWindowSize from '../../hooks/useWindowSize';
|
import useWindowSize from '../../hooks/window/useWindowSize';
|
||||||
|
|
||||||
import Transition from '../ui/Transition';
|
import Transition from '../ui/Transition';
|
||||||
import AddChatMembers from './AddChatMembers';
|
import AddChatMembers from './AddChatMembers';
|
||||||
|
|||||||
@ -34,7 +34,6 @@ import { PRIMARY_VIDEO_MIME, SECONDARY_VIDEO_MIME } from './helpers/videoFormats
|
|||||||
|
|
||||||
import useUnsupportedMedia from '../../hooks/media/useUnsupportedMedia';
|
import useUnsupportedMedia from '../../hooks/media/useUnsupportedMedia';
|
||||||
import useAppLayout, { getIsMobile } from '../../hooks/useAppLayout';
|
import useAppLayout, { getIsMobile } from '../../hooks/useAppLayout';
|
||||||
import useBackgroundMode from '../../hooks/useBackgroundMode';
|
|
||||||
import useCanvasBlur from '../../hooks/useCanvasBlur';
|
import useCanvasBlur from '../../hooks/useCanvasBlur';
|
||||||
import useCurrentOrPrev from '../../hooks/useCurrentOrPrev';
|
import useCurrentOrPrev from '../../hooks/useCurrentOrPrev';
|
||||||
import useEffectWithPrevDeps from '../../hooks/useEffectWithPrevDeps';
|
import useEffectWithPrevDeps from '../../hooks/useEffectWithPrevDeps';
|
||||||
@ -45,6 +44,7 @@ import useLongPress from '../../hooks/useLongPress';
|
|||||||
import useMediaTransition from '../../hooks/useMediaTransition';
|
import useMediaTransition from '../../hooks/useMediaTransition';
|
||||||
import useShowTransition from '../../hooks/useShowTransition';
|
import useShowTransition from '../../hooks/useShowTransition';
|
||||||
import { useStreaming } from '../../hooks/useStreaming';
|
import { useStreaming } from '../../hooks/useStreaming';
|
||||||
|
import useBackgroundMode from '../../hooks/window/useBackgroundMode';
|
||||||
import useStoryPreloader from './hooks/useStoryPreloader';
|
import useStoryPreloader from './hooks/useStoryPreloader';
|
||||||
import useStoryProps from './hooks/useStoryProps';
|
import useStoryProps from './hooks/useStoryProps';
|
||||||
|
|
||||||
|
|||||||
@ -36,7 +36,7 @@ import useHistoryBack from '../../hooks/useHistoryBack';
|
|||||||
import useLastCallback from '../../hooks/useLastCallback';
|
import useLastCallback from '../../hooks/useLastCallback';
|
||||||
import usePrevious from '../../hooks/usePrevious';
|
import usePrevious from '../../hooks/usePrevious';
|
||||||
import useSignal from '../../hooks/useSignal';
|
import useSignal from '../../hooks/useSignal';
|
||||||
import useWindowSize from '../../hooks/useWindowSize';
|
import useWindowSize from '../../hooks/window/useWindowSize';
|
||||||
import useSlideSizes from './hooks/useSlideSizes';
|
import useSlideSizes from './hooks/useSlideSizes';
|
||||||
|
|
||||||
import Story from './Story';
|
import Story from './Story';
|
||||||
|
|||||||
@ -2,7 +2,7 @@ import { useMemo } from '../../../lib/teact/teact';
|
|||||||
|
|
||||||
import { calculateSlideSizes } from '../helpers/dimensions';
|
import { calculateSlideSizes } from '../helpers/dimensions';
|
||||||
|
|
||||||
import useWindowSize from '../../../hooks/useWindowSize';
|
import useWindowSize from '../../../hooks/window/useWindowSize';
|
||||||
|
|
||||||
export default function useSlideSizes() {
|
export default function useSlideSizes() {
|
||||||
const { width: windowWidth, height: windowHeight } = useWindowSize();
|
const { width: windowWidth, height: windowHeight } = useWindowSize();
|
||||||
|
|||||||
@ -8,7 +8,7 @@ import { requestMutation } from '../../../lib/fasterdom/fasterdom';
|
|||||||
import buildClassName from '../../../util/buildClassName';
|
import buildClassName from '../../../util/buildClassName';
|
||||||
import buildStyle from '../../../util/buildStyle';
|
import buildStyle from '../../../util/buildStyle';
|
||||||
|
|
||||||
import useWindowSize from '../../../hooks/useWindowSize';
|
import useWindowSize from '../../../hooks/window/useWindowSize';
|
||||||
|
|
||||||
import MediaAreaSuggestedReaction from './MediaAreaSuggestedReaction';
|
import MediaAreaSuggestedReaction from './MediaAreaSuggestedReaction';
|
||||||
|
|
||||||
|
|||||||
@ -4,18 +4,18 @@ import React, { memo, useEffect, useRef } from '../../lib/teact/teact';
|
|||||||
import { requestMutation } from '../../lib/fasterdom/fasterdom';
|
import { requestMutation } from '../../lib/fasterdom/fasterdom';
|
||||||
import { animate, timingFunctions } from '../../util/animation';
|
import { animate, timingFunctions } from '../../util/animation';
|
||||||
import buildClassName from '../../util/buildClassName';
|
import buildClassName from '../../util/buildClassName';
|
||||||
import { DPR } from '../../util/windowEnvironment';
|
|
||||||
|
|
||||||
import { useStateRef } from '../../hooks/useStateRef';
|
import { useStateRef } from '../../hooks/useStateRef';
|
||||||
|
import useDevicePixelRatio from '../../hooks/window/useDevicePixelRatio';
|
||||||
|
|
||||||
import './ProgressSpinner.scss';
|
import './ProgressSpinner.scss';
|
||||||
|
|
||||||
const SIZES = {
|
const SIZES = {
|
||||||
s: 42, m: 48, l: 54, xl: 52,
|
s: 42, m: 48, l: 54, xl: 52,
|
||||||
};
|
};
|
||||||
const STROKE_WIDTH = 2 * DPR;
|
const STROKE_WIDTH = 2;
|
||||||
const STROKE_WIDTH_XL = 3 * DPR;
|
const STROKE_WIDTH_XL = 3;
|
||||||
const PADDING = 2 * DPR;
|
const PADDING = 2;
|
||||||
const MIN_PROGRESS = 0.05;
|
const MIN_PROGRESS = 0.05;
|
||||||
const MAX_PROGRESS = 1;
|
const MAX_PROGRESS = 1;
|
||||||
const GROW_DURATION = 600; // 0.6 s
|
const GROW_DURATION = 600; // 0.6 s
|
||||||
@ -41,6 +41,8 @@ const ProgressSpinner: FC<{
|
|||||||
const width = SIZES[size];
|
const width = SIZES[size];
|
||||||
const progressRef = useStateRef(progress);
|
const progressRef = useStateRef(progress);
|
||||||
|
|
||||||
|
const dpr = useDevicePixelRatio();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
let isFirst = true;
|
let isFirst = true;
|
||||||
let growFrom = MIN_PROGRESS;
|
let growFrom = MIN_PROGRESS;
|
||||||
@ -65,10 +67,11 @@ const ProgressSpinner: FC<{
|
|||||||
|
|
||||||
drawSpinnerArc(
|
drawSpinnerArc(
|
||||||
canvasRef.current,
|
canvasRef.current,
|
||||||
width * DPR,
|
width * dpr,
|
||||||
size === 'xl' ? STROKE_WIDTH_XL : STROKE_WIDTH,
|
(size === 'xl' ? STROKE_WIDTH_XL : STROKE_WIDTH) * dpr,
|
||||||
'white',
|
'white',
|
||||||
currentProgress,
|
currentProgress,
|
||||||
|
dpr,
|
||||||
isFirst,
|
isFirst,
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -76,7 +79,7 @@ const ProgressSpinner: FC<{
|
|||||||
|
|
||||||
return currentProgress < 1;
|
return currentProgress < 1;
|
||||||
}, requestMutation);
|
}, requestMutation);
|
||||||
}, [progressRef, size, width]);
|
}, [progressRef, size, width, dpr]);
|
||||||
|
|
||||||
const className = buildClassName(
|
const className = buildClassName(
|
||||||
`ProgressSpinner size-${size}`,
|
`ProgressSpinner size-${size}`,
|
||||||
@ -101,10 +104,11 @@ function drawSpinnerArc(
|
|||||||
strokeWidth: number,
|
strokeWidth: number,
|
||||||
color: string,
|
color: string,
|
||||||
progress: number,
|
progress: number,
|
||||||
|
dpr: number,
|
||||||
shouldInit = false,
|
shouldInit = false,
|
||||||
) {
|
) {
|
||||||
const centerCoordinate = size / 2;
|
const centerCoordinate = size / 2;
|
||||||
const radius = (size - strokeWidth) / 2 - PADDING;
|
const radius = (size - strokeWidth) / 2 - PADDING * dpr;
|
||||||
const rotationOffset = (Date.now() % ROTATE_DURATION) / ROTATE_DURATION;
|
const rotationOffset = (Date.now() % ROTATE_DURATION) / ROTATE_DURATION;
|
||||||
const startAngle = (2 * Math.PI) * rotationOffset;
|
const startAngle = (2 * Math.PI) * rotationOffset;
|
||||||
const endAngle = startAngle + (2 * Math.PI) * progress;
|
const endAngle = startAngle + (2 * Math.PI) * progress;
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import type { GlobalState } from '../global/types';
|
import type { GlobalState } from '../global/types';
|
||||||
import type { LangFn } from './useLang';
|
import type { LangFn } from './useLang';
|
||||||
|
|
||||||
import useBrowserOnline from './useBrowserOnline';
|
import useBrowserOnline from './window/useBrowserOnline';
|
||||||
|
|
||||||
export enum ConnectionStatus {
|
export enum ConnectionStatus {
|
||||||
waitingForNetwork,
|
waitingForNetwork,
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import { useEffect } from '../lib/teact/teact';
|
import { useEffect } from '../../lib/teact/teact';
|
||||||
|
|
||||||
import { createCallbackManager } from '../util/callbacks';
|
import { createCallbackManager } from '../../util/callbacks';
|
||||||
import useLastCallback from './useLastCallback';
|
import useLastCallback from '../useLastCallback';
|
||||||
|
|
||||||
const blurCallbacks = createCallbackManager();
|
const blurCallbacks = createCallbackManager();
|
||||||
const focusCallbacks = createCallbackManager();
|
const focusCallbacks = createCallbackManager();
|
||||||
@ -1,7 +1,7 @@
|
|||||||
import { useEffect } from '../lib/teact/teact';
|
import { useEffect } from '../../lib/teact/teact';
|
||||||
|
|
||||||
import { onBeforeUnload } from '../util/schedulers';
|
import { onBeforeUnload } from '../../util/schedulers';
|
||||||
import useLastCallback from './useLastCallback';
|
import useLastCallback from '../useLastCallback';
|
||||||
|
|
||||||
export default function useBeforeUnload(callback: AnyToVoidFunction) {
|
export default function useBeforeUnload(callback: AnyToVoidFunction) {
|
||||||
const lastCallback = useLastCallback(callback);
|
const lastCallback = useLastCallback(callback);
|
||||||
@ -1,4 +1,4 @@
|
|||||||
import { useEffect, useState } from '../lib/teact/teact';
|
import { useEffect, useState } from '../../lib/teact/teact';
|
||||||
|
|
||||||
export default function useBrowserOnline() {
|
export default function useBrowserOnline() {
|
||||||
const [isOnline, setIsOnline] = useState(window.navigator.onLine);
|
const [isOnline, setIsOnline] = useState(window.navigator.onLine);
|
||||||
28
src/hooks/window/useDevicePixelRatio.ts
Normal file
28
src/hooks/window/useDevicePixelRatio.ts
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
import { useState } from '../../lib/teact/teact';
|
||||||
|
|
||||||
|
import { createCallbackManager } from '../../util/callbacks';
|
||||||
|
import useEffectOnce from '../useEffectOnce';
|
||||||
|
|
||||||
|
const callbacks = createCallbackManager();
|
||||||
|
|
||||||
|
function createListener() {
|
||||||
|
window.matchMedia(`(resolution: ${window.devicePixelRatio}dppx)`)
|
||||||
|
.addEventListener('change', callbacks.runCallbacks, { once: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function useDevicePixelRatio() {
|
||||||
|
const [dpr, setDpr] = useState(window.devicePixelRatio);
|
||||||
|
|
||||||
|
useEffectOnce(() => {
|
||||||
|
callbacks.addCallback(() => {
|
||||||
|
setDpr(window.devicePixelRatio);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return dpr;
|
||||||
|
}
|
||||||
|
|
||||||
|
createListener();
|
||||||
|
|
||||||
|
// Set up new listener for the next `devicePixelRatio` change
|
||||||
|
callbacks.addCallback(createListener);
|
||||||
@ -1,8 +1,8 @@
|
|||||||
import { useEffect, useLayoutEffect, useState } from '../lib/teact/teact';
|
import { useEffect, useLayoutEffect, useState } from '../../lib/teact/teact';
|
||||||
|
|
||||||
import { ElectronEvent } from '../types/electron';
|
import { ElectronEvent } from '../../types/electron';
|
||||||
|
|
||||||
import { IS_IOS } from '../util/windowEnvironment';
|
import { IS_IOS } from '../../util/windowEnvironment';
|
||||||
|
|
||||||
type RefType = {
|
type RefType = {
|
||||||
current: HTMLVideoElement | null;
|
current: HTMLVideoElement | null;
|
||||||
@ -1,8 +1,8 @@
|
|||||||
import { useEffect, useMemo, useState } from '../lib/teact/teact';
|
import { useEffect, useMemo, useState } from '../../lib/teact/teact';
|
||||||
|
|
||||||
import { throttle } from '../util/schedulers';
|
import { throttle } from '../../util/schedulers';
|
||||||
import windowSize from '../util/windowSize';
|
import windowSize from '../../util/windowSize';
|
||||||
import useDebouncedCallback from './useDebouncedCallback';
|
import useDebouncedCallback from '../useDebouncedCallback';
|
||||||
|
|
||||||
const THROTTLE = 250;
|
const THROTTLE = 250;
|
||||||
|
|
||||||
@ -4,8 +4,7 @@ import Deferred from '../../util/Deferred';
|
|||||||
import generateUniqueId from '../../util/generateUniqueId';
|
import generateUniqueId from '../../util/generateUniqueId';
|
||||||
import launchMediaWorkers, { MAX_WORKERS } from '../../util/launchMediaWorkers';
|
import launchMediaWorkers, { MAX_WORKERS } from '../../util/launchMediaWorkers';
|
||||||
import {
|
import {
|
||||||
DPR, IS_ANDROID, IS_IOS,
|
IS_ANDROID, IS_IOS, IS_SAFARI,
|
||||||
IS_SAFARI,
|
|
||||||
} from '../../util/windowEnvironment';
|
} from '../../util/windowEnvironment';
|
||||||
import { requestMeasure, requestMutation } from '../fasterdom/fasterdom';
|
import { requestMeasure, requestMutation } from '../fasterdom/fasterdom';
|
||||||
|
|
||||||
@ -338,7 +337,7 @@ class RLottie {
|
|||||||
} = this.params;
|
} = this.params;
|
||||||
|
|
||||||
// Reduced quality only looks acceptable on high DPR screens
|
// Reduced quality only looks acceptable on high DPR screens
|
||||||
return Math.max(DPR * quality, 1);
|
return Math.max(window.devicePixelRatio * quality, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
private destroy() {
|
private destroy() {
|
||||||
|
|||||||
@ -20,9 +20,5 @@ export function setSystemThemeChangeCallback(callback: (newTheme: ThemeKey) => v
|
|||||||
themeChangeCallback = callback;
|
themeChangeCallback = callback;
|
||||||
}
|
}
|
||||||
|
|
||||||
const mql = window.matchMedia('(prefers-color-scheme: dark)');
|
window.matchMedia('(prefers-color-scheme: dark)')
|
||||||
if (typeof mql.addEventListener === 'function') {
|
.addEventListener('change', handleSystemThemeChange);
|
||||||
mql.addEventListener('change', handleSystemThemeChange);
|
|
||||||
} else if (typeof mql.addListener === 'function') {
|
|
||||||
mql.addListener(handleSystemThemeChange);
|
|
||||||
}
|
|
||||||
|
|||||||
@ -80,8 +80,6 @@ export const IS_WEBM_SUPPORTED = Boolean(TEST_VIDEO.canPlayType('video/webm; cod
|
|||||||
|
|
||||||
export const ARE_WEBCODECS_SUPPORTED = 'VideoDecoder' in window;
|
export const ARE_WEBCODECS_SUPPORTED = 'VideoDecoder' in window;
|
||||||
|
|
||||||
export const DPR = window.devicePixelRatio || 1;
|
|
||||||
|
|
||||||
export const MASK_IMAGE_DISABLED = true;
|
export const MASK_IMAGE_DISABLED = true;
|
||||||
export const IS_OPFS_SUPPORTED = Boolean(navigator.storage?.getDirectory);
|
export const IS_OPFS_SUPPORTED = Boolean(navigator.storage?.getDirectory);
|
||||||
if (IS_OPFS_SUPPORTED) {
|
if (IS_OPFS_SUPPORTED) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user