import React, { FC, memo, useCallback, useEffect, } from '../../../lib/teact/teact'; import { withGlobal } from '../../../lib/teact/teactn'; import { GlobalActions } from '../../../global/types'; import { ApiChat, ApiMessage, ApiUser } from '../../../api/types'; import { selectChat, selectChatMessage, selectSender, selectForwardedSender, selectUser, selectCurrentMessageList, selectReplyingToId, selectEditingId, selectEditingScheduledId, selectEditingMessage, } from '../../../modules/selectors'; import captureEscKeyListener from '../../../util/captureEscKeyListener'; import { pick } from '../../../util/iteratees'; import useAsyncRendering from '../../right/hooks/useAsyncRendering'; import useShowTransition from '../../../hooks/useShowTransition'; import buildClassName from '../../../util/buildClassName'; import { isChatPrivate } from '../../../modules/helpers'; import Button from '../../ui/Button'; import EmbeddedMessage from '../../common/EmbeddedMessage'; import './ComposerEmbeddedMessage.scss'; type StateProps = { replyingToId?: number; editingId?: number; message?: ApiMessage; sender?: ApiUser | ApiChat; shouldAnimate?: boolean; forwardedMessagesCount?: number; }; type DispatchProps = Pick; const FORWARD_RENDERING_DELAY = 300; const ComposerEmbeddedMessage: FC = ({ replyingToId, editingId, message, sender, shouldAnimate, forwardedMessagesCount, setReplyingToId, setEditingId, focusMessage, exitForwardMode, }) => { const isShown = Boolean( ((replyingToId || editingId) && message) || (sender && forwardedMessagesCount), ); const canAnimate = useAsyncRendering( [forwardedMessagesCount], forwardedMessagesCount ? FORWARD_RENDERING_DELAY : undefined, ); const { shouldRender, transitionClassNames, } = useShowTransition(canAnimate && isShown, undefined, !shouldAnimate, undefined, !shouldAnimate); const clearEmbedded = useCallback(() => { if (replyingToId) { setReplyingToId({ messageId: undefined }); } else if (editingId) { setEditingId({ messageId: undefined }); } else if (forwardedMessagesCount) { exitForwardMode(); } }, [replyingToId, editingId, forwardedMessagesCount, setReplyingToId, setEditingId, exitForwardMode]); useEffect(() => (isShown ? captureEscKeyListener(clearEmbedded) : undefined), [isShown, clearEmbedded]); const handleMessageClick = useCallback((): void => { focusMessage({ chatId: message!.chatId, messageId: message!.id }); }, [focusMessage, message]); const className = buildClassName('ComposerEmbeddedMessage', transitionClassNames); const customText = forwardedMessagesCount && forwardedMessagesCount > 1 ? `${forwardedMessagesCount} forwarded messages` : undefined; if (!shouldRender) { return undefined; } return (
); }; export default memo(withGlobal( (global): StateProps => { const { chatId, threadId, type: messageListType } = selectCurrentMessageList(global) || {}; if (!chatId || !threadId || !messageListType) { return {}; } const { currentUserId, forwardMessages: { fromChatId, toChatId, messageIds: forwardMessageIds }, } = global; const replyingToId = selectReplyingToId(global, chatId, threadId); const editingId = messageListType === 'scheduled' ? selectEditingScheduledId(global, chatId) : selectEditingId(global, chatId, threadId); const shouldAnimate = global.settings.byKey.animationLevel >= 1; const isForwarding = toChatId === chatId; let message; if (replyingToId) { message = selectChatMessage(global, chatId, replyingToId); } else if (editingId) { message = selectEditingMessage(global, chatId, threadId, messageListType); } else if (isForwarding && forwardMessageIds!.length === 1) { message = selectChatMessage(global, fromChatId!, forwardMessageIds![0]); } let sender: ApiChat | ApiUser | undefined; if (replyingToId && message) { const { forwardInfo } = message; const isChatWithSelf = chatId === currentUserId; if (forwardInfo && (forwardInfo.isChannelPost || isChatWithSelf)) { sender = selectForwardedSender(global, message); } if (!sender) { sender = selectSender(global, message); } } else if (isForwarding) { sender = isChatPrivate(fromChatId!) ? selectUser(global, fromChatId!) : selectChat(global, fromChatId!); } return { replyingToId, editingId, message, sender, shouldAnimate, forwardedMessagesCount: isForwarding ? forwardMessageIds!.length : undefined, }; }, (setGlobal, actions): DispatchProps => pick(actions, [ 'setReplyingToId', 'setEditingId', 'focusMessage', 'exitForwardMode', ]), )(ComposerEmbeddedMessage));