feat(CallFeature): implement call functionality and integrate WebSocket signaling
All checks were successful
Frontend CI / build-and-push-web (push) Successful in 5m2s
Frontend CI / ota-android (push) Successful in 11m28s
Frontend CI / build-android-apk (push) Successful in 1h0m58s

- Updated app.json to include microphone permissions and background audio support.
- Added call-related dependencies in package.json and package-lock.json.
- Enhanced ChatScreen to initiate calls and handle call actions.
- Introduced call components in the layout for incoming call handling.
- Expanded WebSocket service to manage call signaling messages and events.
- Refactored authStore to initialize call state on user authentication.
This commit is contained in:
lafay
2026-03-27 17:12:19 +08:00
parent db7885086f
commit b19a2ced6f
18 changed files with 2086 additions and 18 deletions

View File

@@ -35,7 +35,7 @@ import { SafeAreaView, useSafeAreaInsets } from 'react-native-safe-area-context'
import { Text, ImageGallery, ImageGridItem } from '../../components/common';
import { useAppColors } from '../../theme';
import * as hrefs from '../../navigation/hrefs';
import { messageManager } from '../../stores';
import { messageManager, callStore } from '../../stores';
import { useBreakpointGTE } from '../../hooks/useResponsive';
import {
useChatScreen,
@@ -423,6 +423,15 @@ 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,6 +23,7 @@ export const ChatHeader: React.FC<ChatHeaderProps> = ({
onMorePress,
onGroupInfoPress,
isWideScreen: propIsWideScreen,
onCallPress,
}) => {
const colors = useAppColors();
const baseStyles = useChatScreenStyles();
@@ -124,13 +125,30 @@ 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

@@ -114,11 +114,22 @@ export function createChatScreenStyles(colors: AppColors) {
alignItems: 'center',
justifyContent: 'center',
borderRadius: 19,
backgroundColor: colors.chat.surfaceRaised,
borderWidth: 1,
borderColor: colors.chat.borderLight,
backgroundColor: 'transparent',
},
headerActions: {
flexDirection: 'row',
alignItems: 'center',
gap: spacing.xs,
},
callButton: {
width: 38,
height: 38,
alignItems: 'center',
justifyContent: 'center',
borderRadius: 19,
backgroundColor: `${colors.primary.main}12`,
},
// 消息列表
messageListContainer: {
flex: 1,

View File

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