import type { FC } from '../../lib/teact/teact'; import React, { memo, useEffect, useMemo, useState, } from '../../lib/teact/teact'; import { getActions, withGlobal } from '../../global'; import type { ApiChat, ApiCountryCode, ApiUser, ApiUsername, } from '../../api/types'; import { MAIN_THREAD_ID } from '../../api/types'; import { TME_LINK_PREFIX } from '../../config'; import { getChatLink, getHasAdminRight, isChatChannel, isUserId, isUserRightBanned, selectIsChatMuted, } from '../../global/helpers'; import { selectChat, selectChatFullInfo, selectCurrentMessageList, selectNotifyExceptions, selectNotifySettings, selectTopicLink, selectUser, selectUserFullInfo, } from '../../global/selectors'; import { copyTextToClipboard } from '../../util/clipboard'; import { formatPhoneNumberWithCode } from '../../util/phoneNumber'; import { debounce } from '../../util/schedulers'; import stopEvent from '../../util/stopEvent'; import renderText from './helpers/renderText'; import useEffectWithPrevDeps from '../../hooks/useEffectWithPrevDeps'; import useLang from '../../hooks/useLang'; import useLastCallback from '../../hooks/useLastCallback'; import ListItem from '../ui/ListItem'; import Switcher from '../ui/Switcher'; type OwnProps = { chatOrUserId: string; isSavedDialog?: boolean; isInSettings?: boolean; }; type StateProps = { user?: ApiUser; chat?: ApiChat; canInviteUsers?: boolean; isMuted?: boolean; phoneCodeList: ApiCountryCode[]; topicId?: number; description?: string; chatInviteLink?: string; topicLink?: string; hasSavedMessages?: boolean; }; const runDebounced = debounce((cb) => cb(), 500, false); const ChatExtra: FC = ({ chatOrUserId, user, chat, isInSettings, canInviteUsers, isMuted, phoneCodeList, topicId, description, chatInviteLink, topicLink, hasSavedMessages, }) => { const { loadFullUser, showNotification, updateChatMutedState, updateTopicMutedState, loadPeerStories, openSavedDialog, } = getActions(); const { id: userId, usernames, phoneNumber, isSelf, } = user || {}; const { id: chatId, usernames: chatUsernames } = chat || {}; const peerId = userId || chatId; const lang = useLang(); const [areNotificationsEnabled, setAreNotificationsEnabled] = useState(!isMuted); useEffect(() => { setAreNotificationsEnabled(!isMuted); }, [isMuted]); useEffect(() => { if (!userId) return; loadFullUser({ userId }); }, [userId]); useEffectWithPrevDeps(([prevPeerId]) => { if (!peerId || prevPeerId === peerId) return; if (user || (chat && isChatChannel(chat))) { loadPeerStories({ peerId }); } }, [peerId, chat, user]); const isTopicInfo = Boolean(topicId && topicId !== MAIN_THREAD_ID); const activeUsernames = useMemo(() => { const result = usernames?.filter((u) => u.isActive); return result?.length ? result : undefined; }, [usernames]); const activeChatUsernames = useMemo(() => { const result = !user ? chatUsernames?.filter((u) => u.isActive) : undefined; return result?.length ? result : undefined; }, [chatUsernames, user]); const link = useMemo(() => { if (!chat) { return undefined; } return isTopicInfo ? topicLink! : getChatLink(chat) || chatInviteLink; }, [chat, isTopicInfo, topicLink, chatInviteLink]); const handleNotificationChange = useLastCallback(() => { setAreNotificationsEnabled((current) => { const newAreNotificationsEnabled = !current; runDebounced(() => { if (isTopicInfo) { updateTopicMutedState({ chatId: chatId!, topicId: topicId!, isMuted: !newAreNotificationsEnabled, }); } else { updateChatMutedState({ chatId: chatId!, isMuted: !newAreNotificationsEnabled }); } }); return newAreNotificationsEnabled; }); }); const handleOpenSavedDialog = useLastCallback(() => { openSavedDialog({ chatId: chatOrUserId }); }); if (!chat || chat.isRestricted || (isSelf && !isInSettings)) { return undefined; } function copy(text: string, entity: string) { copyTextToClipboard(text); showNotification({ message: `${entity} was copied` }); } const formattedNumber = phoneNumber && formatPhoneNumberWithCode(phoneCodeList, phoneNumber); function renderUsernames(usernameList: ApiUsername[], isChat?: boolean) { const [mainUsername, ...otherUsernames] = usernameList; const usernameLinks = otherUsernames.length ? (lang('UsernameAlso', '%USERNAMES%') as string) .split('%') .map((s) => { return (s === 'USERNAMES' ? ( <> {otherUsernames.map(({ username: nick }, idx) => { const textToCopy = isChat ? `${TME_LINK_PREFIX}${nick}` : `@${nick}`; return ( <> {idx > 0 ? ', ' : ''} { stopEvent(e); copy(textToCopy, lang(isChat ? 'Link' : 'Username')); }} className="text-entity-link username-link" > {`@${nick}`} ); })} ) : s); }) : undefined; const username = isChat ? `t.me/${mainUsername.username}` : mainUsername.username; const textToCopy = isChat ? `${TME_LINK_PREFIX}${mainUsername.username}` : `@${mainUsername.username}`; return ( copy(textToCopy, lang(isChat ? 'Link' : 'Username'))} > {username} {usernameLinks && {usernameLinks}} {lang(isChat ? 'Link' : 'Username')} ); } return (
{formattedNumber && Boolean(formattedNumber.length) && ( // eslint-disable-next-line react/jsx-no-bind copy(formattedNumber, lang('Phone'))}> {formattedNumber} {lang('Phone')} )} {activeUsernames && renderUsernames(activeUsernames)} {description && Boolean(description.length) && ( {renderText(description, ['br', 'links', 'emoji'])} {lang(userId ? 'UserBio' : 'Info')} )} {activeChatUsernames && !isTopicInfo && renderUsernames(activeChatUsernames, true)} {((!activeChatUsernames && canInviteUsers) || isTopicInfo) && link && ( copy(link, lang('SetUrlPlaceholder'))} >
{link}
{lang('SetUrlPlaceholder')}
)} {!isInSettings && ( {lang('Notifications')} )} {hasSavedMessages && !isInSettings && ( {lang('SavedMessagesTab')} )}
); }; export default memo(withGlobal( (global, { chatOrUserId, isSavedDialog }): StateProps => { const { countryList: { phoneCodes: phoneCodeList } } = global; const chat = chatOrUserId ? selectChat(global, chatOrUserId) : undefined; const user = isUserId(chatOrUserId) ? selectUser(global, chatOrUserId) : undefined; const isForum = chat?.isForum; const isMuted = chat && selectIsChatMuted(chat, selectNotifySettings(global), selectNotifyExceptions(global)); const { threadId } = selectCurrentMessageList(global) || {}; const topicId = isForum ? Number(threadId) : undefined; const chatInviteLink = chat ? selectChatFullInfo(global, chat.id)?.inviteLink : undefined; let description = user ? selectUserFullInfo(global, user.id)?.bio : undefined; if (!description && chat) { description = selectChatFullInfo(global, chat.id)?.about; } const canInviteUsers = chat && !user && ( (!isChatChannel(chat) && !isUserRightBanned(chat, 'inviteUsers')) || getHasAdminRight(chat, 'inviteUsers') ); const topicLink = topicId ? selectTopicLink(global, chatOrUserId, topicId) : undefined; const hasSavedMessages = !isSavedDialog && global.chats.listIds.saved?.includes(chatOrUserId); return { phoneCodeList, chat, user, canInviteUsers, isMuted, topicId, chatInviteLink, description, topicLink, hasSavedMessages, }; }, )(ChatExtra));