Animated Icon: Fix progressive loading animation
This commit is contained in:
parent
f41a12a4d8
commit
8755f9db6d
@ -2,6 +2,10 @@
|
|||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
display: block !important;
|
display: block !important;
|
||||||
|
|
||||||
|
:global(.AnimatedSticker.not-shown) {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.preview {
|
.preview {
|
||||||
@ -10,4 +14,8 @@
|
|||||||
top: 0;
|
top: 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|
||||||
|
&:global(.closing) {
|
||||||
|
transition-delay: 150ms;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
import React, { memo } from '../../lib/teact/teact';
|
import React, { memo } from '../../lib/teact/teact';
|
||||||
|
|
||||||
import type { OwnProps as AnimatedIconProps } from './AnimatedIcon';
|
import type { OwnProps as AnimatedIconProps } from './AnimatedIcon';
|
||||||
|
import AnimatedIcon from './AnimatedIcon';
|
||||||
|
|
||||||
import buildClassName from '../../util/buildClassName';
|
import buildClassName from '../../util/buildClassName';
|
||||||
import buildStyle from '../../util/buildStyle';
|
import buildStyle from '../../util/buildStyle';
|
||||||
@ -9,14 +10,14 @@ import useLastCallback from '../../hooks/useLastCallback';
|
|||||||
import useMediaTransition from '../../hooks/useMediaTransition';
|
import useMediaTransition from '../../hooks/useMediaTransition';
|
||||||
import useFlag from '../../hooks/useFlag';
|
import useFlag from '../../hooks/useFlag';
|
||||||
|
|
||||||
import AnimatedIcon from './AnimatedIcon';
|
|
||||||
|
|
||||||
import styles from './AnimatedIconWithPreview.module.scss';
|
import styles from './AnimatedIconWithPreview.module.scss';
|
||||||
|
|
||||||
type OwnProps =
|
type OwnProps =
|
||||||
Partial<AnimatedIconProps>
|
Partial<AnimatedIconProps>
|
||||||
& { previewUrl?: string; thumbDataUri?: string; noPreviewTransition?: boolean };
|
& { previewUrl?: string; thumbDataUri?: string; noPreviewTransition?: boolean };
|
||||||
|
|
||||||
|
const ANIMATION_DURATION = 300;
|
||||||
|
|
||||||
const loadedPreviewUrls = new Set();
|
const loadedPreviewUrls = new Set();
|
||||||
|
|
||||||
function AnimatedIconWithPreview(props: OwnProps) {
|
function AnimatedIconWithPreview(props: OwnProps) {
|
||||||
@ -24,36 +25,46 @@ function AnimatedIconWithPreview(props: OwnProps) {
|
|||||||
previewUrl, thumbDataUri, className, ...otherProps
|
previewUrl, thumbDataUri, className, ...otherProps
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
const [isPreviewLoaded, markPreviewLoaded] = useFlag(Boolean(thumbDataUri) || loadedPreviewUrls.has(previewUrl));
|
const [isThumbOpen, , unmarkThumbOpen] = useFlag(Boolean(thumbDataUri));
|
||||||
const transitionClassNames = useMediaTransition(isPreviewLoaded);
|
const thumbClassNames = useMediaTransition(isThumbOpen);
|
||||||
|
|
||||||
|
const [isPreviewOpen, markPreviewOpen, unmarkPreviewOpen] = useFlag(loadedPreviewUrls.has(previewUrl));
|
||||||
|
const previewClassNames = useMediaTransition(isPreviewOpen);
|
||||||
|
|
||||||
const [isAnimationReady, markAnimationReady] = useFlag(false);
|
const [isAnimationReady, markAnimationReady] = useFlag(false);
|
||||||
|
|
||||||
const handlePreviewLoad = useLastCallback(() => {
|
const handlePreviewLoad = useLastCallback(() => {
|
||||||
markPreviewLoaded();
|
markPreviewOpen();
|
||||||
loadedPreviewUrls.add(previewUrl);
|
loadedPreviewUrls.add(previewUrl);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const handleAnimationReady = useLastCallback(() => {
|
||||||
|
unmarkThumbOpen();
|
||||||
|
unmarkPreviewOpen();
|
||||||
|
setTimeout(markAnimationReady, ANIMATION_DURATION);
|
||||||
|
});
|
||||||
|
|
||||||
const { size } = props;
|
const { size } = props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={buildClassName(className, styles.root, transitionClassNames)}
|
className={buildClassName(className, styles.root)}
|
||||||
style={buildStyle(size !== undefined && `width: ${size}px; height: ${size}px;`)}
|
style={buildStyle(size !== undefined && `width: ${size}px; height: ${size}px;`)}
|
||||||
>
|
>
|
||||||
{thumbDataUri && !isAnimationReady && (
|
{thumbDataUri && !isAnimationReady && (
|
||||||
// eslint-disable-next-line jsx-a11y/alt-text
|
// eslint-disable-next-line jsx-a11y/alt-text
|
||||||
<img src={thumbDataUri} className={styles.preview} />
|
<img src={thumbDataUri} className={buildClassName(styles.preview, thumbClassNames)} />
|
||||||
)}
|
)}
|
||||||
{previewUrl && !isAnimationReady && (
|
{previewUrl && !isAnimationReady && (
|
||||||
// eslint-disable-next-line jsx-a11y/alt-text
|
// eslint-disable-next-line jsx-a11y/alt-text
|
||||||
<img
|
<img
|
||||||
src={previewUrl}
|
src={previewUrl}
|
||||||
className={styles.preview}
|
className={buildClassName(styles.preview, previewClassNames)}
|
||||||
onLoad={handlePreviewLoad}
|
onLoad={handlePreviewLoad}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{/* eslint-disable-next-line react/jsx-props-no-spreading */}
|
{/* eslint-disable-next-line react/jsx-props-no-spreading */}
|
||||||
<AnimatedIcon {...otherProps} onLoad={markAnimationReady} noTransition />
|
<AnimatedIcon {...otherProps} onLoad={handleAnimationReady} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user