- Adjusted tab bar dimensions and margins in TabsLayout for better visual consistency. - Streamlined ImageGallery by removing loading states and optimizing image transition handling. - Updated ChatScreen to utilize SafeAreaView for improved layout on different devices. - Enhanced GroupInfoScreen and PrivateChatInfoScreen with a consistent page header layout, including back navigation. - Refactored ChatHeader to simplify structure and improve maintainability.
138 lines
4.5 KiB
TypeScript
138 lines
4.5 KiB
TypeScript
/**
|
||
* 聊天头部组件
|
||
* 支持响应式布局(宽屏下显示更多信息)
|
||
*/
|
||
|
||
import React, { useMemo } from 'react';
|
||
import { View, TouchableOpacity, StyleSheet } from 'react-native';
|
||
import { MaterialCommunityIcons } from '@expo/vector-icons';
|
||
import { Avatar, Text, AppBackButton } from '../../../../components/common';
|
||
import { colors, spacing } from '../../../../theme';
|
||
import { chatScreenStyles as baseStyles } from './styles';
|
||
import { 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,
|
||
}) => {
|
||
// 响应式布局
|
||
// 使用 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 (
|
||
<View style={styles.headerContainer}>
|
||
<View style={styles.header}>
|
||
<AppBackButton style={styles.backButton} onPress={onBack} />
|
||
|
||
<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={colors.text.primary} />
|
||
</TouchableOpacity>
|
||
) : (
|
||
<TouchableOpacity
|
||
style={styles.moreButton}
|
||
onPress={onMorePress}
|
||
>
|
||
<MaterialCommunityIcons name="dots-horizontal" size={22} color={colors.text.primary} />
|
||
</TouchableOpacity>
|
||
)}
|
||
</View>
|
||
</View>
|
||
);
|
||
};
|
||
|
||
export default ChatHeader;
|