feat(CallScreen): enhance video call functionality and UI updates
- Integrated video call support by adding local and remote video stream handling. - Implemented state management for video track detection in both local and peer streams. - Updated UI to conditionally render video components based on the presence of video tracks. - Added video toggle functionality to enable or disable local video during calls. - Enhanced incoming call modal to display call type (voice or video). - Refactored call store to manage call types and video state more effectively.
This commit is contained in:
@@ -423,15 +423,6 @@ export const ChatScreen: React.FC = () => {
|
||||
onMorePress={navigateToChatSettings}
|
||||
onGroupInfoPress={handleGroupInfoPress}
|
||||
isWideScreen={isWideScreen}
|
||||
onCallPress={!isGroupChat ? () => {
|
||||
const otherUserId = otherUser?.id;
|
||||
if (otherUserId && conversationId) {
|
||||
callStore.getState().startCall(conversationId, otherUserId, {
|
||||
nickname: otherUser?.nickname,
|
||||
avatar: otherUser?.avatar,
|
||||
});
|
||||
}
|
||||
} : undefined}
|
||||
/>
|
||||
|
||||
{/* 消息列表 */}
|
||||
|
||||
@@ -23,7 +23,6 @@ export const ChatHeader: React.FC<ChatHeaderProps> = ({
|
||||
onMorePress,
|
||||
onGroupInfoPress,
|
||||
isWideScreen: propIsWideScreen,
|
||||
onCallPress,
|
||||
}) => {
|
||||
const colors = useAppColors();
|
||||
const baseStyles = useChatScreenStyles();
|
||||
@@ -125,30 +124,13 @@ export const ChatHeader: React.FC<ChatHeaderProps> = ({
|
||||
>
|
||||
<MaterialCommunityIcons name="dots-horizontal" size={22} color={colors.text.primary} />
|
||||
</TouchableOpacity>
|
||||
) : isGroupChat ? (
|
||||
) : (
|
||||
<TouchableOpacity
|
||||
style={styles.moreButton}
|
||||
onPress={onMorePress}
|
||||
>
|
||||
<MaterialCommunityIcons name="dots-horizontal" size={22} color={colors.text.primary} />
|
||||
</TouchableOpacity>
|
||||
) : (
|
||||
<View style={styles.headerActions}>
|
||||
{onCallPress && (
|
||||
<TouchableOpacity
|
||||
style={styles.callButton}
|
||||
onPress={onCallPress}
|
||||
>
|
||||
<MaterialCommunityIcons name="phone" size={22} color={colors.primary.main} />
|
||||
</TouchableOpacity>
|
||||
)}
|
||||
<TouchableOpacity
|
||||
style={styles.moreButton}
|
||||
onPress={onMorePress}
|
||||
>
|
||||
<MaterialCommunityIcons name="dots-horizontal" size={22} color={colors.text.primary} />
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
</View>
|
||||
|
||||
@@ -143,6 +143,8 @@ export const EMOJIS = [
|
||||
|
||||
// 更多功能项
|
||||
export const MORE_ACTIONS: MoreAction[] = [
|
||||
{ id: 'voice_call', icon: 'phone', name: '语音通话', color: '#4CAF50' },
|
||||
{ id: 'video_call', icon: 'video', name: '视频通话', color: '#2196F3' },
|
||||
{ id: 'image', icon: 'image', name: '图片', color: '#FF6B6B' },
|
||||
{ id: 'camera', icon: 'camera', name: '拍摄', color: '#4ECDC4' },
|
||||
{ id: 'file', icon: 'file-document', name: '文件', color: '#45B7D1' },
|
||||
|
||||
@@ -179,8 +179,6 @@ export interface ChatHeaderProps {
|
||||
onGroupInfoPress?: () => void;
|
||||
/** 是否为大屏幕模式 */
|
||||
isWideScreen?: boolean;
|
||||
/** 拨打电话回调(仅私聊有效) */
|
||||
onCallPress?: () => void;
|
||||
}
|
||||
|
||||
// 回复预览 Props
|
||||
|
||||
@@ -26,7 +26,7 @@ import { messageService } from '../../../../services/messageService';
|
||||
import { uploadService } from '../../../../services/uploadService';
|
||||
import { ApiError } from '../../../../services/api';
|
||||
// 【新架构】使用 MessageManager
|
||||
import { useChat, useGroupTyping, useGroupMuted, messageManager } from '../../../../stores';
|
||||
import { useChat, useGroupTyping, useGroupMuted, messageManager, callStore } from '../../../../stores';
|
||||
import { groupService } from '../../../../services/groupService';
|
||||
import { userManager } from '../../../../stores/userManager';
|
||||
import { groupManager } from '../../../../stores/groupManager';
|
||||
@@ -1060,6 +1060,24 @@ export const useChatScreen = () => {
|
||||
// 处理更多功能
|
||||
const handleMoreAction = useCallback((actionId: string) => {
|
||||
switch (actionId) {
|
||||
case 'voice_call':
|
||||
if (!isGroupChat && otherUser?.id && conversationId) {
|
||||
callStore.getState().startCall(conversationId, otherUser.id, {
|
||||
nickname: otherUser.nickname,
|
||||
avatar: otherUser.avatar,
|
||||
}, 'voice');
|
||||
}
|
||||
setActivePanel('none');
|
||||
break;
|
||||
case 'video_call':
|
||||
if (!isGroupChat && otherUser?.id && conversationId) {
|
||||
callStore.getState().startCall(conversationId, otherUser.id, {
|
||||
nickname: otherUser.nickname,
|
||||
avatar: otherUser.avatar,
|
||||
}, 'video');
|
||||
}
|
||||
setActivePanel('none');
|
||||
break;
|
||||
case 'image':
|
||||
handlePickImage();
|
||||
break;
|
||||
@@ -1077,7 +1095,7 @@ export const useChatScreen = () => {
|
||||
default:
|
||||
setActivePanel('none');
|
||||
}
|
||||
}, [handlePickImage, handleTakePhoto]);
|
||||
}, [handlePickImage, handleTakePhoto, isGroupChat, otherUser, conversationId]);
|
||||
|
||||
// 插入表情
|
||||
const handleInsertEmoji = useCallback((emoji: string) => {
|
||||
|
||||
Reference in New Issue
Block a user