import type { ChangeEvent } from 'react'; import type { FC } from '../../../lib/teact/teact'; import React, { memo, useCallback, useEffect, useMemo, useState, } from '../../../lib/teact/teact'; import { getActions, withGlobal } from '../../../global'; import type { ApiAvailableReaction, ApiChat, ApiChatFullInfo, ApiExportedInvite, } from '../../../api/types'; import { ApiMediaFormat } from '../../../api/types'; import { ManagementProgress, ManagementScreens } from '../../../types'; import { getChatAvatarHash, getHasAdminRight, isChatPublic } from '../../../global/helpers'; import { selectChat, selectChatFullInfo, selectTabState } from '../../../global/selectors'; import { formatInteger } from '../../../util/textFormat'; import useFlag from '../../../hooks/useFlag'; import useHistoryBack from '../../../hooks/useHistoryBack'; import useMedia from '../../../hooks/useMedia'; import useOldLang from '../../../hooks/useOldLang'; import AvatarEditable from '../../ui/AvatarEditable'; import ConfirmDialog from '../../ui/ConfirmDialog'; import FloatingActionButton from '../../ui/FloatingActionButton'; import InputText from '../../ui/InputText'; import ListItem from '../../ui/ListItem'; import Spinner from '../../ui/Spinner'; import TextArea from '../../ui/TextArea'; import './Management.scss'; type OwnProps = { chatId: string; onScreenSelect: (screen: ManagementScreens) => void; onClose: NoneToVoidFunction; isActive: boolean; }; type StateProps = { chat: ApiChat; chatFullInfo?: ApiChatFullInfo; progress?: ManagementProgress; canChangeInfo?: boolean; canInvite?: boolean; exportedInvites?: ApiExportedInvite[]; availableReactions?: ApiAvailableReaction[]; }; const CHANNEL_TITLE_EMPTY = 'Channel title can\'t be empty'; const CHANNEL_MAX_DESCRIPTION = 255; const ManageChannel: FC = ({ chatId, chat, chatFullInfo, progress, canChangeInfo, canInvite, exportedInvites, isActive, availableReactions, onScreenSelect, onClose, }) => { const { updateChat, closeManagement, leaveChannel, deleteChannel, openChat, loadExportedChatInvites, loadChatJoinRequests, } = getActions(); const currentTitle = chat?.title || ''; const currentAbout = chatFullInfo?.about || ''; const hasLinkedChat = Boolean(chatFullInfo?.linkedChatId); const [isDeleteDialogOpen, openDeleteDialog, closeDeleteDialog] = useFlag(); const [isProfileFieldsTouched, setIsProfileFieldsTouched] = useState(false); const [title, setTitle] = useState(currentTitle); const [about, setAbout] = useState(currentAbout); const [photo, setPhoto] = useState(); const [error, setError] = useState(); const imageHash = chat && getChatAvatarHash(chat); const currentAvatarBlobUrl = useMedia(imageHash, false, ApiMediaFormat.BlobUrl); const lang = useOldLang(); useHistoryBack({ isActive, onBack: onClose, }); useEffect(() => { if (!canInvite) return; loadExportedChatInvites({ chatId }); loadExportedChatInvites({ chatId, isRevoked: true }); loadChatJoinRequests({ chatId }); }, [chatId, canInvite]); useEffect(() => { if (progress === ManagementProgress.Complete) { setIsProfileFieldsTouched(false); setError(undefined); } }, [progress]); const adminsCount = useMemo(() => { return Object.keys(chatFullInfo?.adminMembersById || {}).length; }, [chatFullInfo?.adminMembersById]); const removedUsersCount = chatFullInfo?.kickedMembers?.length || 0; const handleClickEditType = useCallback(() => { onScreenSelect(ManagementScreens.ChatPrivacyType); }, [onScreenSelect]); const handleClickDiscussion = useCallback(() => { onScreenSelect(ManagementScreens.Discussion); }, [onScreenSelect]); const handleClickReactions = useCallback(() => { onScreenSelect(ManagementScreens.Reactions); }, [onScreenSelect]); const handleClickAdministrators = useCallback(() => { onScreenSelect(ManagementScreens.ChatAdministrators); }, [onScreenSelect]); const handleClickInvites = useCallback(() => { onScreenSelect(ManagementScreens.Invites); }, [onScreenSelect]); const handleClickRequests = useCallback(() => { onScreenSelect(ManagementScreens.JoinRequests); }, [onScreenSelect]); const handleSetPhoto = useCallback((file: File) => { setPhoto(file); setIsProfileFieldsTouched(true); }, []); const handleTitleChange = useCallback((e: ChangeEvent) => { setTitle(e.target.value); setIsProfileFieldsTouched(true); }, []); const handleAboutChange = useCallback((e: ChangeEvent) => { setAbout(e.target.value); setIsProfileFieldsTouched(true); }, []); const handleUpdateChannel = useCallback(() => { const trimmedTitle = title.trim(); const trimmedAbout = about.trim(); if (!trimmedTitle.length) { setError(CHANNEL_TITLE_EMPTY); return; } updateChat({ chatId, title: trimmedTitle, about: trimmedAbout, photo, }); }, [about, chatId, photo, title, updateChat]); const handleClickSubscribers = useCallback(() => { onScreenSelect(ManagementScreens.ChannelSubscribers); }, [onScreenSelect]); const handleRemovedUsersClick = useCallback(() => { onScreenSelect(ManagementScreens.ChannelRemovedUsers); }, [onScreenSelect]); const handleDeleteChannel = useCallback(() => { if (chat.isCreator) { deleteChannel({ chatId: chat.id }); } else { leaveChannel({ chatId: chat.id }); } closeDeleteDialog(); closeManagement(); openChat({ id: undefined }); }, [chat.isCreator, chat.id, closeDeleteDialog, closeManagement, leaveChannel, deleteChannel, openChat]); const chatReactionsDescription = useMemo(() => { if (!chatFullInfo?.enabledReactions) { return lang('ReactionsOff'); } if (chatFullInfo.enabledReactions.type === 'all') { return lang('ReactionsAll'); } const enabledLength = chatFullInfo.enabledReactions.allowed.length; const totalLength = availableReactions?.filter((reaction) => !reaction.isInactive).length || 0; return totalLength ? `${enabledLength} / ${totalLength}` : `${enabledLength}`; }, [availableReactions, chatFullInfo?.enabledReactions, lang]); const isChannelPublic = useMemo(() => isChatPublic(chat), [chat]); if (chat.isRestricted || chat.isForbidden) { return undefined; } const isLoading = progress === ManagementProgress.InProgress; return (