import type { FC } from '../../../lib/teact/teact'; import React, { memo, useCallback, useEffect, useMemo, } from '../../../lib/teact/teact'; import { getActions, getGlobal, withGlobal } from '../../../global'; import type { ApiGroupCall } from '../../../api/types'; import { selectChat, selectTabState } from '../../../global/selectors'; import { selectChatGroupCall } from '../../../global/selectors/calls'; import buildClassName from '../../../util/buildClassName'; import useCurrentOrPrev from '../../../hooks/useCurrentOrPrev'; import useLang from '../../../hooks/useLang'; import useShowTransition from '../../../hooks/useShowTransition'; import AvatarList from '../../common/AvatarList'; import Button from '../../ui/Button'; import './GroupCallTopPane.scss'; type OwnProps = { chatId: string; hasPinnedOffset: boolean; className?: string; }; type StateProps = { groupCall?: ApiGroupCall; isActive: boolean; }; const PREVIEW_AVATARS_COUNT = 3; const GroupCallTopPane: FC = ({ chatId, isActive, className, groupCall, hasPinnedOffset, }) => { const { requestMasterAndJoinGroupCall, subscribeToGroupCallUpdates, } = getActions(); const lang = useLang(); const handleJoinGroupCall = useCallback(() => { requestMasterAndJoinGroupCall({ chatId, }); }, [requestMasterAndJoinGroupCall, chatId]); const participants = groupCall?.participants; const fetchedParticipants = useMemo(() => { if (!participants) { return []; } // No need for expensive global updates on users and chats, so we avoid them const usersById = getGlobal().users.byId; const chatsById = getGlobal().chats.byId; return Object.values(participants) .slice(0, PREVIEW_AVATARS_COUNT) .map(({ id }) => usersById[id] || chatsById[id]) .filter(Boolean); }, [participants]); useEffect(() => { if (!groupCall?.id) return undefined; if (!isActive && groupCall.isLoaded) return undefined; subscribeToGroupCallUpdates({ id: groupCall.id, subscribed: true, }); return () => { subscribeToGroupCallUpdates({ id: groupCall.id, subscribed: false, }); }; }, [groupCall?.id, groupCall?.isLoaded, isActive, subscribeToGroupCallUpdates]); const { shouldRender, transitionClassNames, } = useShowTransition(Boolean(groupCall && isActive)); const renderingParticipantCount = useCurrentOrPrev(groupCall?.participantsCount, true); const renderingFetchedParticipants = useCurrentOrPrev(fetchedParticipants, true); if (!shouldRender) return undefined; return (
{lang('VoipGroupVoiceChat')} {lang('Participants', renderingParticipantCount ?? 0, 'i')}
{Boolean(renderingFetchedParticipants?.length) && ( )}
); }; export default memo(withGlobal( (global, { chatId }): StateProps => { const chat = selectChat(global, chatId)!; const groupCall = selectChatGroupCall(global, chatId); const activeGroupCallId = selectTabState(global).isMasterTab ? global.groupCalls.activeGroupCallId : undefined; return { groupCall, isActive: activeGroupCallId !== groupCall?.id && Boolean( groupCall ? groupCall.participantsCount > 0 && groupCall.isLoaded : chat && chat.isCallNotEmpty && chat.isCallActive, ), }; }, )(GroupCallTopPane));