Emoji Modal: Fix sticker set card list modal (#4764)
This commit is contained in:
parent
527e4644e2
commit
66d54b2f63
@ -40,7 +40,6 @@
|
||||
.sets {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
min-height: 19rem;
|
||||
overflow-y: auto;
|
||||
padding: 0 0.5rem;
|
||||
text-align: left;
|
||||
|
||||
@ -1,15 +1,19 @@
|
||||
import type { FC } from '../../lib/teact/teact';
|
||||
import React, {
|
||||
memo, useCallback, useRef,
|
||||
memo,
|
||||
useMemo,
|
||||
useRef,
|
||||
} from '../../lib/teact/teact';
|
||||
import { getGlobal } from '../../lib/teact/teactn';
|
||||
import { getActions, withGlobal } from '../../global';
|
||||
|
||||
import type { ApiSticker, ApiStickerSet } from '../../api/types';
|
||||
import type { ApiSticker } from '../../api/types';
|
||||
|
||||
import { selectCanPlayAnimatedEmojis } from '../../global/selectors';
|
||||
import buildClassName from '../../util/buildClassName';
|
||||
|
||||
import { useIntersectionObserver } from '../../hooks/useIntersectionObserver';
|
||||
import useLastCallback from '../../hooks/useLastCallback';
|
||||
import useOldLang from '../../hooks/useOldLang';
|
||||
import usePrevious from '../../hooks/usePrevious';
|
||||
|
||||
@ -24,18 +28,21 @@ export type OwnProps = {
|
||||
};
|
||||
|
||||
type StateProps = {
|
||||
customEmojiSets?: ApiStickerSet[];
|
||||
canPlayAnimatedEmojis?: boolean;
|
||||
};
|
||||
|
||||
const CustomEmojiSetsModal: FC<OwnProps & StateProps> = ({
|
||||
customEmojiSets,
|
||||
customEmojiSetIds,
|
||||
canPlayAnimatedEmojis,
|
||||
onClose,
|
||||
}) => {
|
||||
const { openStickerSet } = getActions();
|
||||
const lang = useOldLang();
|
||||
|
||||
const customEmojiSets = useMemo(() => {
|
||||
return customEmojiSetIds?.map((id) => getGlobal().stickers.setsById[id]);
|
||||
}, [customEmojiSetIds]);
|
||||
|
||||
// eslint-disable-next-line no-null/no-null
|
||||
const customEmojiModalRef = useRef<HTMLDivElement>(null);
|
||||
const { observe: observeIntersectionForCovers } = useIntersectionObserver({
|
||||
@ -45,11 +52,11 @@ const CustomEmojiSetsModal: FC<OwnProps & StateProps> = ({
|
||||
const prevCustomEmojiSets = usePrevious(customEmojiSets);
|
||||
const renderingCustomEmojiSets = customEmojiSets || prevCustomEmojiSets;
|
||||
|
||||
const handleSetClick = useCallback((sticker: ApiSticker) => {
|
||||
const handleSetClick = useLastCallback((sticker: ApiSticker) => {
|
||||
openStickerSet({
|
||||
stickerSetInfo: sticker.stickerSetInfo,
|
||||
});
|
||||
}, [openStickerSet]);
|
||||
});
|
||||
|
||||
return (
|
||||
<Modal
|
||||
@ -60,27 +67,26 @@ const CustomEmojiSetsModal: FC<OwnProps & StateProps> = ({
|
||||
title={lang('lng_custom_emoji_used_sets')}
|
||||
>
|
||||
<div className={buildClassName(styles.sets, 'custom-scroll')} ref={customEmojiModalRef} teactFastList>
|
||||
{renderingCustomEmojiSets?.map((customEmojiSet) => (
|
||||
<StickerSetCard
|
||||
key={customEmojiSet.id}
|
||||
className={styles.setCard}
|
||||
stickerSet={customEmojiSet}
|
||||
onClick={handleSetClick}
|
||||
observeIntersection={observeIntersectionForCovers}
|
||||
noPlay={!canPlayAnimatedEmojis}
|
||||
/>
|
||||
))}
|
||||
{renderingCustomEmojiSets?.map((customEmojiSet) => {
|
||||
return (
|
||||
<StickerSetCard
|
||||
key={customEmojiSet.id}
|
||||
className={styles.setCard}
|
||||
stickerSet={customEmojiSet}
|
||||
onClick={handleSetClick}
|
||||
observeIntersection={observeIntersectionForCovers}
|
||||
noPlay={!canPlayAnimatedEmojis}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
||||
export default memo(withGlobal<OwnProps>(
|
||||
(global, { customEmojiSetIds }): StateProps => {
|
||||
const customEmojiSets = customEmojiSetIds?.map((id) => global.stickers.setsById[id]);
|
||||
|
||||
(global): StateProps => {
|
||||
return {
|
||||
customEmojiSets,
|
||||
canPlayAnimatedEmojis: selectCanPlayAnimatedEmojis(global),
|
||||
};
|
||||
},
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import type { FC } from '../../lib/teact/teact';
|
||||
import React, { memo, useCallback } from '../../lib/teact/teact';
|
||||
import React, { memo } from '../../lib/teact/teact';
|
||||
|
||||
import type { ApiSticker, ApiStickerSet } from '../../api/types';
|
||||
import type { ObserveFn } from '../../hooks/useIntersectionObserver';
|
||||
@ -7,6 +7,7 @@ import type { ObserveFn } from '../../hooks/useIntersectionObserver';
|
||||
import { CHAT_HEIGHT_PX, STICKER_SIZE_GENERAL_SETTINGS } from '../../config';
|
||||
import buildClassName from '../../util/buildClassName';
|
||||
|
||||
import useLastCallback from '../../hooks/useLastCallback';
|
||||
import useOldLang from '../../hooks/useOldLang';
|
||||
|
||||
import StickerSetCover from '../middle/composer/StickerSetCover';
|
||||
@ -35,11 +36,11 @@ const StickerSetCard: FC<OwnProps> = ({
|
||||
|
||||
const firstSticker = stickerSet?.stickers?.[0];
|
||||
|
||||
const handleCardClick = useCallback(() => {
|
||||
const handleCardClick = useLastCallback(() => {
|
||||
if (firstSticker) onClick(firstSticker);
|
||||
}, [firstSticker, onClick]);
|
||||
});
|
||||
|
||||
if (!stickerSet || !stickerSet.stickers) {
|
||||
if (!stickerSet?.stickers) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
|
||||
@ -4,18 +4,17 @@ import React, {
|
||||
} from '../../../lib/teact/teact';
|
||||
import { getActions, getGlobal, withGlobal } from '../../../global';
|
||||
|
||||
import type {
|
||||
ApiAvailableReaction,
|
||||
ApiChatReactions,
|
||||
ApiMessage,
|
||||
ApiReaction,
|
||||
ApiStickerSet, ApiStickerSetInfo,
|
||||
ApiThreadInfo,
|
||||
} from '../../../api/types';
|
||||
import type { ActiveDownloads, MessageListType } from '../../../global/types';
|
||||
import type { IAlbum, IAnchorPosition, ThreadId } from '../../../types';
|
||||
import {
|
||||
type ApiAvailableReaction,
|
||||
type ApiChatReactions,
|
||||
type ApiMessage,
|
||||
type ApiReaction,
|
||||
type ApiStickerSet,
|
||||
type ApiStickerSetInfo,
|
||||
type ApiThreadInfo,
|
||||
MAIN_THREAD_ID,
|
||||
} from '../../../api/types';
|
||||
import { MAIN_THREAD_ID } from '../../../api/types';
|
||||
|
||||
import { PREVIEW_AVATAR_COUNT, SERVICE_NOTIFICATIONS_USER_ID } from '../../../config';
|
||||
import {
|
||||
@ -45,8 +44,7 @@ import {
|
||||
selectIsMessageProtected,
|
||||
selectIsMessageUnread,
|
||||
selectIsPremiumPurchaseBlocked,
|
||||
selectIsReactionPickerOpen,
|
||||
selectMessageCustomEmojiSets,
|
||||
selectIsReactionPickerOpen, selectMessageCustomEmojiSets,
|
||||
selectMessageTranslations,
|
||||
selectRequestedChatTranslationLanguage,
|
||||
selectRequestedMessageTranslationLanguage,
|
||||
@ -88,8 +86,6 @@ type StateProps = {
|
||||
availableReactions?: ApiAvailableReaction[];
|
||||
topReactions?: ApiReaction[];
|
||||
defaultTagReactions?: ApiReaction[];
|
||||
customEmojiSetsInfo?: ApiStickerSetInfo[];
|
||||
customEmojiSets?: ApiStickerSet[];
|
||||
noOptions?: boolean;
|
||||
canSendNow?: boolean;
|
||||
canReschedule?: boolean;
|
||||
@ -98,6 +94,8 @@ type StateProps = {
|
||||
canShowReactionsCount?: boolean;
|
||||
canBuyPremium?: boolean;
|
||||
canShowReactionList?: boolean;
|
||||
customEmojiSetsInfo?: ApiStickerSetInfo[];
|
||||
customEmojiSets?: ApiStickerSet[];
|
||||
canUnpin?: boolean;
|
||||
canDelete?: boolean;
|
||||
canReport?: boolean;
|
||||
@ -694,12 +692,12 @@ export default memo(withGlobal<OwnProps>(
|
||||
const isMessageUnread = selectIsMessageUnread(global, message);
|
||||
const canLoadReadDate = Boolean(
|
||||
isPrivate
|
||||
&& isOwn
|
||||
&& !isMessageUnread
|
||||
&& readDateExpiresAt
|
||||
&& message.date > Date.now() / 1000 - readDateExpiresAt
|
||||
&& !userStatus?.isReadDateRestricted
|
||||
&& messageListType !== 'scheduled',
|
||||
&& isOwn
|
||||
&& !isMessageUnread
|
||||
&& readDateExpiresAt
|
||||
&& message.date > Date.now() / 1000 - readDateExpiresAt
|
||||
&& !userStatus?.isReadDateRestricted
|
||||
&& messageListType !== 'scheduled',
|
||||
);
|
||||
const shouldRenderShowWhen = Boolean(
|
||||
canLoadReadDate && isPrivate && selectUserStatus(global, chat.id)?.isReadDateRestrictedByMe,
|
||||
|
||||
@ -214,7 +214,9 @@ const MessageContextMenu: FC<OwnProps> = ({
|
||||
onShowOriginal,
|
||||
onSelectLanguage,
|
||||
}) => {
|
||||
const { showNotification, openStickerSet, openCustomEmojiSets } = getActions();
|
||||
const {
|
||||
showNotification, openStickerSet, openCustomEmojiSets, loadStickers,
|
||||
} = getActions();
|
||||
// eslint-disable-next-line no-null/no-null
|
||||
const menuRef = useRef<HTMLDivElement>(null);
|
||||
// eslint-disable-next-line no-null/no-null
|
||||
@ -244,6 +246,19 @@ const MessageContextMenu: FC<OwnProps> = ({
|
||||
}
|
||||
}, [onClose, isOpen, isReactionPickerOpen, areItemsHidden]);
|
||||
|
||||
useEffect(() => {
|
||||
if (customEmojiSets?.length) {
|
||||
customEmojiSets.map((customEmojiSet) => {
|
||||
return loadStickers({
|
||||
stickerSetInfo: {
|
||||
id: customEmojiSet.id,
|
||||
accessHash: customEmojiSet.accessHash,
|
||||
},
|
||||
});
|
||||
});
|
||||
}
|
||||
}, [customEmojiSets, openCustomEmojiSets]);
|
||||
|
||||
const handleOpenCustomEmojiSets = useLastCallback(() => {
|
||||
if (!customEmojiSets) return;
|
||||
if (customEmojiSets.length === 1) {
|
||||
|
||||
@ -1,5 +1,11 @@
|
||||
import type {
|
||||
ApiAttachment, ApiChat, ApiMessage, ApiMessageEntityTextUrl, ApiPeer, ApiStory, ApiUser,
|
||||
ApiAttachment,
|
||||
ApiChat,
|
||||
ApiMessage,
|
||||
ApiMessageEntityTextUrl,
|
||||
ApiPeer,
|
||||
ApiStory,
|
||||
ApiUser,
|
||||
} from '../../api/types';
|
||||
import type { MediaContent } from '../../api/types/messages';
|
||||
import type { LangFn } from '../../hooks/useOldLang';
|
||||
|
||||
@ -722,7 +722,7 @@ export function selectAllowedMessageActions<T extends GlobalState>(global: T, me
|
||||
const canSelect = !isLocal && !isAction;
|
||||
|
||||
const canDownload = Boolean(content.webPage?.document || content.webPage?.video || content.webPage?.photo
|
||||
|| content.audio || content.voice || content.photo || content.video || content.document || content.sticker)
|
||||
|| content.audio || content.voice || content.photo || content.video || content.document || content.sticker)
|
||||
&& !hasTtl;
|
||||
|
||||
const canSaveGif = message.content.video?.isGif;
|
||||
@ -1210,7 +1210,7 @@ export function selectLastServiceNotification<T extends GlobalState>(global: T)
|
||||
export function selectIsMessageProtected<T extends GlobalState>(global: T, message?: ApiMessage) {
|
||||
return Boolean(message && (
|
||||
message.isProtected || selectIsChatProtected(global, message.chatId) || hasMessageTtl(message)
|
||||
|| getMessagePaidMedia(message)
|
||||
|| getMessagePaidMedia(message)
|
||||
));
|
||||
}
|
||||
|
||||
@ -1246,7 +1246,7 @@ export function selectCanForwardMessages<T extends GlobalState>(global: T, chatI
|
||||
return messageIds
|
||||
.map((id) => messages[id])
|
||||
.every((message) => !hasMessageTtl(message)
|
||||
&& (message.isForwardingAllowed || isServiceNotificationMessage(message)));
|
||||
&& (message.isForwardingAllowed || isServiceNotificationMessage(message)));
|
||||
}
|
||||
|
||||
export function selectSponsoredMessage<T extends GlobalState>(global: T, chatId: string) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user