import type { FC } from '../../lib/teact/teact'; import React, { memo, useEffect, useState, useRef, } from '../../lib/teact/teact'; import { getActions, withGlobal } from '../../global'; import type { ApiExportedInvite } from '../../api/types'; import { ManagementScreens, ProfileState } from '../../types'; import { MAIN_THREAD_ID } from '../../api/types'; import { ANIMATION_END_DELAY } from '../../config'; import { debounce } from '../../util/schedulers'; import buildClassName from '../../util/buildClassName'; import { selectChat, selectChatFullInfo, selectCurrentGifSearch, selectCurrentStickerSearch, selectCurrentTextSearch, selectIsChatWithSelf, selectTabState, selectUser, } from '../../global/selectors'; import { getCanAddContact, getCanManageTopic, isChatAdmin, isChatChannel, isUserBot, isUserId, } from '../../global/helpers'; import { getDayStartAt } from '../../util/dateFormat'; import useLastCallback from '../../hooks/useLastCallback'; import useCurrentOrPrev from '../../hooks/useCurrentOrPrev'; import useLang from '../../hooks/useLang'; import useFlag from '../../hooks/useFlag'; import useElectronDrag from '../../hooks/useElectronDrag'; import useAppLayout from '../../hooks/useAppLayout'; import SearchInput from '../ui/SearchInput'; import Button from '../ui/Button'; import Transition from '../ui/Transition'; import ConfirmDialog from '../ui/ConfirmDialog'; import './RightHeader.scss'; type OwnProps = { chatId?: string; threadId?: number; isColumnOpen?: boolean; isProfile?: boolean; isSearch?: boolean; isManagement?: boolean; isStatistics?: boolean; isMessageStatistics?: boolean; isStickerSearch?: boolean; isGifSearch?: boolean; isPollResults?: boolean; isCreatingTopic?: boolean; isEditingTopic?: boolean; isAddingChatMembers?: boolean; profileState?: ProfileState; managementScreen?: ManagementScreens; onClose: () => void; onScreenSelect: (screen: ManagementScreens) => void; }; type StateProps = { canAddContact?: boolean; canManage?: boolean; canViewStatistics?: boolean; isChannel?: boolean; userId?: string; messageSearchQuery?: string; stickerSearchQuery?: string; gifSearchQuery?: string; isEditingInvite?: boolean; currentInviteInfo?: ApiExportedInvite; shouldSkipHistoryAnimations?: boolean; isBot?: boolean; isInsideTopic?: boolean; canEditTopic?: boolean; }; const COLUMN_ANIMATION_DURATION = 450 + ANIMATION_END_DELAY; const runDebouncedForSearch = debounce((cb) => cb(), 200, false); enum HeaderContent { Profile, MemberList, SharedMedia, Search, Statistics, MessageStatistics, Management, ManageInitial, ManageChannelSubscribers, ManageChatAdministrators, ManageChatPrivacyType, ManageDiscussion, ManageGroupPermissions, ManageGroupRemovedUsers, ManageChannelRemovedUsers, ManageGroupUserPermissionsCreate, ManageGroupUserPermissions, ManageGroupRecentActions, ManageGroupAdminRights, ManageGroupNewAdminRights, ManageGroupMembers, ManageGroupAddAdmins, StickerSearch, GifSearch, PollResults, AddingMembers, ManageInvites, ManageEditInvite, ManageReactions, ManageInviteInfo, ManageJoinRequests, CreateTopic, EditTopic, } const RightHeader: FC = ({ chatId, threadId, isColumnOpen, isProfile, isSearch, isManagement, isStatistics, isMessageStatistics, isStickerSearch, isGifSearch, isPollResults, isCreatingTopic, isEditingTopic, isAddingChatMembers, profileState, managementScreen, canAddContact, userId, canManage, isChannel, onClose, onScreenSelect, messageSearchQuery, stickerSearchQuery, gifSearchQuery, isEditingInvite, canViewStatistics, currentInviteInfo, shouldSkipHistoryAnimations, isBot, isInsideTopic, canEditTopic, }) => { const { setLocalTextSearchQuery, setStickerSearchQuery, setGifSearchQuery, searchTextMessagesLocal, toggleManagement, openHistoryCalendar, openAddContactDialog, toggleStatistics, setEditingExportedInvite, deleteExportedChatInvite, openEditTopicPanel, } = getActions(); const [isDeleteDialogOpen, openDeleteDialog, closeDeleteDialog] = useFlag(); const { isMobile } = useAppLayout(); const handleEditInviteClick = useLastCallback(() => { setEditingExportedInvite({ chatId: chatId!, invite: currentInviteInfo! }); onScreenSelect(ManagementScreens.EditInvite); }); const handleDeleteInviteClick = useLastCallback(() => { deleteExportedChatInvite({ chatId: chatId!, link: currentInviteInfo!.link }); onScreenSelect(ManagementScreens.Invites); closeDeleteDialog(); }); const handleMessageSearchQueryChange = useLastCallback((query: string) => { setLocalTextSearchQuery({ query }); if (query.length) { runDebouncedForSearch(searchTextMessagesLocal); } }); const handleStickerSearchQueryChange = useLastCallback((query: string) => { setStickerSearchQuery({ query }); }); const handleGifSearchQueryChange = useLastCallback((query: string) => { setGifSearchQuery({ query }); }); const handleAddContact = useLastCallback(() => { openAddContactDialog({ userId }); }); const toggleEditTopic = useLastCallback(() => { if (!chatId || !threadId) return; openEditTopicPanel({ chatId, topicId: threadId }); }); const handleToggleManagement = useLastCallback(() => { toggleManagement(); }); const handleToggleStatistics = useLastCallback(() => { toggleStatistics(); }); const [shouldSkipTransition, setShouldSkipTransition] = useState(!isColumnOpen); useEffect(() => { setTimeout(() => { setShouldSkipTransition(!isColumnOpen); }, COLUMN_ANIMATION_DURATION); }, [isColumnOpen]); const lang = useLang(); const contentKey = isProfile ? ( profileState === ProfileState.Profile ? ( HeaderContent.Profile ) : profileState === ProfileState.SharedMedia ? ( HeaderContent.SharedMedia ) : profileState === ProfileState.MemberList ? ( HeaderContent.MemberList ) : -1 // Never reached ) : isSearch ? ( HeaderContent.Search ) : isPollResults ? ( HeaderContent.PollResults ) : isStickerSearch ? ( HeaderContent.StickerSearch ) : isGifSearch ? ( HeaderContent.GifSearch ) : isAddingChatMembers ? ( HeaderContent.AddingMembers ) : isManagement ? ( managementScreen === ManagementScreens.Initial ? ( HeaderContent.ManageInitial ) : managementScreen === ManagementScreens.ChatPrivacyType ? ( HeaderContent.ManageChatPrivacyType ) : managementScreen === ManagementScreens.Discussion ? ( HeaderContent.ManageDiscussion ) : managementScreen === ManagementScreens.ChannelSubscribers ? ( HeaderContent.ManageChannelSubscribers ) : managementScreen === ManagementScreens.GroupPermissions ? ( HeaderContent.ManageGroupPermissions ) : managementScreen === ManagementScreens.ChatAdministrators ? ( HeaderContent.ManageChatAdministrators ) : managementScreen === ManagementScreens.GroupRemovedUsers ? ( HeaderContent.ManageGroupRemovedUsers ) : managementScreen === ManagementScreens.ChannelRemovedUsers ? ( HeaderContent.ManageChannelRemovedUsers ) : managementScreen === ManagementScreens.GroupUserPermissionsCreate ? ( HeaderContent.ManageGroupUserPermissionsCreate ) : managementScreen === ManagementScreens.GroupUserPermissions ? ( HeaderContent.ManageGroupUserPermissions ) : managementScreen === ManagementScreens.GroupRecentActions ? ( HeaderContent.ManageGroupRecentActions ) : managementScreen === ManagementScreens.ChatAdminRights ? ( HeaderContent.ManageGroupAdminRights ) : managementScreen === ManagementScreens.ChatNewAdminRights ? ( HeaderContent.ManageGroupNewAdminRights ) : managementScreen === ManagementScreens.GroupMembers ? ( HeaderContent.ManageGroupMembers ) : managementScreen === ManagementScreens.Invites ? ( HeaderContent.ManageInvites ) : managementScreen === ManagementScreens.EditInvite ? ( HeaderContent.ManageEditInvite ) : managementScreen === ManagementScreens.GroupAddAdmins ? ( HeaderContent.ManageGroupAddAdmins ) : managementScreen === ManagementScreens.Reactions ? ( HeaderContent.ManageReactions ) : managementScreen === ManagementScreens.InviteInfo ? ( HeaderContent.ManageInviteInfo ) : managementScreen === ManagementScreens.JoinRequests ? ( HeaderContent.ManageJoinRequests ) : undefined // Never reached ) : isStatistics ? ( HeaderContent.Statistics ) : isMessageStatistics ? ( HeaderContent.MessageStatistics ) : isCreatingTopic ? ( HeaderContent.CreateTopic ) : isEditingTopic ? ( HeaderContent.EditTopic ) : undefined; // When column is closed const renderingContentKey = useCurrentOrPrev(contentKey, true) ?? -1; function getHeaderTitle() { if (isInsideTopic) { return lang('AccDescrTopic'); } if (isChannel) { return lang('Channel.TitleInfo'); } if (userId) { return lang(isBot ? 'lng_info_bot_title' : 'lng_info_user_title'); } return lang('GroupInfo.Title'); } function renderHeaderContent() { if (renderingContentKey === -1) { return undefined; } switch (renderingContentKey) { case HeaderContent.PollResults: return

{lang('PollResults')}

; case HeaderContent.Search: return ( <> ); case HeaderContent.AddingMembers: return

{lang(isChannel ? 'ChannelAddSubscribers' : 'GroupAddMembers')}

; case HeaderContent.ManageInitial: return

{lang('Edit')}

; case HeaderContent.ManageChatPrivacyType: return

{lang(isChannel ? 'ChannelTypeHeader' : 'GroupTypeHeader')}

; case HeaderContent.ManageDiscussion: return

{lang('Discussion')}

; case HeaderContent.ManageChatAdministrators: return

{lang('ChannelAdministrators')}

; case HeaderContent.ManageGroupRecentActions: return

{lang('Group.Info.AdminLog')}

; case HeaderContent.ManageGroupAdminRights: return

{lang('EditAdminRights')}

; case HeaderContent.ManageGroupNewAdminRights: return

{lang('SetAsAdmin')}

; case HeaderContent.ManageGroupPermissions: return

{lang('ChannelPermissions')}

; case HeaderContent.ManageGroupRemovedUsers: return

{lang('BlockedUsers')}

; case HeaderContent.ManageChannelRemovedUsers: return

{lang('ChannelBlockedUsers')}

; case HeaderContent.ManageGroupUserPermissionsCreate: return

{lang('ChannelAddException')}

; case HeaderContent.ManageGroupUserPermissions: return

{lang('UserRestrictions')}

; case HeaderContent.ManageInvites: return

{lang('lng_group_invite_title')}

; case HeaderContent.ManageEditInvite: return

{isEditingInvite ? lang('EditLink') : lang('NewLink')}

; case HeaderContent.ManageInviteInfo: return ( <>

{lang('InviteLink')}

{currentInviteInfo && !currentInviteInfo.isRevoked && ( )} {currentInviteInfo && currentInviteInfo.isRevoked && ( <> )}
); case HeaderContent.ManageJoinRequests: return

{isChannel ? lang('SubscribeRequests') : lang('MemberRequests')}

; case HeaderContent.ManageGroupAddAdmins: return

{lang('Channel.Management.AddModerator')}

; case HeaderContent.StickerSearch: return ( ); case HeaderContent.GifSearch: return ( ); case HeaderContent.Statistics: return

{lang(isChannel ? 'ChannelStats.Title' : 'GroupStats.Title')}

; case HeaderContent.MessageStatistics: return

{lang('Stats.MessageTitle')}

; case HeaderContent.SharedMedia: return

{lang('SharedMedia')}

; case HeaderContent.ManageChannelSubscribers: return

{lang('ChannelSubscribers')}

; case HeaderContent.MemberList: case HeaderContent.ManageGroupMembers: return

{lang('GroupMembers')}

; case HeaderContent.ManageReactions: return

{lang('Reactions')}

; case HeaderContent.CreateTopic: return

{lang('NewTopic')}

; case HeaderContent.EditTopic: return

{lang('EditTopic')}

; default: return ( <>

{getHeaderTitle()}

{canAddContact && ( )} {canManage && !isInsideTopic && !isBot && ( )} {canEditTopic && ( )} {canViewStatistics && ( )}
); } } const isBackButton = ( isMobile || contentKey === HeaderContent.SharedMedia || contentKey === HeaderContent.MemberList || contentKey === HeaderContent.AddingMembers || contentKey === HeaderContent.MessageStatistics || isManagement ); const buttonClassName = buildClassName( 'animated-close-icon', isBackButton && 'state-back', (shouldSkipTransition || shouldSkipHistoryAnimations) && 'no-transition', ); // eslint-disable-next-line no-null/no-null const headerRef = useRef(null); useElectronDrag(headerRef); return (
{renderHeaderContent()}
); }; export default memo(withGlobal( (global, { chatId, isProfile, isManagement, threadId, }): StateProps => { const tabState = selectTabState(global); const { query: messageSearchQuery } = selectCurrentTextSearch(global) || {}; const { query: stickerSearchQuery } = selectCurrentStickerSearch(global) || {}; const { query: gifSearchQuery } = selectCurrentGifSearch(global) || {}; const chat = chatId ? selectChat(global, chatId) : undefined; const user = isProfile && chatId && isUserId(chatId) ? selectUser(global, chatId) : undefined; const isChannel = chat && isChatChannel(chat); const isInsideTopic = chat?.isForum && Boolean(threadId && threadId !== MAIN_THREAD_ID); const topic = isInsideTopic ? chat.topics?.[threadId!] : undefined; const canEditTopic = isInsideTopic && topic && getCanManageTopic(chat, topic); const isBot = user && isUserBot(user); const canAddContact = user && getCanAddContact(user); const canManage = Boolean( !isManagement && isProfile && !canAddContact && chat && !selectIsChatWithSelf(global, chat.id) // chat.isCreator is for Basic Groups && (isUserId(chat.id) || ((isChatAdmin(chat) || chat.isCreator) && !chat.isNotJoined)), ); const isEditingInvite = Boolean(chatId && tabState.management.byChatId[chatId]?.editingInvite); const canViewStatistics = !isInsideTopic && chatId ? selectChatFullInfo(global, chatId)?.canViewStatistics : undefined; const currentInviteInfo = chatId ? tabState.management.byChatId[chatId]?.inviteInfo?.invite : undefined; return { canManage, canAddContact, canViewStatistics, isChannel, isBot, isInsideTopic, canEditTopic, userId: user?.id, messageSearchQuery, stickerSearchQuery, gifSearchQuery, isEditingInvite, currentInviteInfo, shouldSkipHistoryAnimations: tabState.shouldSkipHistoryAnimations, }; }, )(RightHeader));