import type React from 'react'; import { useState, useRef, useMemo, useCallback } from 'react'; import { IconVideoFilled, Dialog, useUIKit, } from '@tencentcloud/uikit-base-component-react'; import cs from 'classnames'; import { View, UserPicker, ConversationType, useChatContext, useLoginStore, } from 'tuikit-atomicx-react/chat'; import { startCall } from '../../../utils/call'; import classes from './VideoCallPicker.module.scss'; import type { GroupMember, IUserPickerRef } from 'tuikit-atomicx-react/chat'; interface VideoCallPickerProps { /** * Label text for the button */ label?: string; /** * Icon size in pixels */ iconSize?: number; /** * Whether the button is disabled */ disabled?: boolean; /** * Custom className for the button */ className?: string; /** * Custom style for the button */ style?: React.CSSProperties; /** * Custom icon slot */ children?: React.ReactNode; } interface GroupMemberOption { key: string; label: string; avatarUrl?: string; } const VIDEO_CALL_TYPE = 2; const MAX_GROUP_CALL_MEMBERS = 8; const MIN_GROUP_CALL_MEMBERS = 1; const VideoCallPicker = (props: VideoCallPickerProps) => { const { label = '', iconSize = 20, disabled = false, className, style, children, } = props; const { t } = useUIKit(); const { loginUserInfo } = useLoginStore(); const { activeConversation, memberList, hasMoreMembers, loadMembers, loadMoreMembers, } = useChatContext(); const [isGroupCallDialogVisible, setIsGroupCallDialogVisible] = useState(false); const groupMemberPickerRef = useRef(null); const selfUserId = useMemo(() => loginUserInfo?.userID, [loginUserInfo]); const isPrivateConversation = useMemo(() => activeConversation?.type === ConversationType.C2C, [activeConversation]); const groupMemberOptions = useMemo(() => memberList?.map((member: GroupMember) => ({ key: member.userID, label: member.nameCard || member.nickname || member.userID, ...(member.avatarURL ? { avatarUrl: member.avatarURL } : {}), })) ?? [], [memberList]); const canStartCall = useMemo(() => { if (!activeConversation || disabled) { return false; } return true; }, [activeConversation, disabled]); const initiatePrivateCall = useCallback((): void => { const peerUserId = activeConversation?.conversationID?.startsWith('C2C') ? activeConversation.conversationID.slice(3) : ''; if (!peerUserId) { console.warn('No peer user ID found for C2C call'); return; } try { startCall({ userIDList: [peerUserId], type: VIDEO_CALL_TYPE, }); } catch (error) { console.error('Failed to start private video call:', error); } }, [activeConversation?.conversationID]); const loadMoreGroupMembers = useCallback((): void => { if (activeConversation?.type !== ConversationType.Group) { return; } if (memberList.length === 0) { loadMembers(); return; } if (hasMoreMembers) { loadMoreMembers(); } }, [activeConversation?.type, memberList.length, hasMoreMembers, loadMembers, loadMoreMembers]); const showGroupCallDialog = useCallback((): void => { loadMoreGroupMembers(); setIsGroupCallDialogVisible(true); }, [loadMoreGroupMembers]); const handleCloseGroupCallDialog = useCallback(() => { setIsGroupCallDialogVisible(false); }, []); const initiateGroupCall = useCallback((): void => { const currentGroupId = activeConversation?.conversationID?.startsWith('GROUP') ? activeConversation.conversationID.slice(5) : ''; if (!groupMemberPickerRef.current || !currentGroupId) { console.warn('Missing group information for group call'); return; } const selectedMembers = groupMemberPickerRef.current.getSelectedItems(); if (!Array.isArray(selectedMembers) || selectedMembers.length === 0) { console.warn('No members selected for group call'); return; } const selectedUserIds = selectedMembers.map(member => member.key); try { startCall({ userIDList: selectedUserIds, chatGroupID: currentGroupId, type: VIDEO_CALL_TYPE, }); handleCloseGroupCallDialog(); } catch (error) { console.error('Failed to start group video call:', error); } }, [activeConversation, handleCloseGroupCallDialog]); const handleVideoCallClick = useCallback(() => { if (!canStartCall) { console.warn('Cannot start video call'); return; } if (isPrivateConversation) { initiatePrivateCall(); } else { showGroupCallDialog(); } }, [canStartCall, isPrivateConversation, initiatePrivateCall, showGroupCallDialog]); const handleConfirmGroupCall = useCallback(() => { initiateGroupCall(); }, [initiateGroupCall]); return ( <> ); }; export { VideoCallPicker }; export type { VideoCallPickerProps };