150 lines
4.9 KiB
TypeScript
150 lines
4.9 KiB
TypeScript
/**
|
||
* 聊天头部组件
|
||
* 支持响应式布局(宽屏下显示更多信息)
|
||
*/
|
||
|
||
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,
|
||
onGroupInfoPress,
|
||
isWideScreen: propIsWideScreen,
|
||
}) => {
|
||
// 响应式布局
|
||
const { width } = useResponsive();
|
||
// 使用 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}>
|
||
{/* 大屏幕(>= 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>
|
||
|
||
{/* 大屏幕 + 群聊时显示群信息按钮,否则显示三点菜单 */}
|
||
{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;
|