import React, { memo, useCallback } from '../../../lib/teact/teact'; import { getActions, withGlobal } from '../../../global'; import type { FC } from '../../../lib/teact/teact'; import type { ApiChat, ApiFormattedText, ApiTopic, ApiMessage, ApiMessageOutgoingStatus, ApiTypingStatus, ApiUser, } from '../../../api/types'; import type { ObserveFn } from '../../../hooks/useIntersectionObserver'; import type { ChatAnimationTypes } from './hooks'; import type { AnimationLevel } from '../../../types'; import { selectCanDeleteTopic, selectChat, selectChatMessage, selectCurrentMessageList, selectDraft, selectOutgoingStatus, selectThreadInfo, selectThreadParam, selectUser, } from '../../../global/selectors'; import buildClassName from '../../../util/buildClassName'; import useChatListEntry from './hooks/useChatListEntry'; import renderText from '../../common/helpers/renderText'; import { getMessageAction } from '../../../global/helpers'; import useTopicContextActions from './hooks/useTopicContextActions'; import useFlag from '../../../hooks/useFlag'; import useLang from '../../../hooks/useLang'; import ListItem from '../../ui/ListItem'; import LastMessageMeta from '../../common/LastMessageMeta'; import Badge from './Badge'; import ConfirmDialog from '../../ui/ConfirmDialog'; import TopicIcon from '../../common/TopicIcon'; import styles from './Topic.module.scss'; type OwnProps = { chatId: string; topic: ApiTopic; isSelected: boolean; style: string; observeIntersection?: ObserveFn; orderDiff: number; animationType: ChatAnimationTypes; }; type StateProps = { chat: ApiChat; canDelete?: boolean; lastMessage?: ApiMessage; lastMessageOutgoingStatus?: ApiMessageOutgoingStatus; actionTargetMessage?: ApiMessage; actionTargetUserIds?: string[]; lastMessageSender?: ApiUser | ApiChat; actionTargetChatId?: string; animationLevel?: AnimationLevel; typingStatus?: ApiTypingStatus; draft?: ApiFormattedText; canScrollDown?: boolean; wasTopicOpened?: boolean; }; const Topic: FC = ({ topic, isSelected, chatId, chat, style, lastMessage, canScrollDown, lastMessageOutgoingStatus, observeIntersection, canDelete, actionTargetMessage, actionTargetUserIds, actionTargetChatId, lastMessageSender, animationType, animationLevel, orderDiff, typingStatus, draft, wasTopicOpened, }) => { const { openChat, deleteTopic, focusLastMessage } = getActions(); const lang = useLang(); const [isDeleteModalOpen, openDeleteModal, closeDeleteModal] = useFlag(); const [shouldRenderDeleteModal, markRenderDeleteModal, unmarkRenderDeleteModal] = useFlag(); const { isPinned, isClosed, } = topic; const isMuted = topic.isMuted || (topic.isMuted === undefined && chat.isMuted); const handleOpenDeleteModal = useCallback(() => { markRenderDeleteModal(); openDeleteModal(); }, [markRenderDeleteModal, openDeleteModal]); const handleDelete = useCallback(() => { deleteTopic({ chatId: chat.id, topicId: topic.id }); }, [chat.id, deleteTopic, topic.id]); const { renderSubtitle, ref } = useChatListEntry({ chat, chatId, lastMessage, draft, actionTargetMessage, actionTargetUserIds, actionTargetChatId, lastMessageSender, lastMessageTopic: topic, observeIntersection, isTopic: true, typingStatus, animationType, animationLevel, orderDiff, }); const handleOpenTopic = useCallback(() => { openChat({ id: chatId, threadId: topic.id, shouldReplaceHistory: true }); if (canScrollDown) { focusLastMessage(); } }, [openChat, chatId, topic.id, canScrollDown, focusLastMessage]); const contextActions = useTopicContextActions(topic, chat, wasTopicOpened, canDelete, handleOpenDeleteModal); return (

{renderText(topic.title)}

{topic.isMuted && }
{isClosed && ( )} {lastMessage && ( )}
{renderSubtitle()}
{shouldRenderDeleteModal && ( )} ); }; export default memo(withGlobal( (global, { chatId, topic, isSelected }) => { const chat = selectChat(global, chatId); const lastMessage = selectChatMessage(global, chatId, topic.lastMessageId)!; const { senderId, replyToMessageId, isOutgoing } = lastMessage || {}; const lastMessageSender = senderId ? (selectUser(global, senderId) || selectChat(global, senderId)) : undefined; const lastMessageAction = lastMessage ? getMessageAction(lastMessage) : undefined; const actionTargetMessage = lastMessageAction && replyToMessageId ? selectChatMessage(global, chatId, replyToMessageId) : undefined; const { targetUserIds: actionTargetUserIds, targetChatId: actionTargetChatId } = lastMessageAction || {}; const typingStatus = selectThreadParam(global, chatId, topic.id, 'typingStatus'); const draft = selectDraft(global, chatId, topic.id); const threadInfo = selectThreadInfo(global, chatId, topic.id); const wasTopicOpened = Boolean(threadInfo?.lastReadInboxMessageId); const { chatId: currentChatId, threadId: currentThreadId } = selectCurrentMessageList(global) || {}; return { chat, lastMessage, actionTargetUserIds, actionTargetChatId, actionTargetMessage, lastMessageSender, typingStatus, canDelete: selectCanDeleteTopic(global, chatId, topic.id), animationLevel: global.settings.byKey.animationLevel, draft, ...(isOutgoing && lastMessage && { lastMessageOutgoingStatus: selectOutgoingStatus(global, lastMessage), }), canScrollDown: isSelected && chat?.id === currentChatId && currentThreadId === topic.id, wasTopicOpened, }; }, )(Topic));