Files
frontend/src/screens/message/components/ChatScreen/ChatHeader.tsx

150 lines
4.9 KiB
TypeScript
Raw Normal View History

/**
*
*
*/
import React, { useMemo } from 'react';
import { View, TouchableOpacity, StyleSheet } from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context';
import { MaterialCommunityIcons } from '@expo/vector-icons';
import { Avatar, Text } from '../../../../components/common';
import { colors, spacing } from '../../../../theme';
import { chatScreenStyles as baseStyles } from './styles';
import { useResponsive, useBreakpointGTE } from '../../../../hooks/useResponsive';
import { ChatHeaderProps } from './types';
export const ChatHeader: React.FC<ChatHeaderProps> = ({
isGroupChat,
groupInfo,
otherUser,
routeGroupName,
typingHint,
onBack,
onTitlePress,
onMorePress,
2026-03-16 17:47:10 +08:00
onGroupInfoPress,
isWideScreen: propIsWideScreen,
}) => {
// 响应式布局
const { width } = useResponsive();
2026-03-16 17:47:10 +08:00
// 使用 768px 作为大屏幕和小屏幕的分界线
const isWideScreenHook = useBreakpointGTE('lg');
// 优先使用 props 传入的 isWideScreen否则使用 hook
const isWideScreen = propIsWideScreen !== undefined ? propIsWideScreen : isWideScreenHook;
// 合并样式
const styles = useMemo(() => {
return StyleSheet.create({
...baseStyles,
headerContainer: {
...baseStyles.headerContainer,
maxWidth: isWideScreen ? 1200 : undefined,
alignSelf: isWideScreen ? 'center' : undefined,
width: isWideScreen ? '100%' : undefined,
},
header: {
...baseStyles.header,
paddingHorizontal: isWideScreen ? spacing.xl : spacing.md,
},
headerName: {
...baseStyles.headerName,
fontSize: isWideScreen ? 19 : 17,
},
memberCount: {
...baseStyles.memberCount,
fontSize: isWideScreen ? 14 : 13,
},
typingHint: {
...baseStyles.typingHint,
fontSize: isWideScreen ? 13 : 12,
},
});
}, [isWideScreen]);
// 获取显示标题
const getDisplayTitle = () => {
if (isGroupChat) {
return routeGroupName || groupInfo?.name || '群聊';
}
return otherUser?.nickname || '用户';
};
return (
<SafeAreaView edges={['top']} style={styles.headerContainer}>
<View style={styles.header}>
2026-03-16 17:47:10 +08:00
{/* 大屏幕(>= 768px时隐藏返回按钮 */}
{!isWideScreen ? (
<TouchableOpacity
style={styles.backButton}
onPress={onBack}
>
<MaterialCommunityIcons name="arrow-left" size={22} color={colors.primary.dark} />
</TouchableOpacity>
) : (
<View style={styles.backButton} />
)}
<View style={styles.headerCenter}>
<TouchableOpacity
style={styles.titleRow}
onPress={onTitlePress}
activeOpacity={0.75}
>
{isGroupChat ? (
<>
<View style={styles.titleLeading}>
<MaterialCommunityIcons name="account-group" size={20} color={colors.primary.main} />
</View>
<View style={styles.titleContent}>
<Text style={styles.headerName} numberOfLines={1}>{getDisplayTitle()}</Text>
<View style={styles.subtitleRow}>
<Text style={styles.memberCount}>{groupInfo?.member_count || 0}</Text>
{typingHint && (
<Text style={styles.typingHint} numberOfLines={1}>{typingHint}</Text>
)}
</View>
</View>
</>
) : (
<>
<Avatar
source={otherUser?.avatar || null}
size={32}
name={otherUser?.nickname || ''}
/>
<View style={styles.titleContent}>
<Text style={styles.headerName} numberOfLines={1}>{getDisplayTitle()}</Text>
{typingHint && (
<View style={styles.subtitleRow}>
<Text style={styles.typingHint} numberOfLines={1}>{typingHint}</Text>
</View>
)}
</View>
</>
)}
</TouchableOpacity>
</View>
2026-03-16 17:47:10 +08:00
{/* 大屏幕 + 群聊时显示群信息按钮,否则显示三点菜单 */}
{isWideScreen && isGroupChat && onGroupInfoPress ? (
<TouchableOpacity
style={styles.moreButton}
onPress={onGroupInfoPress}
>
<MaterialCommunityIcons name="dots-horizontal" size={22} color="#667085" />
</TouchableOpacity>
) : (
<TouchableOpacity
style={styles.moreButton}
onPress={onMorePress}
>
<MaterialCommunityIcons name="dots-horizontal" size={22} color="#667085" />
</TouchableOpacity>
)}
</View>
</SafeAreaView>
);
};
export default ChatHeader;