feat(CallScreen): enhance video call functionality and UI updates
Some checks failed
Frontend CI / build-and-push-web (push) Successful in 3m13s
Frontend CI / build-android-apk (push) Has been cancelled
Frontend CI / ota-android (push) Has been cancelled

- 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:
lafay
2026-03-28 00:56:52 +08:00
parent b19a2ced6f
commit f6176c945b
11 changed files with 790 additions and 268 deletions

View File

@@ -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}
/>
{/* 消息列表 */}

View File

@@ -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>

View File

@@ -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' },

View File

@@ -179,8 +179,6 @@ export interface ChatHeaderProps {
onGroupInfoPress?: () => void;
/** 是否为大屏幕模式 */
isWideScreen?: boolean;
/** 拨打电话回调(仅私聊有效) */
onCallPress?: () => void;
}
// 回复预览 Props

View File

@@ -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) => {