106 lines
2.8 KiB
TypeScript
106 lines
2.8 KiB
TypeScript
import React, {
|
|
FC, memo,
|
|
} from '../../lib/teact/teact';
|
|
|
|
import { ApiMediaFormat, ApiSticker } from '../../api/types';
|
|
import { ActiveEmojiInteraction } from '../../global/types';
|
|
|
|
import buildClassName from '../../util/buildClassName';
|
|
import { ObserveFn, useIsIntersecting } from '../../hooks/useIntersectionObserver';
|
|
import useMedia from '../../hooks/useMedia';
|
|
import useMediaTransition from '../../hooks/useMediaTransition';
|
|
import useAnimatedEmoji from './hooks/useAnimatedEmoji';
|
|
import { LIKE_STICKER_ID } from './helpers/mediaDimensions';
|
|
|
|
import AnimatedSticker from './AnimatedSticker';
|
|
|
|
import './AnimatedEmoji.scss';
|
|
|
|
type OwnProps = {
|
|
sticker: ApiSticker;
|
|
effect?: ApiSticker;
|
|
isOwn?: boolean;
|
|
soundId?: string;
|
|
observeIntersection?: ObserveFn;
|
|
size?: 'large' | 'medium' | 'small';
|
|
lastSyncTime?: number;
|
|
forceLoadPreview?: boolean;
|
|
messageId?: number;
|
|
chatId?: string;
|
|
activeEmojiInteraction?: ActiveEmojiInteraction;
|
|
};
|
|
|
|
const QUALITY = 1;
|
|
|
|
const AnimatedEmoji: FC<OwnProps> = ({
|
|
sticker,
|
|
effect,
|
|
isOwn,
|
|
soundId,
|
|
size = 'medium',
|
|
observeIntersection,
|
|
lastSyncTime,
|
|
forceLoadPreview,
|
|
messageId,
|
|
chatId,
|
|
activeEmojiInteraction,
|
|
}) => {
|
|
const {
|
|
markAnimationLoaded,
|
|
isAnimationLoaded,
|
|
ref,
|
|
width,
|
|
style,
|
|
handleClick,
|
|
playKey,
|
|
} = useAnimatedEmoji(size, chatId, messageId, soundId, activeEmojiInteraction, isOwn, undefined, effect?.emoji);
|
|
|
|
const localMediaHash = `sticker${sticker.id}`;
|
|
|
|
const isIntersecting = useIsIntersecting(ref, observeIntersection);
|
|
|
|
const thumbDataUri = sticker.thumbnail?.dataUri;
|
|
const previewBlobUrl = useMedia(
|
|
`${localMediaHash}?size=m`,
|
|
!isIntersecting && !forceLoadPreview,
|
|
ApiMediaFormat.BlobUrl,
|
|
lastSyncTime,
|
|
);
|
|
const transitionClassNames = useMediaTransition(previewBlobUrl);
|
|
|
|
const mediaData = useMedia(localMediaHash, !isIntersecting, ApiMediaFormat.Lottie, lastSyncTime);
|
|
const isMediaLoaded = Boolean(mediaData);
|
|
|
|
return (
|
|
<div
|
|
ref={ref}
|
|
className={buildClassName('AnimatedEmoji media-inner', sticker.id === LIKE_STICKER_ID && 'like-sticker-thumb')}
|
|
// @ts-ignore teact feature
|
|
style={style}
|
|
onClick={handleClick}
|
|
>
|
|
{!isAnimationLoaded && thumbDataUri && (
|
|
<img src={thumbDataUri} alt="" />
|
|
)}
|
|
{!isAnimationLoaded && previewBlobUrl && (
|
|
<img src={previewBlobUrl} className={transitionClassNames} alt="" />
|
|
)}
|
|
{isMediaLoaded && localMediaHash && (
|
|
<AnimatedSticker
|
|
key={localMediaHash}
|
|
id={localMediaHash}
|
|
animationData={mediaData!}
|
|
size={width}
|
|
quality={QUALITY}
|
|
play={isIntersecting && playKey}
|
|
forceOnHeavyAnimation
|
|
noLoop
|
|
onLoad={markAnimationLoaded}
|
|
/>
|
|
)}
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default memo(AnimatedEmoji);
|