import { memo, useEffect, useMemo } from '../../lib/teact/teact'; import { getActions, withGlobal } from '../../global'; import type { ApiChatMember, ApiTopic, ApiTypingStatus, ApiUser, ApiUserStatus, } from '../../api/types'; import type { CustomPeer, StoryViewerOrigin, ThreadId } from '../../types'; import type { IconName } from '../../types/icons'; import { MediaViewerOrigin } from '../../types'; import { getMainUsername, getUserStatus, isSystemBot, isUserOnline, } from '../../global/helpers'; import { selectChatMessages, selectThreadMessagesCount, selectTopic, selectUser, selectUserStatus, } from '../../global/selectors'; import buildClassName from '../../util/buildClassName'; import { REM } from './helpers/mediaDimensions'; import renderText from './helpers/renderText'; import useIntervalForceUpdate from '../../hooks/schedulers/useIntervalForceUpdate'; import useLang from '../../hooks/useLang'; import useLastCallback from '../../hooks/useLastCallback'; import useOldLang from '../../hooks/useOldLang'; import RippleEffect from '../ui/RippleEffect'; import Transition from '../ui/Transition'; import Avatar from './Avatar'; import DotAnimation from './DotAnimation'; import FullNameTitle from './FullNameTitle'; import Icon from './icons/Icon'; import TopicIcon from './TopicIcon'; import TypingStatus from './TypingStatus'; const TOPIC_ICON_SIZE = 2.5 * REM; type BaseOwnProps = { typingStatus?: ApiTypingStatus; avatarSize?: 'tiny' | 'small' | 'medium' | 'large' | 'jumbo'; forceShowSelf?: boolean; status?: string; statusIcon?: IconName; ripple?: boolean; withDots?: boolean; withMediaViewer?: boolean; withUsername?: boolean; withStory?: boolean; withFullInfo?: boolean; withUpdatingStatus?: boolean; storyViewerOrigin?: StoryViewerOrigin; noEmojiStatus?: boolean; noFake?: boolean; noVerified?: boolean; emojiStatusSize?: number; noStatusOrTyping?: boolean; noRtl?: boolean; adminMember?: ApiChatMember; isSavedDialog?: boolean; noAvatar?: boolean; className?: string; iconElement?: React.ReactNode; rightElement?: React.ReactNode; onClick?: VoidFunction; onEmojiStatusClick?: VoidFunction; }; type OwnProps = BaseOwnProps & ({ userId: string; threadId?: ThreadId; customPeer?: never; } | { userId?: never; threadId?: never; customPeer: CustomPeer; }); type StateProps = { user?: ApiUser; userStatus?: ApiUserStatus; self?: ApiUser; isSavedMessages?: boolean; areMessagesLoaded: boolean; isSynced?: boolean; topic?: ApiTopic; messagesCount?: number; }; const UPDATE_INTERVAL = 1000 * 60; // 1 min const PrivateChatInfo = ({ userId, customPeer, typingStatus, avatarSize = 'medium', status, statusIcon, withDots, withMediaViewer, withUsername, withStory, withFullInfo, withUpdatingStatus, emojiStatusSize, noStatusOrTyping, noEmojiStatus, noFake, noVerified, noRtl, user, userStatus, self, topic, messagesCount, isSavedMessages, isSavedDialog, areMessagesLoaded, adminMember, ripple, className, storyViewerOrigin, noAvatar, isSynced, iconElement, rightElement, onClick, onEmojiStatusClick, }: OwnProps & StateProps) => { const { loadFullUser, openMediaViewer, loadMoreProfilePhotos, } = getActions(); const oldLang = useOldLang(); const lang = useLang(); const isTopic = Boolean(user?.isBotForum && topic); const hasAvatarMediaViewer = withMediaViewer && !isSavedMessages; useEffect(() => { if (userId) { if (withFullInfo && isSynced) loadFullUser({ userId }); if (withMediaViewer) loadMoreProfilePhotos({ peerId: userId, isPreload: true }); } }, [userId, withFullInfo, withMediaViewer, isSynced]); useIntervalForceUpdate(UPDATE_INTERVAL); const handleAvatarViewerOpen = useLastCallback( (e: React.MouseEvent, hasMedia: boolean) => { if (hasMedia) { e.stopPropagation(); openMediaViewer({ isAvatarView: true, chatId: userId, mediaIndex: 0, origin: avatarSize === 'jumbo' ? MediaViewerOrigin.ProfileAvatar : MediaViewerOrigin.MiddleHeaderAvatar, }); } }, ); const mainUsername = useMemo(() => user && withUsername && getMainUsername(user), [user, withUsername]); if (!user && !customPeer) { return undefined; } function renderStatusOrTyping() { if (status) { return withDots ? ( ) : ( {statusIcon && } {renderText(status)} ); } if (withUpdatingStatus && !areMessagesLoaded) { return ( ); } if (customPeer?.subtitleKey) { return ( {oldLang(customPeer.subtitleKey)} ); } if (!user) { return undefined; } if (typingStatus) { return ; } if (isTopic) { return ( {messagesCount !== undefined ? oldLang('messages', messagesCount, 'i') : oldLang('lng_forum_no_messages')} ); } if (isSystemBot(user.id)) { return undefined; } const translatedStatus = getUserStatus(oldLang, user, userStatus); const mainUserNameClassName = buildClassName('handle', translatedStatus && 'withStatus'); return ( {mainUsername && {mainUsername}} {translatedStatus && {translatedStatus}} ); } const customTitle = adminMember ? adminMember.customTitle || oldLang(adminMember.isOwner ? 'GroupInfo.LabelOwner' : 'GroupInfo.LabelAdmin') : undefined; function renderNameTitle() { if (isTopic) { return (

{renderText(topic!.title)}

); } if (customTitle) { return (
{customTitle && {customTitle}}
); } return ( ); } return (
{isSavedDialog && self && ( )} {!noAvatar && !isTopic && ( )} {isTopic && ( )}
{renderNameTitle()} {(status || (!isSavedMessages && !noStatusOrTyping)) && renderStatusOrTyping()}
{ripple && } {rightElement}
); }; export default memo(withGlobal( (global, { userId, threadId, forceShowSelf }): Complete => { const { isSynced } = global; const user = userId ? selectUser(global, userId) : undefined; const userStatus = userId ? selectUserStatus(global, userId) : undefined; const isSavedMessages = !forceShowSelf && user && user.isSelf; const self = isSavedMessages ? user : selectUser(global, global.currentUserId!); const areMessagesLoaded = Boolean(userId ? selectChatMessages(global, userId) : undefined); const topic = threadId ? selectTopic(global, userId, threadId) : undefined; const messagesCount = topic && userId ? selectThreadMessagesCount(global, userId, threadId!) : undefined; return { user, userStatus, isSavedMessages, areMessagesLoaded, self, isSynced, topic, messagesCount, }; }, )(PrivateChatInfo));