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