Sticker Set Cover: Fix pausing when hidden
This commit is contained in:
parent
b8573ebf35
commit
3bffde60cb
@ -29,13 +29,13 @@ type OwnProps<T> = {
|
|||||||
noAnimate?: boolean;
|
noAnimate?: boolean;
|
||||||
title?: string;
|
title?: string;
|
||||||
className?: string;
|
className?: string;
|
||||||
clickArg: T;
|
|
||||||
noContextMenu?: boolean;
|
noContextMenu?: boolean;
|
||||||
isSavedMessages?: boolean;
|
isSavedMessages?: boolean;
|
||||||
canViewSet?: boolean;
|
canViewSet?: boolean;
|
||||||
isCurrentUserPremium?: boolean;
|
isCurrentUserPremium?: boolean;
|
||||||
observeIntersection: ObserveFn;
|
observeIntersection: ObserveFn;
|
||||||
onClick?: (arg: OwnProps<T>['clickArg'], isSilent?: boolean, shouldSchedule?: boolean) => void;
|
onClick?: (arg: OwnProps<T>['clickArg'], isSilent?: boolean, shouldSchedule?: boolean) => void;
|
||||||
|
clickArg: T;
|
||||||
onFaveClick?: (sticker: ApiSticker) => void;
|
onFaveClick?: (sticker: ApiSticker) => void;
|
||||||
onUnfaveClick?: (sticker: ApiSticker) => void;
|
onUnfaveClick?: (sticker: ApiSticker) => void;
|
||||||
onRemoveRecentClick?: (sticker: ApiSticker) => void;
|
onRemoveRecentClick?: (sticker: ApiSticker) => void;
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import React, { memo, useCallback, useMemo } from '../../lib/teact/teact';
|
import React, { memo, useCallback } from '../../lib/teact/teact';
|
||||||
|
|
||||||
import type { ApiSticker, ApiStickerSet } from '../../api/types';
|
import type { ApiSticker, ApiStickerSet } from '../../api/types';
|
||||||
import type { FC } from '../../lib/teact/teact';
|
import type { FC } from '../../lib/teact/teact';
|
||||||
@ -11,7 +11,6 @@ import useLang from '../../hooks/useLang';
|
|||||||
|
|
||||||
import ListItem from '../ui/ListItem';
|
import ListItem from '../ui/ListItem';
|
||||||
import Button from '../ui/Button';
|
import Button from '../ui/Button';
|
||||||
import StickerSetCoverAnimated from '../middle/composer/StickerSetCoverAnimated';
|
|
||||||
import StickerSetCover from '../middle/composer/StickerSetCover';
|
import StickerSetCover from '../middle/composer/StickerSetCover';
|
||||||
import StickerButton from './StickerButton';
|
import StickerButton from './StickerButton';
|
||||||
|
|
||||||
@ -19,6 +18,7 @@ import './StickerSetCard.scss';
|
|||||||
|
|
||||||
type OwnProps = {
|
type OwnProps = {
|
||||||
stickerSet?: ApiStickerSet;
|
stickerSet?: ApiStickerSet;
|
||||||
|
noAnimate?: boolean;
|
||||||
className?: string;
|
className?: string;
|
||||||
observeIntersection: ObserveFn;
|
observeIntersection: ObserveFn;
|
||||||
onClick: (value: ApiSticker) => void;
|
onClick: (value: ApiSticker) => void;
|
||||||
@ -26,6 +26,7 @@ type OwnProps = {
|
|||||||
|
|
||||||
const StickerSetCard: FC<OwnProps> = ({
|
const StickerSetCard: FC<OwnProps> = ({
|
||||||
stickerSet,
|
stickerSet,
|
||||||
|
noAnimate,
|
||||||
className,
|
className,
|
||||||
observeIntersection,
|
observeIntersection,
|
||||||
onClick,
|
onClick,
|
||||||
@ -38,7 +39,11 @@ const StickerSetCard: FC<OwnProps> = ({
|
|||||||
if (firstSticker) onClick(firstSticker);
|
if (firstSticker) onClick(firstSticker);
|
||||||
}, [firstSticker, onClick]);
|
}, [firstSticker, onClick]);
|
||||||
|
|
||||||
const preview = useMemo(() => {
|
if (!stickerSet || !stickerSet.stickers) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderPreview() {
|
||||||
if (!stickerSet) return undefined;
|
if (!stickerSet) return undefined;
|
||||||
if (stickerSet.hasThumbnail || !firstSticker) {
|
if (stickerSet.hasThumbnail || !firstSticker) {
|
||||||
return (
|
return (
|
||||||
@ -47,18 +52,12 @@ const StickerSetCard: FC<OwnProps> = ({
|
|||||||
color="translucent"
|
color="translucent"
|
||||||
isRtl={lang.isRtl}
|
isRtl={lang.isRtl}
|
||||||
>
|
>
|
||||||
{stickerSet.isLottie ? (
|
<StickerSetCover
|
||||||
<StickerSetCoverAnimated
|
stickerSet={stickerSet}
|
||||||
size={STICKER_SIZE_GENERAL_SETTINGS}
|
size={STICKER_SIZE_GENERAL_SETTINGS}
|
||||||
stickerSet={stickerSet}
|
noAnimate={noAnimate}
|
||||||
observeIntersection={observeIntersection}
|
observeIntersection={observeIntersection}
|
||||||
/>
|
/>
|
||||||
) : (
|
|
||||||
<StickerSetCover
|
|
||||||
stickerSet={stickerSet}
|
|
||||||
observeIntersection={observeIntersection}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</Button>
|
</Button>
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
@ -67,17 +66,14 @@ const StickerSetCard: FC<OwnProps> = ({
|
|||||||
sticker={firstSticker}
|
sticker={firstSticker}
|
||||||
size={STICKER_SIZE_GENERAL_SETTINGS}
|
size={STICKER_SIZE_GENERAL_SETTINGS}
|
||||||
title={stickerSet.title}
|
title={stickerSet.title}
|
||||||
|
noAnimate={noAnimate}
|
||||||
observeIntersection={observeIntersection}
|
observeIntersection={observeIntersection}
|
||||||
clickArg={undefined}
|
|
||||||
noContextMenu
|
noContextMenu
|
||||||
isCurrentUserPremium
|
isCurrentUserPremium
|
||||||
|
clickArg={undefined}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}, [firstSticker, lang.isRtl, observeIntersection, stickerSet]);
|
|
||||||
|
|
||||||
if (!stickerSet || !stickerSet.stickers) {
|
|
||||||
return undefined;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -87,7 +83,7 @@ const StickerSetCard: FC<OwnProps> = ({
|
|||||||
inactive={!firstSticker}
|
inactive={!firstSticker}
|
||||||
onClick={handleCardClick}
|
onClick={handleCardClick}
|
||||||
>
|
>
|
||||||
{preview}
|
{renderPreview()}
|
||||||
<div className="multiline-menu-item">
|
<div className="multiline-menu-item">
|
||||||
<div className="title">{stickerSet.title}</div>
|
<div className="title">{stickerSet.title}</div>
|
||||||
<div className="subtitle">{lang('StickerPack.StickerCount', stickerSet.count, 'i')}</div>
|
<div className="subtitle">{lang('StickerPack.StickerCount', stickerSet.count, 'i')}</div>
|
||||||
|
|||||||
@ -33,7 +33,6 @@ import Button from '../../ui/Button';
|
|||||||
import StickerButton from '../../common/StickerButton';
|
import StickerButton from '../../common/StickerButton';
|
||||||
import StickerSet from './StickerSet';
|
import StickerSet from './StickerSet';
|
||||||
import StickerSetCover from './StickerSetCover';
|
import StickerSetCover from './StickerSetCover';
|
||||||
import StickerSetCoverAnimated from './StickerSetCoverAnimated';
|
|
||||||
|
|
||||||
import './StickerPicker.scss';
|
import './StickerPicker.scss';
|
||||||
|
|
||||||
@ -50,7 +49,7 @@ type StateProps = {
|
|||||||
addedCustomEmojiIds?: string[];
|
addedCustomEmojiIds?: string[];
|
||||||
recentCustomEmoji: ApiSticker[];
|
recentCustomEmoji: ApiSticker[];
|
||||||
featuredCustomEmojiIds?: string[];
|
featuredCustomEmojiIds?: string[];
|
||||||
shouldPlay?: boolean;
|
canAnimate?: boolean;
|
||||||
isSavedMessages?: boolean;
|
isSavedMessages?: boolean;
|
||||||
isCurrentUserPremium?: boolean;
|
isCurrentUserPremium?: boolean;
|
||||||
};
|
};
|
||||||
@ -68,7 +67,7 @@ const CustomEmojiPicker: FC<OwnProps & StateProps> = ({
|
|||||||
recentCustomEmoji,
|
recentCustomEmoji,
|
||||||
stickerSetsById,
|
stickerSetsById,
|
||||||
featuredCustomEmojiIds,
|
featuredCustomEmojiIds,
|
||||||
shouldPlay,
|
canAnimate,
|
||||||
isSavedMessages,
|
isSavedMessages,
|
||||||
isCurrentUserPremium,
|
isCurrentUserPremium,
|
||||||
onCustomEmojiSelect,
|
onCustomEmojiSelect,
|
||||||
@ -199,14 +198,10 @@ const CustomEmojiPicker: FC<OwnProps & StateProps> = ({
|
|||||||
>
|
>
|
||||||
{stickerSet.id === RECENT_SYMBOL_SET_ID ? (
|
{stickerSet.id === RECENT_SYMBOL_SET_ID ? (
|
||||||
<i className="icon-recent" />
|
<i className="icon-recent" />
|
||||||
) : stickerSet.isLottie ? (
|
|
||||||
<StickerSetCoverAnimated
|
|
||||||
stickerSet={stickerSet as ApiStickerSet}
|
|
||||||
observeIntersection={observeIntersectionForCovers}
|
|
||||||
/>
|
|
||||||
) : (
|
) : (
|
||||||
<StickerSetCover
|
<StickerSetCover
|
||||||
stickerSet={stickerSet as ApiStickerSet}
|
stickerSet={stickerSet as ApiStickerSet}
|
||||||
|
noAnimate={!canAnimate || !loadAndPlay}
|
||||||
observeIntersection={observeIntersectionForCovers}
|
observeIntersection={observeIntersectionForCovers}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
@ -220,11 +215,12 @@ const CustomEmojiPicker: FC<OwnProps & StateProps> = ({
|
|||||||
size={STICKER_SIZE_PICKER_HEADER}
|
size={STICKER_SIZE_PICKER_HEADER}
|
||||||
title={stickerSet.title}
|
title={stickerSet.title}
|
||||||
className={buttonClassName}
|
className={buttonClassName}
|
||||||
|
noAnimate={!canAnimate || !loadAndPlay}
|
||||||
observeIntersection={observeIntersectionForCovers}
|
observeIntersection={observeIntersectionForCovers}
|
||||||
onClick={selectStickerSet}
|
|
||||||
clickArg={index}
|
|
||||||
noContextMenu
|
noContextMenu
|
||||||
isCurrentUserPremium
|
isCurrentUserPremium
|
||||||
|
onClick={selectStickerSet}
|
||||||
|
clickArg={index}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -260,14 +256,14 @@ const CustomEmojiPicker: FC<OwnProps & StateProps> = ({
|
|||||||
<StickerSet
|
<StickerSet
|
||||||
key={stickerSet.id}
|
key={stickerSet.id}
|
||||||
stickerSet={stickerSet}
|
stickerSet={stickerSet}
|
||||||
loadAndPlay={Boolean(shouldPlay && loadAndPlay)}
|
loadAndPlay={Boolean(canAnimate && loadAndPlay)}
|
||||||
index={i}
|
index={i}
|
||||||
observeIntersection={observeIntersection}
|
observeIntersection={observeIntersection}
|
||||||
shouldRender={activeSetIndex >= i - 1 && activeSetIndex <= i + 1}
|
shouldRender={activeSetIndex >= i - 1 && activeSetIndex <= i + 1}
|
||||||
onStickerSelect={handleEmojiSelect}
|
|
||||||
isSavedMessages={isSavedMessages}
|
isSavedMessages={isSavedMessages}
|
||||||
isCustomEmojiPicker
|
isCustomEmojiPicker
|
||||||
isCurrentUserPremium={isCurrentUserPremium}
|
isCurrentUserPremium={isCurrentUserPremium}
|
||||||
|
onStickerSelect={handleEmojiSelect}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
@ -288,7 +284,7 @@ export default memo(withGlobal<OwnProps>(
|
|||||||
return {
|
return {
|
||||||
stickerSetsById: setsById,
|
stickerSetsById: setsById,
|
||||||
addedCustomEmojiIds: global.customEmojis.added.setIds,
|
addedCustomEmojiIds: global.customEmojis.added.setIds,
|
||||||
shouldPlay: global.settings.byKey.shouldLoopStickers,
|
canAnimate: global.settings.byKey.shouldLoopStickers,
|
||||||
isSavedMessages,
|
isSavedMessages,
|
||||||
isCurrentUserPremium: selectIsCurrentUserPremium(global),
|
isCurrentUserPremium: selectIsCurrentUserPremium(global),
|
||||||
recentCustomEmoji,
|
recentCustomEmoji,
|
||||||
|
|||||||
@ -35,7 +35,6 @@ import Button from '../../ui/Button';
|
|||||||
import StickerButton from '../../common/StickerButton';
|
import StickerButton from '../../common/StickerButton';
|
||||||
import StickerSet from './StickerSet';
|
import StickerSet from './StickerSet';
|
||||||
import StickerSetCover from './StickerSetCover';
|
import StickerSetCover from './StickerSetCover';
|
||||||
import StickerSetCoverAnimated from './StickerSetCoverAnimated';
|
|
||||||
import PremiumIcon from '../../common/PremiumIcon';
|
import PremiumIcon from '../../common/PremiumIcon';
|
||||||
|
|
||||||
import './StickerPicker.scss';
|
import './StickerPicker.scss';
|
||||||
@ -56,7 +55,7 @@ type StateProps = {
|
|||||||
premiumStickers: ApiSticker[];
|
premiumStickers: ApiSticker[];
|
||||||
stickerSetsById: Record<string, ApiStickerSet>;
|
stickerSetsById: Record<string, ApiStickerSet>;
|
||||||
addedSetIds?: string[];
|
addedSetIds?: string[];
|
||||||
shouldPlay?: boolean;
|
canAnimate?: boolean;
|
||||||
isSavedMessages?: boolean;
|
isSavedMessages?: boolean;
|
||||||
isCurrentUserPremium?: boolean;
|
isCurrentUserPremium?: boolean;
|
||||||
};
|
};
|
||||||
@ -78,7 +77,7 @@ const StickerPicker: FC<OwnProps & StateProps> = ({
|
|||||||
premiumStickers,
|
premiumStickers,
|
||||||
addedSetIds,
|
addedSetIds,
|
||||||
stickerSetsById,
|
stickerSetsById,
|
||||||
shouldPlay,
|
canAnimate,
|
||||||
isSavedMessages,
|
isSavedMessages,
|
||||||
isCurrentUserPremium,
|
isCurrentUserPremium,
|
||||||
onStickerSelect,
|
onStickerSelect,
|
||||||
@ -286,14 +285,10 @@ const StickerPicker: FC<OwnProps & StateProps> = ({
|
|||||||
<i className="icon-favorite" />
|
<i className="icon-favorite" />
|
||||||
) : stickerSet.id === CHAT_STICKER_SET_ID ? (
|
) : stickerSet.id === CHAT_STICKER_SET_ID ? (
|
||||||
<Avatar chat={chat} size="small" />
|
<Avatar chat={chat} size="small" />
|
||||||
) : stickerSet.isLottie ? (
|
|
||||||
<StickerSetCoverAnimated
|
|
||||||
stickerSet={stickerSet as ApiStickerSet}
|
|
||||||
observeIntersection={observeIntersectionForCovers}
|
|
||||||
/>
|
|
||||||
) : (
|
) : (
|
||||||
<StickerSetCover
|
<StickerSetCover
|
||||||
stickerSet={stickerSet as ApiStickerSet}
|
stickerSet={stickerSet as ApiStickerSet}
|
||||||
|
noAnimate={!canAnimate || !loadAndPlay}
|
||||||
observeIntersection={observeIntersectionForCovers}
|
observeIntersection={observeIntersectionForCovers}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
@ -307,11 +302,12 @@ const StickerPicker: FC<OwnProps & StateProps> = ({
|
|||||||
size={STICKER_SIZE_PICKER_HEADER}
|
size={STICKER_SIZE_PICKER_HEADER}
|
||||||
title={stickerSet.title}
|
title={stickerSet.title}
|
||||||
className={buttonClassName}
|
className={buttonClassName}
|
||||||
|
noAnimate={!canAnimate || !loadAndPlay}
|
||||||
observeIntersection={observeIntersectionForCovers}
|
observeIntersection={observeIntersectionForCovers}
|
||||||
onClick={selectStickerSet}
|
|
||||||
clickArg={index}
|
|
||||||
noContextMenu
|
noContextMenu
|
||||||
isCurrentUserPremium
|
isCurrentUserPremium
|
||||||
|
onClick={selectStickerSet}
|
||||||
|
clickArg={index}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -350,17 +346,17 @@ const StickerPicker: FC<OwnProps & StateProps> = ({
|
|||||||
<StickerSet
|
<StickerSet
|
||||||
key={stickerSet.id}
|
key={stickerSet.id}
|
||||||
stickerSet={stickerSet}
|
stickerSet={stickerSet}
|
||||||
loadAndPlay={Boolean(shouldPlay && loadAndPlay)}
|
loadAndPlay={Boolean(canAnimate && loadAndPlay)}
|
||||||
index={i}
|
index={i}
|
||||||
observeIntersection={observeIntersection}
|
observeIntersection={observeIntersection}
|
||||||
shouldRender={activeSetIndex >= i - 1 && activeSetIndex <= i + 1}
|
shouldRender={activeSetIndex >= i - 1 && activeSetIndex <= i + 1}
|
||||||
|
favoriteStickers={favoriteStickers}
|
||||||
|
isSavedMessages={isSavedMessages}
|
||||||
|
isCurrentUserPremium={isCurrentUserPremium}
|
||||||
onStickerSelect={handleStickerSelect}
|
onStickerSelect={handleStickerSelect}
|
||||||
onStickerUnfave={handleStickerUnfave}
|
onStickerUnfave={handleStickerUnfave}
|
||||||
onStickerFave={handleStickerFave}
|
onStickerFave={handleStickerFave}
|
||||||
onStickerRemoveRecent={handleRemoveRecentSticker}
|
onStickerRemoveRecent={handleRemoveRecentSticker}
|
||||||
favoriteStickers={favoriteStickers}
|
|
||||||
isSavedMessages={isSavedMessages}
|
|
||||||
isCurrentUserPremium={isCurrentUserPremium}
|
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
@ -388,7 +384,7 @@ export default memo(withGlobal<OwnProps>(
|
|||||||
premiumStickers: premiumSet.stickers,
|
premiumStickers: premiumSet.stickers,
|
||||||
stickerSetsById: setsById,
|
stickerSetsById: setsById,
|
||||||
addedSetIds: added.setIds,
|
addedSetIds: added.setIds,
|
||||||
shouldPlay: global.settings.byKey.shouldLoopStickers,
|
canAnimate: global.settings.byKey.shouldLoopStickers,
|
||||||
isSavedMessages,
|
isSavedMessages,
|
||||||
isCurrentUserPremium: selectIsCurrentUserPremium(global),
|
isCurrentUserPremium: selectIsCurrentUserPremium(global),
|
||||||
};
|
};
|
||||||
|
|||||||
@ -166,15 +166,15 @@ const StickerSet: FC<OwnProps> = ({
|
|||||||
size={itemSize}
|
size={itemSize}
|
||||||
observeIntersection={observeIntersection}
|
observeIntersection={observeIntersection}
|
||||||
noAnimate={!loadAndPlay}
|
noAnimate={!loadAndPlay}
|
||||||
|
isSavedMessages={isSavedMessages}
|
||||||
|
canViewSet
|
||||||
|
isCurrentUserPremium={isCurrentUserPremium}
|
||||||
onClick={onStickerSelect}
|
onClick={onStickerSelect}
|
||||||
clickArg={sticker}
|
clickArg={sticker}
|
||||||
onUnfaveClick={stickerSet.id === FAVORITE_SYMBOL_SET_ID && favoriteStickerIdsSet?.has(sticker.id)
|
onUnfaveClick={stickerSet.id === FAVORITE_SYMBOL_SET_ID && favoriteStickerIdsSet?.has(sticker.id)
|
||||||
? onStickerUnfave : undefined}
|
? onStickerUnfave : undefined}
|
||||||
onFaveClick={!favoriteStickerIdsSet?.has(sticker.id) ? onStickerFave : undefined}
|
onFaveClick={!favoriteStickerIdsSet?.has(sticker.id) ? onStickerFave : undefined}
|
||||||
onRemoveRecentClick={isRecent ? onStickerRemoveRecent : undefined}
|
onRemoveRecentClick={isRecent ? onStickerRemoveRecent : undefined}
|
||||||
isSavedMessages={isSavedMessages}
|
|
||||||
canViewSet
|
|
||||||
isCurrentUserPremium={isCurrentUserPremium}
|
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
{!isExpanded && stickerSet.count > itemsBeforeCutout && (
|
{!isExpanded && stickerSet.count > itemsBeforeCutout && (
|
||||||
|
|||||||
@ -0,0 +1,3 @@
|
|||||||
|
.video {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
@ -1,44 +1,73 @@
|
|||||||
import type { FC } from '../../../lib/teact/teact';
|
import type { FC } from '../../../lib/teact/teact';
|
||||||
import React, { memo, useMemo, useRef } from '../../../lib/teact/teact';
|
import React, { memo, useRef } from '../../../lib/teact/teact';
|
||||||
|
|
||||||
import type { ApiStickerSet } from '../../../api/types';
|
import type { ApiStickerSet } from '../../../api/types';
|
||||||
|
import type { ObserveFn } from '../../../hooks/useIntersectionObserver';
|
||||||
|
|
||||||
|
import { STICKER_SIZE_PICKER_HEADER } from '../../../config';
|
||||||
import { IS_WEBM_SUPPORTED } from '../../../util/environment';
|
import { IS_WEBM_SUPPORTED } from '../../../util/environment';
|
||||||
import { getFirstLetters } from '../../../util/textFormat';
|
import { getFirstLetters } from '../../../util/textFormat';
|
||||||
import type { ObserveFn } from '../../../hooks/useIntersectionObserver';
|
import buildClassName from '../../../util/buildClassName';
|
||||||
import { useIsIntersecting } from '../../../hooks/useIntersectionObserver';
|
import { useIsIntersecting } from '../../../hooks/useIntersectionObserver';
|
||||||
import useMedia from '../../../hooks/useMedia';
|
import useMedia from '../../../hooks/useMedia';
|
||||||
import useMediaTransition from '../../../hooks/useMediaTransition';
|
import useMediaTransition from '../../../hooks/useMediaTransition';
|
||||||
|
|
||||||
|
import AnimatedSticker from '../../common/AnimatedSticker';
|
||||||
import OptimizedVideo from '../../ui/OptimizedVideo';
|
import OptimizedVideo from '../../ui/OptimizedVideo';
|
||||||
|
|
||||||
|
import styles from './StickerSetCover.module.scss';
|
||||||
|
|
||||||
type OwnProps = {
|
type OwnProps = {
|
||||||
stickerSet: ApiStickerSet;
|
stickerSet: ApiStickerSet;
|
||||||
|
size?: number;
|
||||||
|
noAnimate?: boolean;
|
||||||
observeIntersection: ObserveFn;
|
observeIntersection: ObserveFn;
|
||||||
};
|
};
|
||||||
|
|
||||||
const StickerSetCover: FC<OwnProps> = ({ stickerSet, observeIntersection }) => {
|
const StickerSetCover: FC<OwnProps> = ({
|
||||||
|
stickerSet,
|
||||||
|
size = STICKER_SIZE_PICKER_HEADER,
|
||||||
|
noAnimate,
|
||||||
|
observeIntersection,
|
||||||
|
}) => {
|
||||||
// eslint-disable-next-line no-null/no-null
|
// eslint-disable-next-line no-null/no-null
|
||||||
const ref = useRef<HTMLDivElement>(null);
|
const ref = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
|
const { hasThumbnail, isLottie, isVideos: isVideo } = stickerSet;
|
||||||
|
|
||||||
const isIntersecting = useIsIntersecting(ref, observeIntersection);
|
const isIntersecting = useIsIntersecting(ref, observeIntersection);
|
||||||
|
|
||||||
const mediaData = useMedia(stickerSet.hasThumbnail && `stickerSet${stickerSet.id}`, !isIntersecting);
|
const mediaData = useMedia((hasThumbnail || isLottie) && `stickerSet${stickerSet.id}`, !isIntersecting);
|
||||||
const transitionClassNames = useMediaTransition(mediaData);
|
const isReady = mediaData && (!isVideo || IS_WEBM_SUPPORTED);
|
||||||
const isVideo = stickerSet.isVideos;
|
const transitionClassNames = useMediaTransition(isReady);
|
||||||
|
|
||||||
const firstLetters = useMemo(() => {
|
|
||||||
if ((isVideo && !IS_WEBM_SUPPORTED) || !mediaData) return getFirstLetters(stickerSet.title, 2);
|
|
||||||
return undefined;
|
|
||||||
}, [isVideo, mediaData, stickerSet.title]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div ref={ref} className="sticker-set-cover">
|
<div ref={ref} className="sticker-set-cover">
|
||||||
{firstLetters}
|
{isReady ? (
|
||||||
{isVideo ? (
|
isLottie ? (
|
||||||
<OptimizedVideo canPlay src={mediaData} className={transitionClassNames} loop disablePictureInPicture />
|
<AnimatedSticker
|
||||||
|
className={transitionClassNames}
|
||||||
|
tgsUrl={mediaData}
|
||||||
|
size={size}
|
||||||
|
play={isIntersecting && !noAnimate}
|
||||||
|
/>
|
||||||
|
) : isVideo ? (
|
||||||
|
<OptimizedVideo
|
||||||
|
className={buildClassName(styles.video, transitionClassNames)}
|
||||||
|
src={mediaData}
|
||||||
|
canPlay={isIntersecting && !noAnimate}
|
||||||
|
loop
|
||||||
|
disablePictureInPicture
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<img
|
||||||
|
src={mediaData}
|
||||||
|
className={transitionClassNames}
|
||||||
|
alt=""
|
||||||
|
/>
|
||||||
|
)
|
||||||
) : (
|
) : (
|
||||||
<img src={mediaData} className={transitionClassNames} alt="" />
|
getFirstLetters(stickerSet.title, 2)
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -1,57 +0,0 @@
|
|||||||
import type { FC } from '../../../lib/teact/teact';
|
|
||||||
import React, { memo, useMemo, useRef } from '../../../lib/teact/teact';
|
|
||||||
|
|
||||||
import type { ApiStickerSet } from '../../../api/types';
|
|
||||||
|
|
||||||
import { STICKER_SIZE_PICKER_HEADER } from '../../../config';
|
|
||||||
import { getFirstLetters } from '../../../util/textFormat';
|
|
||||||
|
|
||||||
import type { ObserveFn } from '../../../hooks/useIntersectionObserver';
|
|
||||||
import { useIsIntersecting } from '../../../hooks/useIntersectionObserver';
|
|
||||||
import useMedia from '../../../hooks/useMedia';
|
|
||||||
import useMediaTransition from '../../../hooks/useMediaTransition';
|
|
||||||
|
|
||||||
import AnimatedSticker from '../../common/AnimatedSticker';
|
|
||||||
|
|
||||||
type OwnProps = {
|
|
||||||
size?: number;
|
|
||||||
stickerSet: ApiStickerSet;
|
|
||||||
observeIntersection: ObserveFn;
|
|
||||||
};
|
|
||||||
|
|
||||||
const StickerSetCoverAnimated: FC<OwnProps> = ({
|
|
||||||
size = STICKER_SIZE_PICKER_HEADER,
|
|
||||||
stickerSet,
|
|
||||||
observeIntersection,
|
|
||||||
}) => {
|
|
||||||
// eslint-disable-next-line no-null/no-null
|
|
||||||
const ref = useRef<HTMLDivElement>(null);
|
|
||||||
|
|
||||||
const isIntersecting = useIsIntersecting(ref, observeIntersection);
|
|
||||||
|
|
||||||
const mediaHash = `stickerSet${stickerSet.id}`;
|
|
||||||
const lottieData = useMedia(mediaHash, !isIntersecting);
|
|
||||||
const transitionClassNames = useMediaTransition(lottieData);
|
|
||||||
|
|
||||||
const firstLetters = useMemo(() => {
|
|
||||||
if (lottieData) return undefined;
|
|
||||||
|
|
||||||
return getFirstLetters(stickerSet.title, 2);
|
|
||||||
}, [lottieData, stickerSet.title]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div ref={ref} className="sticker-set-cover">
|
|
||||||
{firstLetters}
|
|
||||||
{lottieData && (
|
|
||||||
<AnimatedSticker
|
|
||||||
size={size}
|
|
||||||
tgsUrl={lottieData}
|
|
||||||
className={transitionClassNames}
|
|
||||||
play={isIntersecting}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default memo(StickerSetCoverAnimated);
|
|
||||||
Loading…
x
Reference in New Issue
Block a user