diff --git a/src/components/common/CustomEmojiSetsModal.module.scss b/src/components/common/CustomEmojiSetsModal.module.scss index ae2446792..f8a7945ce 100644 --- a/src/components/common/CustomEmojiSetsModal.module.scss +++ b/src/components/common/CustomEmojiSetsModal.module.scss @@ -40,7 +40,6 @@ .sets { position: relative; width: 100%; - min-height: 19rem; overflow-y: auto; padding: 0 0.5rem; text-align: left; diff --git a/src/components/common/CustomEmojiSetsModal.tsx b/src/components/common/CustomEmojiSetsModal.tsx index 3051e9165..31ca2ba9e 100644 --- a/src/components/common/CustomEmojiSetsModal.tsx +++ b/src/components/common/CustomEmojiSetsModal.tsx @@ -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 = ({ - 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(null); const { observe: observeIntersectionForCovers } = useIntersectionObserver({ @@ -45,11 +52,11 @@ const CustomEmojiSetsModal: FC = ({ const prevCustomEmojiSets = usePrevious(customEmojiSets); const renderingCustomEmojiSets = customEmojiSets || prevCustomEmojiSets; - const handleSetClick = useCallback((sticker: ApiSticker) => { + const handleSetClick = useLastCallback((sticker: ApiSticker) => { openStickerSet({ stickerSetInfo: sticker.stickerSetInfo, }); - }, [openStickerSet]); + }); return ( = ({ title={lang('lng_custom_emoji_used_sets')} >
- {renderingCustomEmojiSets?.map((customEmojiSet) => ( - - ))} + {renderingCustomEmojiSets?.map((customEmojiSet) => { + return ( + + ); + })}
); }; export default memo(withGlobal( - (global, { customEmojiSetIds }): StateProps => { - const customEmojiSets = customEmojiSetIds?.map((id) => global.stickers.setsById[id]); - + (global): StateProps => { return { - customEmojiSets, canPlayAnimatedEmojis: selectCanPlayAnimatedEmojis(global), }; }, diff --git a/src/components/common/StickerSetCard.tsx b/src/components/common/StickerSetCard.tsx index 331feea46..1ce30c838 100644 --- a/src/components/common/StickerSetCard.tsx +++ b/src/components/common/StickerSetCard.tsx @@ -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 = ({ 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; } diff --git a/src/components/middle/message/ContextMenuContainer.tsx b/src/components/middle/message/ContextMenuContainer.tsx index 9aebe6ded..aedecd07f 100644 --- a/src/components/middle/message/ContextMenuContainer.tsx +++ b/src/components/middle/message/ContextMenuContainer.tsx @@ -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( 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, diff --git a/src/components/middle/message/MessageContextMenu.tsx b/src/components/middle/message/MessageContextMenu.tsx index 10b7efbdc..341cfd946 100644 --- a/src/components/middle/message/MessageContextMenu.tsx +++ b/src/components/middle/message/MessageContextMenu.tsx @@ -214,7 +214,9 @@ const MessageContextMenu: FC = ({ onShowOriginal, onSelectLanguage, }) => { - const { showNotification, openStickerSet, openCustomEmojiSets } = getActions(); + const { + showNotification, openStickerSet, openCustomEmojiSets, loadStickers, + } = getActions(); // eslint-disable-next-line no-null/no-null const menuRef = useRef(null); // eslint-disable-next-line no-null/no-null @@ -244,6 +246,19 @@ const MessageContextMenu: FC = ({ } }, [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) { diff --git a/src/global/helpers/messages.ts b/src/global/helpers/messages.ts index 061c59b05..681328473 100644 --- a/src/global/helpers/messages.ts +++ b/src/global/helpers/messages.ts @@ -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'; diff --git a/src/global/selectors/messages.ts b/src/global/selectors/messages.ts index 79be10460..6f6a82723 100644 --- a/src/global/selectors/messages.ts +++ b/src/global/selectors/messages.ts @@ -722,7 +722,7 @@ export function selectAllowedMessageActions(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(global: T) export function selectIsMessageProtected(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(global: T, chatI return messageIds .map((id) => messages[id]) .every((message) => !hasMessageTtl(message) - && (message.isForwardingAllowed || isServiceNotificationMessage(message))); + && (message.isForwardingAllowed || isServiceNotificationMessage(message))); } export function selectSponsoredMessage(global: T, chatId: string) {